I have such code:
interface A<T extends A> {
T method();
}
class AIml<T extends A> implements A<T> {
@Override
public T method() {
return (T) this;
}
}
My questin is:
Why we can't write return this;
in method implementation.
As I underood after generic erasing this code should become like this.
interface A {
A method();
}
class AIml implements A {
@Override
public A method() {
return (A)this;
}
}
And class casting becomes redundant.
So is it compiler not smart enough here? Or I miss something and ClassCastException can happens here?
When you declare generic type <T extends A>
it means that you want to accept some type which explicitly or implicitly extends/implements A
type. Nothing more, nothing less.
You can have many types which fulfill these requirements. Lets say you have
class Foo implements A<Foo>{...}
or even
class Bar implement A<Foo>{...} //<-- generic type doesn't need to be Bar,
// *some* other type which extends A is OK
Now when you are declaring T
as
class AIml<T extends A> implements A<T> {...}
you are agreeing to same conditions as before, so it is legal to have AIml<Foo>
. Problem is that Foo
isn't really related to AIml
so you can't return this
as its representation.
Or I miss something and ClassCastException can happens here?
While you are right that
public T method() {
return (T) this;
}
will be erased to
public T method() {
return (A) this;
}
it will allow you to only use it safely with code like
AIml<Foo> aimp = new AIml<Foo>();
A methodResult = aimp.method();
but you will get ClassCastException
if you will want to hold result of method()
in reference variable of same type as T
AIml<Foo> aimp = new AIml();
Foo methodResult = aimp.method();
//^^^-- since method() returned AIml, not Foo