views:

95

answers:

2

What is the difference between passing in generic parameter some generic class with and without his generic parameter?

Example:

Simple Generic class:

public class Foo<T> { /*...*/ }

Simple class that extend simple generic class setting the generic parameter to some irrelevant type:

public class FooFoo extends Foo<Type1> { /*...*/ }

Another generic class

public class Bar<T> extends FooFoo { /*...*/ }

Our base class that as generic parameter need something that extends class Foo

public class TestFooClass<T extends Foo<?>> { /*...*/ }

And the question what is the deference between this two parameters

public class BarTestOne extends TestFooClass<Bar> { /*...*/ }

public class BarTestTwo extends TestFooClass<Bar<?>> { /*...*/ }

Problem

Class<T> class = (Class<T>) ((Foo)getClass().getGenericSuperclass()).getActualTypeArguments()[0];

In the first case code works in the second doesn't.

A: 

Bar means Bar<Object> and Bar<?> doesn't. For example, if you have a List, you can add to it, if you have a List<?> you can't, because the compiler doesn't know if your object is compatible with the "actual generic type" of the object.

As for the reflection code, I don't know. It says getClass(), which depends on the object you call it on; in this case the object is obviously this... From where is this code called?

Silly Freak
Yes, but in this case the Bar<Object> or Bar<?> have the same impact.
Vash
Actually Bar is the raw supertype of Bar<?> and Bar<Object> is a subtype of Bar<?>.
Timo Westkämper
+2  A: 

It looks like you are trying to determine the actual type that the TestFooClass is parameterized with?

In that context, the difference between using generic class with and without its generic parameter is that getActualTypeArguments()[0] will:

  1. In the first case provide an instance of Class representing the raw type
  2. In the second case provide an instance of ParameterizedType (thus one may get ClassCastException). If you call getRawType() on that ParameterizedType, you will get Class representing the raw type.

This:

BarTestOne one = new BarTestOne();
BarTestTwo two = new BarTestTwo();

Class<?> clazz1 = (Class<?>) ((ParameterizedType) one.getClass().getGenericSuperclass()).getActualTypeArguments()[0];       
Class<?> clazz2 = (Class<?>) ((ParameterizedType) ((ParameterizedType) two.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).getRawType();

System.out.println(clazz1.equals(clazz2));

This will return true.

Alas, any deeper answer is beyond my knowledge of generics.

finrod