5.7 反射

能够分析类能力的类称为反射(reflective)

反射可以用来:

  • 运行时分析类的能力。
  • 在运行时查看对象。
  • 实现通用的数组操作代码。

使用反射的人主要是工具构造者。

5.7.1 Class类

    //获取Class的方式。
   e.getClass();//第一种方式

   String className = "java.util.Random";//第二种方式
   Class cl = Class.forName(className);

   .class //第三种方式

虚拟机为每个类型管理一个Class对象。

    //动态创建一个类的实例
    e.getClass().newInstance();
    //调用默认构造器初始化新创建的对象。
    String s = "java.util.Random";
    Object m = Class.forName(s).getInstance();
    //如果希望创建的类的构造器提供参数:
    Class<?> classType = String.class;
    Constructor cons = classType.getConstructor(new Class[] {});
    Object  obj = cons.newInstance(new Object[]{});
    Class<?> classType = B.class;
    Constructor cons = classType.getConstructor(int.class,String.class);
    Object  obj = cons.newInstance(999,"一只独立特性的猪");

    Field [] fields = obj.getClass().getDeclaredFields();
    for (Field field : fields) {
        System.out.println(field.getType().getName() + field.getName());
    }
    System.out.println(obj.toString());

5.7.2捕获异常

异常分为两种类型:未检查异常和已检查异常(编译器将会检查是否提供了处理器)。

java.lang.Throwable

  • void printStackTrace()
    将Throwable对象和栈的轨迹输出到标准错误流。

5.7.3利用反射分析类的能力

Field | Method | Constructor 这三个类还有一个叫做getModifies的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用状况。

Modifier类的而静态方法:isPublic isPrivate或isFinal。

field.getModifiers();//输出一个整数值
Modifier.toString(field.getModifiers())//输出private public ...

Class类中的getFields getMethod getConstructors 方法都将分别返回类提供的public域 方法和构造器数组,其中包括超类的共有成员。Class类的getDeclareFields getDeclareMethods getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但是不包括超类的成员。

java.reflect.Modifier 类中包含的都是一些判断。判断类的访问修饰符,接口还是方法。

5.7.4在运行时使用反射分析对象

查看对象域的关键方法是Field类中的get方法。f.get(obj);

Class cl = this.getClass();
Field f = cl.getDeclaredField("name");
Object v = f.get(this);

设置访问域

f.setAccessible(true);

反射机制将会自动地将这个域值打包到对应的对象包装器中。

ObjectAnalyzer将记录已经被访问过的对象。

new ObjectAnalyzer().toString(this);

Class cl = this.getClass();
cl.isPrimitive();//判断是否是原始类型

//确定对应数组类型
getComponentType() //返回 类数组的组件类型的Class。 

String[] arr = new String[] {"admin"};

Class arrClass = arr.getClass();
Class componentType = arrClass.getComponentType();
if (componentType != null) {
   System.out.println("ComponentType = " + componentType.getName());
}else {
   System.out.println("ComponentType is null");
}

5.7.5 使用反射编写泛型数组代码

Java 数组会记住每个元素的类型,即创建数组时new表达式中使用的元素类型。

Object newArray = Array.newInstance(componentType,newLength);
public static Object copyOf(Object a, int newLength);
   Class cl = a.getClass();
   if(cl.isArray()) return null;
   Class componentType = c1.getComponrnType();
   int length = Array.getLength(a);
   Object newArray = Array.newInstance(componentType,newLength);
   System.arraycopy(a,0,newArray,0,Math.min(length,newLength));
   return newArray;
}

整型数组类型 int[] 可以被转换成Object,但不能转换为对象数组。

5.7.6调用任意方法

Method类中有一个invoke方法,它允许调用包装在当前Method对象中的方法。

Object invoke(Object obj,Object...args);
//第一个参数时隐式参数,其余的对象提供了显式参数,对于静态方法,第一个参数可以被忽略,即将它设为null。

例如,用m1代表Person类的getName方法,下面的语句显示如何调用这个方法:

Sring n = (String)m1.invoke(harry);

如果返回类型时基本类型,invoke方法会返回其包装器类型。

invoke的参数和方法必须是Object类型的。这也意味着必须进行多次类型转换。

建议Java开发者不要使用Method对象的回调功能。使用接口进行回调会使得代码的执行速度更快,更易于维护。

Class<?> classType = B.class;
Constructor cons = classType.getConstructor(int.class,String.class);
Object  obj = cons.newInstance(999,"一只独立特性的猪");
Field [] fields = obj.getClass().getDeclaredFields();
Method m1 = obj.getClass().getDeclaredMethod("getName");
System.out.println(m1);
System.out.println((String)m1.invoke(obj));

执行结果

public java.lang.String com.example.demo.entity.B.getName()
一只独立特性的猪
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值