How does erasing styles work under a template in java?

As mentioned in the javadoc,

Replace all type parameters in generic types with their bounds or an object if the type parameters are not constrained. Thus, the resulting bytecode contains only regular classes, interfaces, and methods.

Insert a cast type if necessary to maintain type safety.

I understand the above two points that are handled using javac

for type parameters such as T

and <K, V>

.

But for the wild cards below,

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}    

public void sumOfNumbers(List<? extends Number> numbers){
        double d = 0.0;
        for(Number n: numbers){
            d += n.doubleValue();
        }
        System.out.println(d);
    }

      

In the case of wild cards

1)

How javac

does one deal with these wildcards? Does he replace something?

2)

How are the types of throws done?

+3


source to share


3 answers


?

is replaced by Object

(since it has no boundaries) - not that useful.
At build time, the compiler verifies that you are only calling the object's behavior.

? extends Number

is replaced by its grade Number

.
At build time, the compiler checks that you are passing only Number

or any of its subtypes as an argument.

Casting . At build time, the compiler verifies that you are only calling behavior that is valid for Number

.



T

is replaced by whatever type you provide for the class type parameter.
At build time, the compiler checks that you only pass the type of T

whatever was as an argument (uses it T

as a parameter in your method).

?

and T

have different uses.
Think T

to create a generic type (classes, interfaces), which can then be categorized as any type.

Think of it ?

as a way to restrict what types you can legally call a method at compile time.

+1


source


At compile time, decals differ only from named type parameters, as the compiler will try to enforce these types using the same name.

But if you look at this source code:

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void foo(List<? extends Number> first, List<? extends Number> second) {
        Number n = first.get( 0 );
        Number m = second.get( 0 );
        List<Number> third = new ArrayList<Number>();
        third.add( n );
        third.add( m );
        System.out.println( third );
    }  

    public static <T extends Number> void bar(List<T> first, List<T> second) {
        T n = first.get( 0 );
        T m = second.get( 0 );
        List<T> third = new ArrayList<T>();
        third.add( n );
        third.add( m );
        System.out.println( third );
    }
}

      

... and decompiled bytecode:



Compiled from "Test.java"
public class Test {
  public Test();
    Code:

  public static void foo(java.util.List<? extends java.lang.Number>, java.util.L
ist<? extends java.lang.Number>);
    Code:
       0: aload_0
       1: iconst_0
       2: invokeinterface #2,  2            // InterfaceMethod java/util/List.ge
t:(I)Ljava/lang/Object;
       7: checkcast     #3                  // class java/lang/Number
      10: astore_2
      11: aload_1
      12: iconst_0
      13: invokeinterface #2,  2            // InterfaceMethod java/util/List.ge
t:(I)Ljava/lang/Object;
      18: checkcast     #3                  // class java/lang/Number
      21: astore_3
      22: new           #4                  // class java/util/ArrayList
      25: dup
      26: invokespecial #5                  // Method java/util/ArrayList."<init
>":()V
      29: astore        4
      31: aload         4
      33: aload_2
      34: invokeinterface #6,  2            // InterfaceMethod java/util/List.ad
d:(Ljava/lang/Object;)Z
      39: pop
      40: aload         4
      42: aload_3
      43: invokeinterface #6,  2            // InterfaceMethod java/util/List.ad
d:(Ljava/lang/Object;)Z
      48: pop
      49: getstatic     #7                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      52: aload         4
      54: invokevirtual #8                  // Method java/io/PrintStream.printl
n:(Ljava/lang/Object;)V
      57: return

  public static <T extends java.lang.Number> void bar(java.util.List<T>, java.ut
il.List<T>);
    Code:
       0: aload_0
       1: iconst_0
       2: invokeinterface #2,  2            // InterfaceMethod java/util/List.ge
t:(I)Ljava/lang/Object;
       7: checkcast     #3                  // class java/lang/Number
      10: astore_2
      11: aload_1
      12: iconst_0
      13: invokeinterface #2,  2            // InterfaceMethod java/util/List.ge
t:(I)Ljava/lang/Object;
      18: checkcast     #3                  // class java/lang/Number
      21: astore_3
      22: new           #4                  // class java/util/ArrayList
      25: dup
      26: invokespecial #5                  // Method java/util/ArrayList."<init
>":()V
      29: astore        4
      31: aload         4
      33: aload_2
      34: invokeinterface #6,  2            // InterfaceMethod java/util/List.ad
d:(Ljava/lang/Object;)Z
      39: pop
      40: aload         4
      42: aload_3
      43: invokeinterface #6,  2            // InterfaceMethod java/util/List.ad
d:(Ljava/lang/Object;)Z
      48: pop
      49: getstatic     #7                  // Field java/lang/System.out:Ljava/
io/PrintStream;
      52: aload         4
      54: invokevirtual #8                  // Method java/io/PrintStream.printl
n:(Ljava/lang/Object;)V
      57: return
}

      

... you can see that the same opcode is checkcast #3

used in both methods, checking only that the values ​​obtained from the list can be translated to Number

, but not if they are of the same type.

And when you think about it, such a check will not be possible at all due to type erasure.

0


source


Can anyone try to answer the question above, how do wildcards get erased in restricted wildcards used in methods? I think the above answers don't solve the question. An example will help.

0


source







All Articles