Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Wildcards in Class declaration

 
Santiago Bravo
Ranch Hand
Posts: 226
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

Why cant wildcards be used in class declarations?



The above code gives a compiler error. If I try the code below i get an error which says

WildcardsTest.java:11: non-static class Integer cannot be referenced from a static context
Set<Integer> d = new HashSet<Integer>();
^
WildcardsTest.java:11: non-static class Integer cannot be referenced from a static context
Set<Integer> d = new HashSet<Integer>();




Thanks
 
victor kamat
Ranch Hand
Posts: 247
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is because Integer is a final class and cannot be sub-classed.
 
Santiago Bravo
Ranch Hand
Posts: 226
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi

I get the same error if I try with ? extends Number or even ? extends Object

Is this mentioned in the JLS somewhere?

or can anyone explain why these errors occur?


Thanks
 
Markus Klein
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
you can't use wildcards in class declarations.

perhaps this can help you to understand why wildcards are not allowed in class declarations:

http://www.coderanch.com/t/269984/java-programmer-SCJP/certification/extends-Animal-VS-extends-Animal
[ November 27, 2008: Message edited by: Markus Klein ]
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1.Firstly, wild cards are not allowed in generic class declarations.

2. Your second error is also new to me at least. But i found the following writeup in the sun generics tutorial. Hope this helps.

A Generic Class is Shared by all its Invocations
What does the following code fragment print?
List <String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());

You might be tempted to say false, but you�d be wrong. It prints true, because all instances of a generic class have the same run-time class, regardless of their actual type parameters.
Indeed, what makes a class generic is the fact that it has the same behavior for all of its possible type parameters; the same class can be viewed as having many different types.
As consequence, the static variables and methods of a class are also shared among all the instances. That is why it is illegal to refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or initializer of a static
variable.


The link to the tutorial is link

Honestly speaking, i am still trying to figure out the inner workings of the above explanation.
:roll:
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey maybe i am being a bit lazy but can the experts please clarify this with an elaborate example. Henry, Marc, Jesper, Bert or anyone.
 
Ankit Garg
Sheriff
Posts: 9510
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well harvider what you told was the case where you create your own generic classes. Then you cannot use the generic type in static context. Eg



This is the same reason Santiago is facing problems. Santiago you have used the name <Integer> as the type of your class. You have to use an identifier there. like WildcardsTest<T>. But by using Integer there, you are declaring it as your own type. So now when you right Integer, it means the typed Integer of your class. If you change your code to

Set<String> d = new HashSet<String>();

Then it will compile fine even if String is a final class. So basically you will have to change your class to

public class WildcardsTest<Identifier>

Then you will not get any errors...

[Edit: corrected the spelling of Harvinder ]
[ November 28, 2008: Message edited by: Ankit Garg ]
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ankit, I got till there..... but i was looking for little bit more insight as to what possible errors the compiler takes care of by putting in that restriction.
Anyways, I'll get back once i find something....
 
Ankit Garg
Sheriff
Posts: 9510
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
harvinder if you declare a class like this

class MyClass<? extends Integer>

then what is the use of it. I mean what is the use of the type. The typing information is useless. You cannot use it in any way whatsoever. Let's take an example



Now you can use the T in your class. But if we would have used ?, then what??



So basically if you were allowed to declare a class with wildcards, then the type of the class will be useless. I hope that this will clear it a bit.

Anyways this is my view on this. Let's see if any of the moderators have to say something on this...
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot for the explanation Ankit
My doubt was regarding the second part.
Let me explain my query a little more clearly.


Firstly, i was confused about the generic type named as "Integer".
Here, "Integer" is identified by compiler as another type and not the Integer class. So it is clear to me now.

So had i used <T> or <X> instead of <Integer> i would have got a compiler error.

Now the generics tutorial gives the reason as follows:

Indeed, what makes a class generic is the fact that it has the same behavior for all of its possible type parameters; the same class can be viewed as having many different types.
As consequence, the static variables and methods of a class are also shared among all the instances. That is why it is illegal to refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or initializer of a static
variable.


So, since a static variable and method is shared across all the instances hence the Class's Generic Type parameter is prohibited from being used in there.

But if you say,



then it is not a compile time error.

I hope i have understood the reason which is as follows:

if i say,



Now on instantiating an object of type Generic as :

Generic <String> gen1 = new Generic<String>();

would replace all the T's with "String".
Similarly, if i said :

Generic <Integer> gen2 = new Generic<Integer>();

would replace all the T's with "Integer".

If i were using *gen1* and *gen2* in the same code block then the compiler would be at a loss as to which <GENERIC TYPE> do i replace the <T>'s in static methods of class Generic: <Integer> or <String> because static means only single method or variable is shared by all the instances.

Therefore, the compiler does not allow it at all.

Please correct me if i am wrong.
 
Santiago Bravo
Ranch Hand
Posts: 226
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Ankit and Harvinder for your explanations
 
Ankit Garg
Sheriff
Posts: 9510
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
harvinder you got it right!
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic