Reputation: 1256
I have some generic interface
interface Animal<T> {}
And I have a subclass that I only want to extend Animal<Object>
. So I did
class Pet implements Animal<Object>
I have some method that should only compile if both parameters have matching type:
<T> T apply(T source, Animal<T> target)
I was wondering, why does this compile
String source = "test";
Pet pet = new Pet();
apply(source, pet);
It seems that since the type of source is String
, and the type of pet is Pet
which implements Animal<Object>
, there should be a type mismatch here and cause a compiler error, but I found that this compiles and was wondering if someone could explain why.
Upvotes: 1
Views: 255
Reputation:
Because you are calling method apply
without explicitly specifying a type between angle brackets, you are relying on the compiler to infer one for you. If you try assigning the result to a variable of some type, say String
, the compiler will tell you which type it has inferred for example:
String r = Animal.apply(source, pet);
Type mismatch: Cannot convert from Object to String
In which case you know that T
was inferred as Object
. If you pass two String
instances, T
will be inferred as String
:
String r = Animal.apply("A", "B");
Note that Java allows you to explicitly specify the type argument for a generic method (called type witness). This is useful to check assumptions you might have about how the type parameter will be bound:
Animal.<Object>apply(source, pet);
More information: Java Tutorial
Upvotes: 1
Reputation: 16
You are casting binding the generic in
class Pet implements Animal<Object>
to the object class. Everything in java is a descendant of the object class so the compiler will have no issue here. When you declare that your class implements Animal you need to bind it to a specific type to restrict what it will accept for parameters.
Upvotes: 0
Reputation: 102923
String is also an Object (all non-primitives are also Objects). so, the apply method here works fine, and binds T to object, at which point everything lines up. It's like having a method: foo(Object x)
, and calling it as foo("")
which is perfectly fine.
Upvotes: 0