Reputation: 180934
I'm usually a C# developer, new to Java and I'm trying to setup some code using Generics. My Demo code looks like this:
// Main.java
public static void main(String[] args) {
MyBase my = getMeStuff();
System.out.println(my.getSomething());
}
private static <T extends MyBase> T getMeStuff(){
return new MyDerived(123);
}
// MyBase/MyDerived.java
public class MyBase {
private final int something;
protected MyBase(int something) { this.something = something; }
public int getSomething() { return something; }
}
public class MyDerived extends MyBase {
public MyDerived(int something) { super(something); }
}
This fails to compile:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Type mismatch: cannot convert from x.MyDerived to T
at x.Main.getMeStuff(Main.java:14)
at x.Main.main(Main.java:9)
As said, I'm usually a C# Developer, so the code looks good at first glance. I can "resolve" this error by changing getMeStuff to add a cast to (T), but is that cast really necessary? It smells a bit, like I've forgotten something?
Upvotes: 4
Views: 1896
Reputation: 16190
Java Generics want to help you achieve type safety.
Let me use a parallel: Let us assume you wrote <T extends MyUIControl>
and at one point you use MyButton
s with it and somewhere else MyPanel
s - which cannot be cast safely.
The compiler recognized such a situation in the code.
Upvotes: 1
Reputation: 4134
The problem is that the return type can be anything that derives from MyBase and you've specifically typed it to MyDerived, which doesn't even work in C# without a cast. The caller could have specified SomeOtherDerived instead, which also derives from MyBase but has nothing to do with MyDerived.
public class MyBase{}
public class MyDerived extends MyBase{}
public class SomeOtherDerived extends MyBase{}
public static <T extends MyBase> T getAnything(){ return (T)new MyDerived(); }
public static void main(String[] args) {
SomeOtherDerived instance = getAnything(); //This is legal and bad
}
It's also important to note that, even with a cast, this is a very bad thing and can easily result in runtime exceptions when called with any type that's not explicitly provided. This also goes against the concept of generics by nailing down very specific types in what should be a generalized situation.
Upvotes: 5