框架的基石——反射

反射是指程序可以访问、检测和修改它本身状态或行为的一种能力

反射查看类信息

Class类和Class类实例

Class类的实例表示正在运行的Java应用程序中的类和接口

类的声明为:

public final class Class<T> extends Object implements Serializable, GeneicDeclaration,Type,AnnotationElement

泛型T:表示此Class对象建模的类的类型。例如,String.class的类型是Class<String>。如果表示的类未知,则使用Class<?>或Class

得到Class类的实例的3中方式:

  • 使用Class类的forName(String className)静态方法,className表示全限定名。如String的全限定名:java.lang.String
  • 调用某个类的class属性获取Class对象,如Date.class 会返回Date类的Class对象(其实就是得到一个类的一份字节码)
  • 调用某个对象的getClass()方法,该方法属于Object类。Class<?> clz = new Date().getCladd()
public static void main(String[] args){
    Class<Date> clz1 = Date.class;
    Class<Date> clz1 = (Class<Date>) Class.forName("java.util.Date");
    Class<Date> clz1 = (Class<Date>) new Date().getClass();
}

九个预定义Class对象

Java的基本类型(byte、short、int、long、float、double、char、boolean)和关键字void通过class属性也表示为Class对象

Class类中boolean isPeimitive()方法用于判断指定的Class对象是否是基本类型。包装类和void类的静态TYPE字段表示其基本类型的字节码对象。

数组的维数和数组的类型都相同时才表示同一种数组类型

public static void main(String[] args) throws Exception{
    boolean ret = Integer.TYPE == int.class;//true
    ret = Interger.class == int.class;//false
    Class<String[]> clz = String[].class;
    int[] arr1 = new int[]{1, 2, 3};
    ret = arr1.getClass() == int[].class;//true
    ret = int.class.isPrimitive();//true
    ret = Integer.class.isPrimitive();//false
}

获取类中构造器

  • Constructor<T>,getConstructor(Class<?>... parameterTypes):返回该Class对象表示类的指定的public 构造器
  • Constructor<?>,getConstructors():返回该Class对象表示类的所有public构造器
  • Constructor<T>,getDeclaredConstructor(Class<?>... parameterTypes):返回该Class对象表示类的指定的构造器,和访问权限无关
  • Constructor<?>,getDeclaredConstructors():返回该Class对象表示类的所有构造器,和访问权限无关

获取类中方法

  • Method getMethod(String name, Class<?> ... parameterTypes):返回该Class对象表示类和其父类的指定的public方法
  • Method[] getMethods():返回该Class对象表示类和其父类的所有public方法
  • Method getDeclaredMethod(String name, Class<?> ... parameterTypes):返回该Class对象表示类的指定方法,和访问权限无关,但不包括继承的方法
  • Method[] getDeclaredMethods():返回该Class对象表示类的所有方法,和访问权限无关,不包括继承的方法

获取类中字段

  • Field getField(String name, Class<?> ... parameterTypes):返回该Class对象表示类和其父类的指定的public字段
  • Field[] getFields():返回该Class对象表示类和其父类的所有public字段
  • Field getDeclaredField(String name, Class<?> ... parameterTypes):返回该Class对象表示类的指定字段,和访问权限无关,但不包括继承的字段
  • Field[] getDeclaredFields():返回该Class对象表示类的所有字段,和访问权限无关,不包括继承的字段

其他常用方法

  • public boolean isArray():判断该Class对象是否表示数字类型
  • public boolean isEnum():判断该Class对象是否表示枚举类型
  • public boolean isInterface():判断该Class对象是否表示接口
  • public boolean isInstance(Object obj):判断obj是否是该Class对象所表示的实例,等价于instanceof;
  • public Class<? super T> getSuperclass():返回该Class对象所表示类型(类、接口、基本类型或void)的超类的Class

反射生成并操作对象

创建对象

  • 使用Class对象的new Instance()方法创建该Class对象的实例,此时该Class对象必须要有无参数的构造方法
  • 使用Class对象获取指定的Constructor对象,再调用Constructor的newInstance()方法创建对象类的实例,此时可以选择使用某个构造方法。

调用方法

invoke

访问字段

Fiel提供两种方法操作字段:

  • xxx getXxx(Object obj):获取obj对象该Fiel的字段值。若该字段的类型是引用数据类型则使用,Object get(Object obj)
  • void setXxx(Object obj, xxx val):将obj对象的该Field字段设置成val值。若该字段的类型是引用数据类型则使用 void set(Object obj, Object value)

此处的xxx表示数据类型,如int ,double等

使用反射加载资源文件

  • Class类中的getResourceAsStream方法:表示从当前路径去加载资源。若加载资源文件的类和资源文件在同一路径下,首选该方式
  • ClassLoader类中getResourceAsSteam方法:表示从classpath的根路径去加载资源。若加载资源文件的类和资源文件不在同一路径下,首选该方式

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注