有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!


共 (1) 个答案

  1. # 1 楼答案

    本教程在这里有些误导。它试图强调类型擦除,但它做得并不优雅

    生成的类的字节码如下所示。显然,这些信息并没有被丢弃

      Last modified 2 Mar 2020; size 332 bytes
      MD5 checksum e3b7faf33fd5666eae578bd516d0f903
      Compiled from "Test.java"
    public class Test<E extends java.lang.Object> extends java.lang.Object
      minor version: 0
      major version: 53
      flags: (0x0021) ACC_PUBLIC, ACC_SUPER
      this_class: #2                          // Test
      super_class: #3                         // java/lang/Object
      interfaces: 0, fields: 0, methods: 2, attributes: 2
    Constant pool:
       #1 = Methodref          #3.#15         // java/lang/Object."<init>":()V
       #2 = Class              #16            // Test
       #3 = Class              #17            // java/lang/Object
       #4 = Utf8               <init>
       #5 = Utf8               ()V
       #6 = Utf8               Code
       #7 = Utf8               LineNumberTable
       #8 = Utf8               setE
       #9 = Utf8               (Ljava/lang/Object;)V
      #10 = Utf8               Signature
      #11 = Utf8               (TE;)V
      #12 = Utf8               <E:Ljava/lang/Object;>Ljava/lang/Object;
      #13 = Utf8               SourceFile
      #14 = Utf8               Test.java
      #15 = NameAndType        #4:#5          // "<init>":()V
      #16 = Utf8               Test
      #17 = Utf8               java/lang/Object
    {
      public Test();
        descriptor: ()V
        flags: (0x0001) ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: return
          LineNumberTable:
            line 1: 0
    
      void setE(E);
        descriptor: (Ljava/lang/Object;)V
        flags: (0x0000)
        Code:
          stack=0, locals=2, args_size=2
             0: return
          LineNumberTable:
            line 3: 0
        Signature: #11                          // (TE;)V
    }
    Signature: #12                          // <E:Ljava/lang/Object;>Ljava/lang/Object;
    SourceFile: "Test.java"
    

    这些信息不能在字节码中丢弃的原因是,假设这个类是库的一部分;另一个项目取决于它。在第二个项目的编译时,他们的编译器需要能够断言泛型类型参数是否在边界内。如果它被完全扔掉了,他们就得写信了

    Test test = new Test();
    

    而在我的源项目中,我可以写

    Test<String> test = new Test<>():