Reputation: 119
For the below code
public class T<T> {
public String toString() {
return "Generic Types!";
}
public void run(T var) {
Integer repeatCount = 12_57;
System.out.println("debug: " + repeatCount + ", " + var.toString());
}
public static void main(String[] args) {
System.out.println("Hello, World!");
T<String> t = new T();
t.run(t);
}
}
The line public class T<T>
gives a warning The type parameter T is hiding the type T<T>
.
The line T<String> t = new T()
gives a error cannot make a static reference to non-static type T
.
It works fine with below output, if I change public class T<T>
to public class T<K>
. But I don't understand the reason.
output :
Hello, World!
debug: 1257, Generic Types!
I am new to the concepts of Generics , can someone please explain what is wrong with the above code ?
Upvotes: 1
Views: 308
Reputation: 274835
Here you declared a class T
, with a generic parameter T
. In this class, T
can now refer to two things:
Indicated by the two arrows here:
public class T<T>
^ ^
1 2
So when you write T
inside this class, how does Java know which meaning do you mean? 1 and 2 are both types! According to the rules of the language, meaning 2 is favoured.
If you are interested in which rule it is, it's in §6.4.1 of the JLS.
A declaration d of a type named n shadows the declarations of any other types named n that are in scope at the point where d occurs throughout the scope of d.
The second T
is in the scope of the first T
, so shadows it.
All your references to T
inside the class refers to the second T
, the generic parameter. For why the generic parameter T
is non-static, see Static method in a generic class? or Generics - Why are Class type variables not valid in static contexts?
Though, even if the generic parameter T
were static, it is not generic, and you would not be able to parameterise it as in T<String>
(in fact you can't make any generic parameter generic).
Other than renaming the class name (first T
), you can also refer to it using the fully qualified name:
yourpackagename.T
Upvotes: 3
Reputation: 1789
EDIT: You're creating a class T
that has type T
as a generic parameter. These two T
's are not the same, and the generic parameter T
is hiding class T
within that class (i.e. when you use T
within the class, it will use the generic parameter T
, and not class T
). To solve this problem, rename either the generic parameter or the class.
You've created a class The basic idea of a generic parameter is to make your class usable for some type that you can pass in when using that class. An example is:T
that has type T
as a generic argument, which has type T
as a generic argumument, which has T
as a... You can probably see why the compiler has issues with this.
public class MyObject<T> {
private final T object;
public MyObject(T object) {
this.object = object;
}
public T getObject() {
return this.object;
}
}
Which you can use as:
MyObject<String> myStringObject = new MyObject<String>("Some string");
String myStringObject2 = myStringObject.getObject();
The upside here is mainly that you can define what T
is in the bottom code block, so you don't have to just make MyObject
and all its methods work with Object
and insert casts to make the type system accept this (without getting compiler errors when you make a mistake in that process).
Upvotes: 1