【Java基础】反射与泛型

【Java基础】反射与泛型

能够分析类能力的程序称之为反射()。

反射库( )提供了一个丰富且精巧的工具集boolean java lang,可以用来编写能够动态操控Java代码的程序。

主要作用有:

获取类对象的三种方式

实例.getClass();
Class.forName("java.lang.Object");
类.class;

利用反射分析类的能力Class

所有类运行时的抽象。

Field[] getFields():返回这个类与超类的公共字段;
Field[] getDeclaredFields():返回这个类的所有字段,否则返回一个长度为0的数组;
Method[] getMethods():返回一个包含Method对象的数组,该数组反映由这个class对象表示的类或接口的所有公共方法,包括由类或接口声明的方法以及从超类和超接口继承的方法;
Method[] getDeclaredMethods():返回一个包含Method对象的数组,该数组反映由这个class对象表示的类或接口的所有声明方法,包括公共、受保护、默认(包)访问和私有方法,但不包括继承的方法;
Constructor[] getConstructors():返回一个包含构造函数对象的数组,该构造函数对象反映由此class对象表示的类的所有公共构造函数;
Constructor[] getDeclaredConstructors():全部构造器函数;
String getPackageName():得到包含这个类型的所有包名;如果是一个基本类型,则返回 "java.lang";
...

Field

类的字段。

Object get(Object obj):返回obj这个类此字段的值;
void set(Object obj, Object newValue):修改此对象该字段的值;

类的方法。

Object invoke(Object obj, Object... args);

类的构造器。

Object newInstance(Object... params);

分析修饰符。

public static boolean isPublic(int mod);
public static boolean isPrivate(int mod);
public static boolean isAbstract(int mod);
public static boolean isNative(int mod);
public static boolean isVolatile(int mod);
public static boolean isSynchronized(int mod);
public static boolean isStrict(int mod);
...

此外反射包下还有Array、等类,也有很强的能力。

利用反射获取泛型java.lang.Class

TypeVariable<Class>[] getTypeParameters():如果这个类型声明为泛型类型,则获得泛型类型变量,否则获得一个长度为为0的数组;
Type getGenericSuperclass():获得这个类型所声明超类的泛型类型;如果这个类型是Obejct或不是类类型(class type),则返回null;
Type[] getGenericInterfaces():获得这个类型所声明接口的泛型类型(按照声明的顺序),否则,如果这个类型没有实现接口,返回长度为0的数组;

java.lang..

TypeVariable[] getTypeParameters():如果这个方法被声明为一个泛型方法,则获得泛型类型变量,否则返回长度为0的数组;
Type getGenericReturnType():获得这个方法声明的泛型返回类型;
Type[] getGenericParameterTypes():获得这个方法声明的泛型参数类型,如果这个方法没有参数,则返回一个长度为0的数组;

java.lang..

String getName():获得这个类型变量的名字;
Type[] getBounds():获得这个类型变量的子类限定,否则,如果该类没有子类限定,返回长度为0的数组;

java.lang..

Type[] getUpperBounds():获得这个类型变量的子类限定,否则,如果没有子类限定,返回长度为0的数组;
Type[] getLowerBounds():获得这个类型变量的超类限定,否则,如果没有超类限定,返回长度为0的数组;

java.lang..

Type getRawType():获得这个参数化类型的原始类型;
Type[] getActualTypeArguments():获得这个参数化类型声明的类型参数;
Type getOwnerType():如果是内部类型,则返回外部类类型;如果是一个顶级类型,则返回null;

java.lang..

Type getGenericComponentType():获得这个数组类型所声明的泛型元素类型;

boolean java lang

Java的泛型的本质是参数化类型( Type)或者参数化多态( )的应用,即一种既可以将操作数据类型指定为方法签名中的一种特殊参数,这种参数类型能够用在类、接口和方法的创建中,分别构成泛型类、泛型接口、泛型方法,以增强语言类型系统以及抽象能力。也是一种语法糖。

这种泛型实现方式称之为“类型擦除式泛型(Type )”,与C#的”具现化式泛型( )”相对。

类型擦除

编译期间Java编译器会将类型参数替换为其上界(类型参数中子句的类型),如果上界没有定义,则默认为boolean java lang,这就叫做类型擦除。

裸类型

裸类型被视为所有类型泛型化的共同父类型。

泛型擦除前:

Map map = new HashMap();
map.put("a", "b");
System.out.println(map.get(a));

泛型擦除后:

Map map = new HashMap();
map.put("a", "b");
System.out.println(map.get(a));

类型擦除的利弊

弊:

利:

桥方法

Java中的桥接方法( )是一种为了实现某些Java语言特性而由编译器自动生成的方法。

我们可以通过类的方法来判断一个方法是否是桥接方法。

在字节码文件中,桥接方法会被标记为和:

什么时候生成桥方法?

为了实现哪些Java语言特性会生成桥接方法?最常见的两种情况就是协变返回值类型和类型擦除【Java基础】反射与泛型,因为它们导致了父类方法的参数和实际调用的方法参数类型不一致。下面我们通过两个例子更好地理解一下。

注意:静态方法与升级修饰符不会生成桥接方法。

协变返回类型

协变返回类型是指子类方法的返回值类型不必严格等同于父类中被重写的方法的返回值类型,而可以是更 “具体” 的类型。

在Java 1.5添加了对协变返回类型的支持,即子类重写父类方法时,返回的类型可以是子类方法返回类型的子类。下面看一个例子:

public class Parent {
    Number get() {
        return 1;
    }
}

public class Child extends Parent {
    @Override
    Integer get() {
        return 1;
    }
}

boolean java lang

Child类重写其父类的get方法,的get方法返回类型为,而Child类中get方法返回类型为。

将这段代码进行编译,再反编译:

javac Child.java
javap -v -c Child.class

结果如下:

public class Child extends Parent
......省略部分结果......
  java.lang.Integer get();
    descriptor: ()Ljava/lang/Integer;
    flags:
    Code:
      stack=1, locals=1, args_size=1
         0: iconst_1
         1: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         4: areturn
      LineNumberTable:
        line 5: 0
  java.lang.Number get();
    descriptor: ()Ljava/lang/Number;
    flags: ACC_BRIDGE, ACC_SYNTHETIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokevirtual #3                  // Method get:()Ljava/lang/Integer;
         4: areturn
      LineNumberTable:
        line 1: 0

从上面的结果可以看到,有一个方法java.lang. get(), 在源码中是没有出现过的,是由编译器自动生成的,该方法被标记为和,就是我们前面所说的桥接方法。

这个方法就起了一个桥接的作用,它所做的就是把对自身的调用通过指令再调用方法java.lang. get()。

**编译器这么做的原因是什么呢?**因为在JVM方法中,返回类型也是方法签名的一部分【Java基础】反射与泛型,而桥接方法的签名和其父类的方法签名一致,以此就实现了协变返回值类型。

类型擦除

泛型是Java 1.5才引进的概念,在这之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容,这是为什么呢?

这是因为,在编译期间Java编译器会将类型参数替换为其上界(类型参数中子句的类型),如果上界没有定义,则默认为,这就叫做类型擦除。

当一个子类在继承(或实现)一个父类(或接口)的泛型方法时,在子类中明确指定了泛型类型,那么在编译时编译器会自动生成桥接方法,例如:

public class Parent {    
    void set(T t) {
    } 
}

public class Child extends Parent {
    @Override
    void set(String str) {
    }
}

Child类在继承其父类的泛型方法时,明确指定了泛型类型为,将这段代码进行编译,再反编译:

public class Child extends Parent
......省略部分结果......
  void set(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags:
    Code:
      stack=0, locals=2, args_size=2
         0: return
      LineNumberTable:
        line 5: 0
  void set(java.lang.Object);
    descriptor: (Ljava/lang/Object;)V
    flags: ACC_BRIDGE, ACC_SYNTHETIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: checkcast     #2                  // class java/lang/String
         5: invokevirtual #3                  // Method set:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 1: 0

从上面的结果可以看到,有一个方法void set(java.lang.), 在源码中是没有出现过的,是由编译器自动生成的,该方法被标记为和,就是我们前面所说的桥接方法。

这个方法就起了一个桥接的作用,它所做的就是把对自身的调用通过指令再调用方法void set(java.lang.)。

**编译器这么做的原因是什么呢?**因为类在类型擦除之后boolean java lang,变成这样:

public class Parent {
    void set(Object t) {
    }
}

编译器为了让子类有一个与父类的方法签名一致的方法,就在子类自动生成一个与父类的方法签名一致的桥接方法。

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » 【Java基础】反射与泛型

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们