Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The type parameter G is hiding the type G

Tags:

java

generics

public class MyGenericClass< G> {


    public <G> G genericMethod1(G g){
        System.out.println(g.toString());
        return g;

    }

    public <X> G genericMethod2(G g) {
        System.out.println(g.toString());
        return g;
    }

    public <X> X genericMethod3(G g) {
        System.out.println(g.toString());
        Integer i = new Integer(100);
        return (X) i;       
    }


    public static void main(String... cmdarg) {

        MyGenericClass<Employee> gemp = new MyGenericClass<Employee>();
        Employee e1 = new Employee();
        e1.setName("My Name");


        String resultOfMethod3 = gemp.genericMethod3(e1);
        System.out.println(resultOfMethod3);                            

    }


}

in genericMethod1: I get the compiler warning as "The type parameter G is hiding the type G".

Question: Which G is hidden by this G? What's the actual meaning of this?

genericMethod2 doesn't show any errors/warnings.

Question: I thought it should not compile. why is two different types allowed in same method signature? What can be typical real time example to compare with G and X?

In genericMethod3: I'm intentionally returning an Integer object and in the main method i'm trying to assign the result to a String. As expected: I got the ClassCastException.

Question: Isn't the original purpose of having generics to avoid ClassCastExceptions? Why did the compiler allow it? Is this a bug in the design of Generics?

like image 937
Jinnah Avatar asked Oct 24 '25 14:10

Jinnah


2 Answers

Generics can be used at class level and at method level:

  • public class MyClass<T>: T is available for all instance members (i.e. non-static) of the class (fields, methods, inner classes...)
  • public (static) <U> ReturnType myMethod(..) {...}: U is available for the method only

You're mixing them.

With public <G> G genericMethod1(G g), this <G> generic is hiding the class' one since they have the same name, so the latter isn't available in the method anymore. If you want to use the class' generic, don't specify it at the method level: public G genericMethod1(G g).

With public <X> G genericMethod2(G g), you're defining a generic <X> that isn't used: only the class' generic G is used.

With public <X> X genericMethod3(G g), you're defining a generic <X> that is used for the return value of the method. In the method body, you're casting an int to X but you can't be sure that X is a super type of int. Technically, this can be done with <X super Integer>, but I'm not sure this is actually what you're looking for.

like image 60
sp00m Avatar answered Oct 27 '25 06:10

sp00m


public class MyGenericClass< G> {


    public <G> G genericMethod1(G g){
        System.out.println(g.toString());
        return g;

    }

You have two different <G> variables here, one on class level and one on method level. This is roughly equivalent to having a field and a local variable of the same name. The local variable would "win" in that case, just as the method level <G> would override the class-level one. Since this is a common cause of errors, IDEs warn you of this.

Method 2 doesn't redefine <G>, so it generates no warning.

like image 33
Sean Patrick Floyd Avatar answered Oct 27 '25 04:10

Sean Patrick Floyd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!