2

I have a generic class with parameter that extends Paint. I really don't understand why I should cast it manually to T in first constructor. What am i doing wrong? Or this is the case when the compiler can't determine a safe cast itself?

public class XYPlot <T extends Paint> extends AbsPlot implements XYChartElement { public XYPlot(AbsSeries series){ setUp(series, (T) new Paint(DEFAULT_PAINT));//TODO } public XYPlot(AbsSeries series, T paint){ setUp(series, paint); } private void setUp(AbsSeries series, T paint){ if(series == null) throw new NullPointerException("Series is null"); setSeries(series); setPaint(paint); } 
0

2 Answers 2

5

I really don't understand why I should cast it manually to T in first constructor.

You shouldn't - you shouldn't be creating an instance of just Paint in the first place. That Paint won't be an instance of T, unless T is exactly Paint. A generic class which only works properly for a single type argument shouldn't be generic in the first place.

If you need an instance of T on construction, you'll either need the caller to pass one in, or take a Class<T> so that you can look through the constructors using reflection and call an appropriate one.

Let's look at a simpler version of what you're doing, and hopefully you'll see why it's wrong:

public class Wrapper<T extends Object> { private final T value; public Wrapper() { value = (T) new Object(); } public T getValue() { return value; } } 

Here we're using Object instead of Paint - but otherwise, it's basically similar.

Now if we call it:

Wrapper<String> wrapper = new Wrapper<String>(); String text = wrapper.getValue(); 

... what would you expect that to do?

Fundamentally it's not clear why you have made your class generic in the first place - but the approach you're taking is inherently flawed.

Sign up to request clarification or add additional context in comments.

2 Comments

Ok, now I understand the problem. So I decided to make child classes to create default values like this. Is that a good idea? public abstract class Wrapper<T extends Object> { private final T value; public Wrapper() { value = getDefaultValue(); } public abstract T getDefaultValue() public T getValue() { return value; } }
@KorniltsevAnatoly: Well, that's okay so long as you have a subclass for each type argument... otherwise it becomes similarly tricky. If you're creating subclasses anyway, why not make the subclass constructor pass the value to the superclass constructor, rather than using a virtual method?
0
setUp(series, (T) new Paint(DEFAULT_PAINT)); 

That is only safe if your actual argument for T is Paint itself. That would end up in a CCE if the type argument is some subclass of Paint instead.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.