• Post Reply Bookmark Topic Watch Topic
  • New Topic

Upper Bounded Wildcard on Method - OCP  RSS feed

 
Ranch Hand
Posts: 140
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

I cannot understand at all the following example from OCP page 124.

We have that :



and the example is as follows:




The book mentions that

method3() does not compile. <B extends A> says that you want to use B as a type
parameter just for this method and that it needs to extend the A class. Coincidentally, B
is also the name of a class. It isn’t a coincidence. It’s an evil trick. Within the scope of the
method, B can represent classes A, B, or C, because all extend the A class. Since B no longer
refers to the B class in the method, you can’t instantiate it.



I cannot understand why the Cannot instantiate the type B means. What would the correct way be to write this?

Thanks..
Ioanna


 
Saloon Keeper
Posts: 2111
44
Firefox Browser IntelliJ IDE Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
new B();

How can the compiler be sure that B has an accessible constructor with zero arguments?
 
Ioanna Katsanou
Ranch Hand
Posts: 140
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I write instead this:



this does not throw a compiler error. It compiles just fine. In the same manner how can the compiler know that B has an accessible constructor with zero arguments?
 
Paweł Baczyński
Saloon Keeper
Posts: 2111
44
Firefox Browser IntelliJ IDE Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If this compiles it means you have a class named B in a place accessible to the compiler. If the compiler can access the class then it can validate whether the class has a proper constructor.

In this example B is not a class name. It is a generic parameter name. This <B extends A> means any type (further referenced by the name B) that is a subtype of A (or A itself).

If I had a class (I am assuming A is a class) how would you expect your new B() to work with type C?
 
Ioanna Katsanou
Ranch Hand
Posts: 140
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So,

to get this straight:

If for example I had a class B



In the following method:


This compiles. Because I have <T> a generic type, return type: B where B is a class, and input List < B > of objects B.
I return new B(); an instance of object B.


Instead in this example:



Here I get a compiler error because  is now a generic type. So everywhere I see the "B" it is referred to the generic type and not the class.
return type of method : B -> refers to generic type now.
List< B > -> refers again to generic type and not the class B.

and return new B(); ->now it is trying to return a generic type and not class B. That is why we get a compiler error.


Is this correct?
 
Java Cowboy
Sheriff
Posts: 16078
88
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In the two examples in your last post, the B means two completely different things in both examples. The fact that they are both named "B" only makes things confusing.

In the first example, B is a concrete class. Ofcourse you can do "new B()" in that case, you're just creating an instance of class B.

In the second example, B is a type parameter of method3. You cannot do "new B()" when B is a type parameter. The reason why you cannot do this has to do with the way that generics are implemented in the Java compiler and JVM; using type erasure. This means that in Java, generics are purely a compile-time feature. The compiler uses generics for more type-safety, but in the actual byte code, the information about the generics is not present anymore. This means that the information about the generic types is not available to the JVM at runtime - the type parameter "B" doesn't exist anymore at runtime. You cannot do "new B()" where B is a type parameter, because at runtime there is no such thing as the type parameter "B". The JVM wouldn't know what type of object needs to be instantiated.
 
Bartender
Posts: 1843
10
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Ioanna - you seem to have grasped the concept :-)


This is the sort of question that I really hate in these exams.
Contriving a confusing example which no programmer worth their salt would ever conceive of in 'real' code, and expecting you to interpret it 'correctly'
This is why we have naming conventions/standards.

For clarity you wanted to re-write it so that T represented the Generic type and B represented the class (and thus avoid the confusing name collision), I believe the result should be:



EDIT: You have to cast the new B() to type T to get it to compile.
 
Ioanna Katsanou
Ranch Hand
Posts: 140
1
Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you so much for your answers !
One last question:

When using generics in method, according to Java doc (https://docs.oracle.com/javase/tutorial/java/generics/methods.html)

the syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type



Do I have to declare the type parameters if I use generics on return type or inside the method signature? Or Both?

For example I tried out the following combinations:



According to these examples, I have to add <T> if I use it somewhere in the method( either in the return type or in the method signature.)
Is that correct?

Thanks again,
ioanna
 
Saloon Keeper
Posts: 8109
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Type parameters are just like regular variables. If you want to use them, you have to declare them somewhere first.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!