Java泛型小記

前言

經(jīng)常會(huì)看到 “泛型會(huì)在編譯期擦除逻炊,但是運(yùn)行時(shí)可以獲取到”,自己也有過(guò)這樣的疑惑慢宗。此處做一下筆記坪蚁,記錄一下認(rèn)識(shí)和理解。

一镜沽、泛型概述

可以參照本文 Java 泛型敏晤,你了解類型擦除嗎?

二缅茉、獲取泛型類型

3.1嘴脾、demo

參照本文Java通過(guò)反射獲取泛型實(shí)際類型總結(jié)(什么可獲取,什么不可獲取)

文章中列出了幾種可以通過(guò)反射在 runtime 獲取泛型類型的情況:

package bean;

import java.lang.reflect.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestCache extends LocalCache<User> {

    private Map<String, Long> map = new HashMap<>();

    public TestCache(Map<String, Student> map) {
    }

    public void set(List<User> list) {

    }

    public List<String> get() {
        return null;
    }

    public static void main(String[] args) throws Exception {
        System.out.println("獲取屬性上的泛型: ");
        getFieldType();
        System.out.println("獲取方法參數(shù)中的泛型類型: ");
        getMethodParamsType();
        System.out.println("獲取方法返回值中的泛型類型: ");
        getMethodReturnType();
        System.out.println("獲取構(gòu)造方法中參數(shù)的泛型類型: ");
        getConstructorParamsType();
        System.out.println("獲取當(dāng)前類的直接父類上設(shè)置的泛型類型: ");
        getClassType();
    }

    /**
     * 獲取屬性的泛型類型
     *
     * @throws Exception
     */
    private static void getFieldType() throws Exception {
        Field field = TestCache.class.getDeclaredField("map");
        field.setAccessible(true);
        Type genericType = field.getGenericType();
        if (genericType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            Type[] typeList = parameterizedType.getActualTypeArguments();
            for (Type type : typeList) {
                System.out.println(type.getTypeName());
            }
        }
    }

    /**
     * 獲取方法參數(shù)中的泛型類型
     *
     * @throws Exception
     */
    public static void getMethodParamsType() throws Exception {
        Method method = TestCache.class.getDeclaredMethod("set", List.class);
        Type[] types = method.getGenericParameterTypes();
        if (types[0] instanceof ParameterizedType) {
            System.out.println(((ParameterizedType) (types[0])).getActualTypeArguments()[0]);
        }
    }

    /**
     * 獲取方法返回值中的泛型類型
     *
     * @throws Exception
     */
    public static void getMethodReturnType() throws Exception {
        Method method = TestCache.class.getDeclaredMethod("get");
        Type genericReturnType = method.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            System.out.println(((ParameterizedType) (genericReturnType)).getActualTypeArguments()[0]);
        }
    }

    /**
     * 獲取構(gòu)造方法中參數(shù)的泛型類型
     *
     * @throws Exception
     */
    public static void getConstructorParamsType() throws Exception {
        Constructor<TestCache> constructor = TestCache.class.getConstructor(Map.class);
        Type[] genericParameterTypes = constructor.getGenericParameterTypes();
        Type[] typeList = ((ParameterizedType) (genericParameterTypes[0])).getActualTypeArguments();
        for (Type type : typeList) {
            System.out.println(type.getTypeName());
        }
    }

    /**
     * 獲取當(dāng)前類的直接父類上設(shè)置的泛型類型
     */
    public static void getClassType() {
        Type genType = TestCache.class.getGenericSuperclass();
        Type type = ((ParameterizedType) genType).getActualTypeArguments()[0];
        System.out.println(type);
    }
}

我個(gè)人理解:
能從 class 文件中找到的泛型蔬墩,都可以在 runtime 通過(guò)反射獲取到统阿,下面看一下 class 文件中哪些地方記錄了泛型的類型。

3.2筹我、class 文件一覽

3.2.1扶平、class 文件內(nèi)容

 ~/Documents/projects/java-go/target/classes/bean  javap -v TestCache.class

Classfile /Users/dongbaowen/Documents/projects/java-go/target/classes/bean/TestCache.class
  Last modified 2021年2月11日; size 3721 bytes
  SHA-256 checksum 4d46ed7b93a4e7d51f9e3aa7e65832b01b342f11622a3ab0d52b64a5ccebbbb7
  Compiled from "TestCache.java"
public class bean.TestCache extends bean.LocalCache<bean.User>
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #6                          // bean/TestCache
  super_class: #35                        // bean/LocalCache
  interfaces: 0, fields: 1, methods: 9, attributes: 2
Constant pool:
    #1 = Methodref          #35.#97       // bean/LocalCache."<init>":()V
    #2 = Class              #98           // java/util/HashMap
    #3 = Methodref          #2.#97        // java/util/HashMap."<init>":()V
    #4 = Fieldref           #6.#99        // bean/TestCache.map:Ljava/util/Map;
    #5 = Methodref          #6.#100       // bean/TestCache.getConstructorParamsType:()V
    #6 = Class              #101          // bean/TestCache
    #7 = String             #36           // map
    #8 = Methodref          #16.#102      // java/lang/Class.getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;
    #9 = Methodref          #103.#104     // java/lang/reflect/Field.setAccessible:(Z)V
   #10 = Methodref          #103.#105     // java/lang/reflect/Field.getGenericType:()Ljava/lang/reflect/Type;
   #11 = Class              #106          // java/lang/reflect/ParameterizedType
   #12 = Fieldref           #107.#108     // java/lang/System.out:Ljava/io/PrintStream;
   #13 = InterfaceMethodref #11.#109      // java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type;
   #14 = Methodref          #110.#111     // java/io/PrintStream.println:(Ljava/lang/Object;)V
   #15 = String             #50           // set
   #16 = Class              #112          // java/lang/Class
   #17 = Class              #113          // java/util/List
   #18 = Methodref          #16.#114      // java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
   #19 = Methodref          #115.#116     // java/lang/reflect/Method.getGenericParameterTypes:()[Ljava/lang/reflect/Type;
   #20 = Class              #117          // java/lang/StringBuilder
   #21 = Methodref          #20.#97       // java/lang/StringBuilder."<init>":()V
   #22 = String             #118          // genericParameterTypes=
   #23 = Methodref          #20.#119      // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #24 = Methodref          #20.#120      // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
   #25 = Methodref          #20.#121      // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #26 = Methodref          #110.#122     // java/io/PrintStream.println:(Ljava/lang/String;)V
   #27 = String             #56           // get
   #28 = Methodref          #115.#123     // java/lang/reflect/Method.getGenericReturnType:()Ljava/lang/reflect/Type;
   #29 = String             #124          // genericReturnType=
   #30 = Class              #125          // java/util/Map
   #31 = Methodref          #16.#126      // java/lang/Class.getConstructor:([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
   #32 = Methodref          #127.#116     // java/lang/reflect/Constructor.getGenericParameterTypes:()[Ljava/lang/reflect/Type;
   #33 = Methodref          #16.#128      // java/lang/Class.getGenericSuperclass:()Ljava/lang/reflect/Type;
   #34 = String             #129          // params=
   #35 = Class              #130          // bean/LocalCache
   #36 = Utf8               map
   #37 = Utf8               Ljava/util/Map;
   #38 = Utf8               Signature
   #39 = Utf8               Ljava/util/Map<Ljava/lang/String;Ljava/lang/Long;>;
   #40 = Utf8               <init>
   #41 = Utf8               (Ljava/util/Map;)V
   #42 = Utf8               Code
   #43 = Utf8               LineNumberTable
   #44 = Utf8               LocalVariableTable
   #45 = Utf8               this
   #46 = Utf8               Lbean/TestCache;
   #47 = Utf8               LocalVariableTypeTable
   #48 = Utf8               Ljava/util/Map<Ljava/lang/String;Lbean/Student;>;
   #49 = Utf8               (Ljava/util/Map<Ljava/lang/String;Lbean/Student;>;)V
   #50 = Utf8               set
   #51 = Utf8               (Ljava/util/List;)V
   #52 = Utf8               list
   #53 = Utf8               Ljava/util/List;
   #54 = Utf8               Ljava/util/List<Lbean/User;>;
   #55 = Utf8               (Ljava/util/List<Lbean/User;>;)V
   #56 = Utf8               get
   #57 = Utf8               ()Ljava/util/List;
   #58 = Utf8               ()Ljava/util/List<Ljava/lang/String;>;
   #59 = Utf8               main
   #60 = Utf8               ([Ljava/lang/String;)V
   #61 = Utf8               args
   #62 = Utf8               [Ljava/lang/String;
   #63 = Utf8               Exceptions
   #64 = Class              #131          // java/lang/Exception
   #65 = Utf8               getFieldType
   #66 = Utf8               ()V
   #67 = Utf8               parameterizedType
   #68 = Utf8               Ljava/lang/reflect/ParameterizedType;
   #69 = Utf8               field
   #70 = Utf8               Ljava/lang/reflect/Field;
   #71 = Utf8               genericType
   #72 = Utf8               Ljava/lang/reflect/Type;
   #73 = Utf8               StackMapTable
   #74 = Class              #132          // java/lang/reflect/Field
   #75 = Class              #133          // java/lang/reflect/Type
   #76 = Utf8               getMethodParamsType
   #77 = Utf8               method
   #78 = Utf8               Ljava/lang/reflect/Method;
   #79 = Utf8               types
   #80 = Utf8               [Ljava/lang/reflect/Type;
   #81 = Class              #134          // java/lang/reflect/Method
   #82 = Class              #80           // "[Ljava/lang/reflect/Type;"
   #83 = Utf8               getMethodReturnType
   #84 = Utf8               genericReturnType
   #85 = Utf8               getConstructorParamsType
   #86 = Utf8               constructor
   #87 = Utf8               Ljava/lang/reflect/Constructor;
   #88 = Utf8               genericParameterTypes
   #89 = Utf8               type
   #90 = Utf8               Ljava/lang/reflect/Constructor<Lbean/TestCache;>;
   #91 = Utf8               getClassType
   #92 = Utf8               genType
   #93 = Utf8               params
   #94 = Utf8               Lbean/LocalCache<Lbean/User;>;
   #95 = Utf8               SourceFile
   #96 = Utf8               TestCache.java
   #97 = NameAndType        #40:#66       // "<init>":()V
   #98 = Utf8               java/util/HashMap
   #99 = NameAndType        #36:#37       // map:Ljava/util/Map;
  #100 = NameAndType        #85:#66       // getConstructorParamsType:()V
  #101 = Utf8               bean/TestCache
  #102 = NameAndType        #135:#136     // getDeclaredField:(Ljava/lang/String;)Ljava/lang/reflect/Field;
  #103 = Class              #132          // java/lang/reflect/Field
  #104 = NameAndType        #137:#138     // setAccessible:(Z)V
  #105 = NameAndType        #139:#140     // getGenericType:()Ljava/lang/reflect/Type;
  #106 = Utf8               java/lang/reflect/ParameterizedType
  #107 = Class              #141          // java/lang/System
  #108 = NameAndType        #142:#143     // out:Ljava/io/PrintStream;
  #109 = NameAndType        #144:#145     // getActualTypeArguments:()[Ljava/lang/reflect/Type;
  #110 = Class              #146          // java/io/PrintStream
  #111 = NameAndType        #147:#148     // println:(Ljava/lang/Object;)V
  #112 = Utf8               java/lang/Class
  #113 = Utf8               java/util/List
  #114 = NameAndType        #149:#150     // getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
  #115 = Class              #134          // java/lang/reflect/Method
  #116 = NameAndType        #151:#145     // getGenericParameterTypes:()[Ljava/lang/reflect/Type;
  #117 = Utf8               java/lang/StringBuilder
  #118 = Utf8               genericParameterTypes=
  #119 = NameAndType        #152:#153     // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #120 = NameAndType        #152:#154     // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #121 = NameAndType        #155:#156     // toString:()Ljava/lang/String;
  #122 = NameAndType        #147:#157     // println:(Ljava/lang/String;)V
  #123 = NameAndType        #158:#140     // getGenericReturnType:()Ljava/lang/reflect/Type;
  #124 = Utf8               genericReturnType=
  #125 = Utf8               java/util/Map
  #126 = NameAndType        #159:#160     // getConstructor:([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
  #127 = Class              #161          // java/lang/reflect/Constructor
  #128 = NameAndType        #162:#140     // getGenericSuperclass:()Ljava/lang/reflect/Type;
  #129 = Utf8               params=
  #130 = Utf8               bean/LocalCache
  #131 = Utf8               java/lang/Exception
  #132 = Utf8               java/lang/reflect/Field
  #133 = Utf8               java/lang/reflect/Type
  #134 = Utf8               java/lang/reflect/Method
  #135 = Utf8               getDeclaredField
  #136 = Utf8               (Ljava/lang/String;)Ljava/lang/reflect/Field;
  #137 = Utf8               setAccessible
  #138 = Utf8               (Z)V
  #139 = Utf8               getGenericType
  #140 = Utf8               ()Ljava/lang/reflect/Type;
  #141 = Utf8               java/lang/System
  #142 = Utf8               out
  #143 = Utf8               Ljava/io/PrintStream;
  #144 = Utf8               getActualTypeArguments
  #145 = Utf8               ()[Ljava/lang/reflect/Type;
  #146 = Utf8               java/io/PrintStream
  #147 = Utf8               println
  #148 = Utf8               (Ljava/lang/Object;)V
  #149 = Utf8               getDeclaredMethod
  #150 = Utf8               (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
  #151 = Utf8               getGenericParameterTypes
  #152 = Utf8               append
  #153 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #154 = Utf8               (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #155 = Utf8               toString
  #156 = Utf8               ()Ljava/lang/String;
  #157 = Utf8               (Ljava/lang/String;)V
  #158 = Utf8               getGenericReturnType
  #159 = Utf8               getConstructor
  #160 = Utf8               ([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
  #161 = Utf8               java/lang/reflect/Constructor
  #162 = Utf8               getGenericSuperclass
{
  public bean.TestCache(java.util.Map<java.lang.String, bean.Student>);
    descriptor: (Ljava/util/Map;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method bean/LocalCache."<init>":()V
         4: aload_0
         5: new           #2                  // class java/util/HashMap
         8: dup
         9: invokespecial #3                  // Method java/util/HashMap."<init>":()V
        12: putfield      #4                  // Field map:Ljava/util/Map;
        15: return
      LineNumberTable:
        line 20: 0
        line 18: 4
        line 21: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  this   Lbean/TestCache;
            0      16     1   map   Ljava/util/Map;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0      16     1   map   Ljava/util/Map<Ljava/lang/String;Lbean/Student;>;
    Signature: #49                          // (Ljava/util/Map<Ljava/lang/String;Lbean/Student;>;)V

  public void set(java.util.List<bean.User>);
    descriptor: (Ljava/util/List;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=0, locals=2, args_size=2
         0: return
      LineNumberTable:
        line 25: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       1     0  this   Lbean/TestCache;
            0       1     1  list   Ljava/util/List;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0       1     1  list   Ljava/util/List<Lbean/User;>;
    Signature: #55                          // (Ljava/util/List<Lbean/User;>;)V

  public java.util.List<java.lang.String> get();
    descriptor: ()Ljava/util/List;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aconst_null
         1: areturn
      LineNumberTable:
        line 28: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       2     0  this   Lbean/TestCache;
    Signature: #58                          // ()Ljava/util/List<Ljava/lang/String;>;

  public static void main(java.lang.String[]) throws java.lang.Exception;
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #5                  // Method getConstructorParamsType:()V
         3: return
      LineNumberTable:
        line 32: 0
        line 33: 3
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       4     0  args   [Ljava/lang/String;
    Exceptions:
      throws java.lang.Exception

  public static void getMethodParamsType() throws java.lang.Exception;
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=6, locals=2, args_size=0
         0: ldc           #6                  // class bean/TestCache
         2: ldc           #15                 // String set
         4: iconst_1
         5: anewarray     #16                 // class java/lang/Class
         8: dup
         9: iconst_0
        10: ldc           #17                 // class java/util/List
        12: aastore
        13: invokevirtual #18                 // Method java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
        16: astore_0
        17: aload_0
        18: invokevirtual #19                 // Method java/lang/reflect/Method.getGenericParameterTypes:()[Ljava/lang/reflect/Type;
        21: astore_1
        22: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
        25: new           #20                 // class java/lang/StringBuilder
        28: dup
        29: invokespecial #21                 // Method java/lang/StringBuilder."<init>":()V
        32: ldc           #22                 // String genericParameterTypes=
        34: invokevirtual #23                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        37: aload_1
        38: invokevirtual #24                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
        41: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        44: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        47: aload_1
        48: iconst_0
        49: aaload
        50: instanceof    #11                 // class java/lang/reflect/ParameterizedType
        53: ifeq          78
        56: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
        59: aload_1
        60: iconst_0
        61: aaload
        62: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        65: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        68: invokeinterface #13,  1           // InterfaceMethod java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type;
        73: iconst_0
        74: aaload
        75: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        78: return
      LineNumberTable:
        line 56: 0
        line 57: 17
        line 58: 22
        line 59: 47
        line 60: 56
        line 62: 78
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           17      62     0 method   Ljava/lang/reflect/Method;
           22      57     1 types   [Ljava/lang/reflect/Type;
      StackMapTable: number_of_entries = 1
        frame_type = 253 /* append */
          offset_delta = 78
          locals = [ class java/lang/reflect/Method, class "[Ljava/lang/reflect/Type;" ]
    Exceptions:
      throws java.lang.Exception

  public static void getMethodReturnType() throws java.lang.Exception;
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=6, locals=2, args_size=0
         0: ldc           #6                  // class bean/TestCache
         2: ldc           #27                 // String get
         4: iconst_1
         5: anewarray     #16                 // class java/lang/Class
         8: dup
         9: iconst_0
        10: ldc           #17                 // class java/util/List
        12: aastore
        13: invokevirtual #18                 // Method java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
        16: astore_0
        17: aload_0
        18: invokevirtual #28                 // Method java/lang/reflect/Method.getGenericReturnType:()Ljava/lang/reflect/Type;
        21: astore_1
        22: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
        25: new           #20                 // class java/lang/StringBuilder
        28: dup
        29: invokespecial #21                 // Method java/lang/StringBuilder."<init>":()V
        32: ldc           #29                 // String genericReturnType=
        34: invokevirtual #23                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        37: aload_1
        38: invokevirtual #24                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
        41: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        44: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        47: aload_1
        48: instanceof    #11                 // class java/lang/reflect/ParameterizedType
        51: ifeq          74
        54: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
        57: aload_1
        58: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        61: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        64: invokeinterface #13,  1           // InterfaceMethod java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type;
        69: iconst_0
        70: aaload
        71: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        74: return
      LineNumberTable:
        line 70: 0
        line 71: 17
        line 72: 22
        line 73: 47
        line 74: 54
        line 76: 74
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           17      58     0 method   Ljava/lang/reflect/Method;
           22      53     1 genericReturnType   Ljava/lang/reflect/Type;
      StackMapTable: number_of_entries = 1
        frame_type = 253 /* append */
          offset_delta = 74
          locals = [ class java/lang/reflect/Method, class java/lang/reflect/Type ]
    Exceptions:
      throws java.lang.Exception

  public static void getConstructorParamsType() throws java.lang.Exception;
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=5, locals=3, args_size=0
         0: ldc           #6                  // class bean/TestCache
         2: iconst_1
         3: anewarray     #16                 // class java/lang/Class
         6: dup
         7: iconst_0
         8: ldc           #30                 // class java/util/Map
        10: aastore
        11: invokevirtual #31                 // Method java/lang/Class.getConstructor:([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
        14: astore_0
        15: aload_0
        16: invokevirtual #32                 // Method java/lang/reflect/Constructor.getGenericParameterTypes:()[Ljava/lang/reflect/Type;
        19: astore_1
        20: aload_1
        21: iconst_0
        22: aaload
        23: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        26: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        29: invokeinterface #13,  1           // InterfaceMethod java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type;
        34: iconst_0
        35: aaload
        36: astore_2
        37: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
        40: aload_2
        41: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        44: return
      LineNumberTable:
        line 84: 0
        line 85: 15
        line 86: 20
        line 87: 37
        line 88: 44
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           15      30     0 constructor   Ljava/lang/reflect/Constructor;
           20      25     1 genericParameterTypes   [Ljava/lang/reflect/Type;
           37       8     2  type   Ljava/lang/reflect/Type;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
           15      30     0 constructor   Ljava/lang/reflect/Constructor<Lbean/TestCache;>;
    Exceptions:
      throws java.lang.Exception

  public static void getClassType() throws java.lang.Exception;
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=0
         0: ldc           #6                  // class bean/TestCache
         2: invokevirtual #33                 // Method java/lang/Class.getGenericSuperclass:()Ljava/lang/reflect/Type;
         5: astore_0
         6: aload_0
         7: checkcast     #11                 // class java/lang/reflect/ParameterizedType
        10: invokeinterface #13,  1           // InterfaceMethod java/lang/reflect/ParameterizedType.getActualTypeArguments:()[Ljava/lang/reflect/Type;
        15: iconst_0
        16: aaload
        17: astore_1
        18: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
        21: new           #20                 // class java/lang/StringBuilder
        24: dup
        25: invokespecial #21                 // Method java/lang/StringBuilder."<init>":()V
        28: ldc           #34                 // String params=
        30: invokevirtual #23                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        33: aload_1
        34: invokevirtual #24                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
        37: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        40: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: return
      LineNumberTable:
        line 96: 0
        line 97: 6
        line 98: 18
        line 99: 43
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            6      38     0 genType   Ljava/lang/reflect/Type;
           18      26     1 params   Ljava/lang/reflect/Type;
    Exceptions:
      throws java.lang.Exception
}
Signature: #94                          // Lbean/LocalCache<Lbean/User;>;
SourceFile: "TestCache.java"

查看 class 文件內(nèi)容,發(fā)現(xiàn) LocalVariableTypeTable 中的 Signature 包含了方法中存在的泛型蔬蕊,類似于:

      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0      16     1   map   Ljava/util/Map<Ljava/lang/String;Lbean/Student;>;
    Signature: #49                          // (Ljava/util/Map<Ljava/lang/String;Lbean/Student;>;)V

下方的 Signature 的#后面的編號(hào)對(duì)應(yīng)著 Constant pool 中保存的信息结澄。每個(gè)方法中都可以通過(guò) LocalVariableTypeTable 的 Signature 獲取到代碼中寫的泛型實(shí)際類型。

至于成員屬性岸夯,只有在 Constant pool 中保存著麻献。

#39 = Utf8               Ljava/util/Map<Ljava/lang/String;Ljava/lang/Long;>;

LocalVariableTypeTable 以及 Signature 的解釋:
深入探索Java泛型的本質(zhì) | 泛型

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市猜扮,隨后出現(xiàn)的幾起案子勉吻,更是在濱河造成了極大的恐慌,老刑警劉巖旅赢,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齿桃,死亡現(xiàn)場(chǎng)離奇詭異惑惶,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)短纵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門带污,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人香到,你說(shuō)我怎么就攤上這事鱼冀。” “怎么了悠就?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵千绪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我梗脾,道長(zhǎng)荸型,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任藐唠,我火速辦了婚禮帆疟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宇立。我一直安慰自己踪宠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布妈嘹。 她就那樣靜靜地躺著柳琢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪润脸。 梳的紋絲不亂的頭發(fā)上柬脸,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音毙驯,去河邊找鬼倒堕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛爆价,可吹牛的內(nèi)容都是我干的垦巴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼铭段,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼骤宣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起序愚,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤憔披,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芬膝,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡望门,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔗候。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怒允。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡埂软,死狀恐怖锈遥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勘畔,我是刑警寧澤所灸,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站炫七,受9級(jí)特大地震影響爬立,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜万哪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一侠驯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奕巍,春花似錦吟策、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至诅福,卻和暖如春匾委,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背氓润。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工赂乐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人咖气。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓挨措,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親采章。 傳聞我的和親對(duì)象是個(gè)殘疾皇子运嗜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容