How Class Level Generics Works

Consider the following code from Java Puzzlers

class Gloam<T>{ String glom(Collection<?> objs ) { System.out.println("collection"); String result = ""; for (Object o : objs ){ result += o; } return result; } int glom(List <Integer> ints ) { System.out.println("List"); int result = 0; for ( int i : ints ) result += i ; return result; } public static void main(String[] args) { List<String> strings = Arrays.asList("1", "2", "3"); System.out.println(new Gloam().glom(strings)); } } 

When I run this program, it gives an exception to the cast class, but if I provide a general argument for the Gloam class in the main method, it works fine.

 public static void main(String[] args) { List<String> strings = Arrays.asList("1", "2", "3"); System.out.println(new Gloam<Date>().glom(strings)); } 

I don’t understand how generic works in a class type parameter?

+4
source share
3 answers

In the absence of a common type passed to the constructor, all types are erased, and the compiler is presented with these options

 String glom ( Collection ); int glom ( List ); 

The type is also removed from the strings variable defined in main , therefore its type is List .

Since List more specific than Collection , it selects int glom ( List ) .

Now, if you specify a general parameter, type erasing does not occur, and the compiler knows that it cannot match int glom ( List<Integer> ) to List<String> , so it returns to String glom ( Collection<?> )

+9
source

Once you provide a type parameter, all typical typifications for the entire class will disappear in the eyes of the compiler. The class essentially becomes:

 class Gloam<T> { String glom(Collection objs) { System.out.println("collection"); String result = ""; for (Object o : objs) { result += o; } return result; } int glom(List ints) { System.out.println("List"); int result = 0; for (int i : ints) result += i; return result; } public static void main(String[] args) { List strings = Arrays.asList("1", "2", "3"); System.out.println(new Gloam().glom(strings)); } } 

So, now the compiler will choose the int glom(List ints) , as this is the most specific override that corresponds to the call. But it will also lead to class exclusion. When you provide a generic parameter, the generic files are saved, and the redefinition of String glom(Collection<?> objs ) corresponds to the call (which passes List<String> ), whereas int glom(List <Integer> ints ) does not match because String not Integer

+2
source

You can use generic to distinguish a method in Java. The JVM does not see this type, however, provided that the argument or return type is different, it will still compile in the Sun / Oracle compiler. This does not compile for the IBM / eclipse compiler.

This shows what you want at the byte code level.

0
source

Source: https://habr.com/ru/post/1492332/


All Articles