1

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 ?

Sourabh
  • 119
  • 1
  • 8
  • 1
    Can you explain if (and if so why) you *want* to use this confusing naming? Perhaps there's some underlying confusion we could clear up! Typically a class name is descriptive and a generic parameter is an initial for something, like `T` for Type, `E` for Element, `K/V` for Key/Value, etc. Why do you want to name your class `T`? – Mark Peters Jan 14 '21 at 03:42
  • This is an experimental class I am using to learn about Generics @Mark and I do understand that naming convention is not right. – Sourabh Jan 14 '21 at 03:46

2 Answers2

3

Here you declared a class T, with a generic parameter T. In this class, T can now refer to two things:

  1. the generic class
  2. the generic parameter

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
Sweeper
  • 213,210
  • 22
  • 193
  • 313
1

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 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. 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:

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).

Pieter12345
  • 1,713
  • 1
  • 11
  • 18
  • Why does the compiler say "cannot make a static reference to non-static type T" ? The error message seems wrong. – Sourabh Jan 14 '21 at 03:25
  • Oh, I see that I were wrong on the cause of this exception. You are using the same class name as generic type name, leading to the generic type 'hiding' the class name itself. So when you use `new T()`, you are effectively trying to create a new instance of the generic type, which is not something that you can do. What you should do is rename either the class or the generic type. – Pieter12345 Jan 14 '21 at 03:28