反射

反射可以用于分析每个类的具体信息。

1. 前置知识:Class类

运用反射机制就要知道一个叫Class的类。这个类的主要功能就是记录一个类的各种信息。在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
比如对一个Math类,其对应的Class类就记录了Math类中有多少域,方法和构造器等信息。

Class类的获取途径

不同于传统类用构造器或者工厂方法获得,该类的获取途径有3个:

  • 实例.getClass()
  • 类名.class
  • Class.forName()

实例.getClass()

Animal a = new Animal();
Animal b = new Dog();
...
Class c_Ani = a.getClass(); //c_Ani的信息是Animal类的Class类的信息
Class c_Dog = b.getClass(); //c_Dog的信息是Dog类的Class类里面的信息

类名.class

Class c_AniClass = Animal.class;    //直接通过类名调用该类的class

Class.forName()

forName()是Class类的一个静态方法。使用如下:

Class c_Math = Class.forName("Math");       //错误,类名不完整
Class c_MathCorrect = Class.forName("java.lang.Math");  //正确

利用Class类进行实例化

这利用了反射的思想,即对于运行当中产生的类,我们可以通过以下代码对其动态(识别)实例化:

public class Test{
    public void method(Object obj){
        Object instance_One = obj.getClass.newInstance();//也可以在newInstance中放入参数,不放参数则调用默认构造器
        Object instance_Two = obj.getClass.newInstance(Object[] args);
    }
}

2. 利用反射进行分析——类Field,Method,Constructor

在java.lang.reflect包中有三个类Field,Method,Constructor用于去对Class类包含的域,方法和构造器信息进行分析。

Field类

Field类的获得方法采用了工厂方法:

Field[] f = E.class.getFields();
Field[] f = E.class.getDeclaredFields();
Field f = E.class.getField("域名,如name");

在得到该类的某个域后,可以采用如下方式进行查看/设置(反射回去设置)

Dog dog = new Dog("charls");
Field fName = Dog.class.getField("name");
String newName = fName.get(dog);    //查看或设置时侯可能需要权限,这时候要用setAccessible()方法
fName.set(dog, "puppy");        //设置

Method类

Method类的获取方法大致同Field。由于方法名可能相同,因此会有一种特殊的获得方法getMethod(String name,Class<?>... parameterTypes)方法的调用则采用invoke()方法。

import java.lang.reflect.Method;  

public class MethodTest {  
    public static void main(String[] args) throws Exception {  
        User user = new User();  
        user.setName("jeey");  
        user.setAge(20);  
        Class c1= user.getClass();  
        Method m = c1.getDeclaredMethod("getAge");  
        System.out.println("获取age属性值:"+m.invoke(user));  
        //获得重载方法
        m = c1.getDeclaredMethod("setAge",int.class);  
        m.invoke(user, 99);  
        System.out.println("修改后的值:"+user.getAge());  
    }  
}  

Constructor类

Constructor类的获得方法和Method类一致,在具体的使用上是采用了newInstance()方法

import java.lang.reflect.Constructor;  

public class ConstructorTest {  

    public static void main(String[] args) throws Exception {  
        User user = new User();  
        user.setName("jeey");  
        user.setAge(20);  
        Class c1= user.getClass();  
        Constructor cons = c1.getDeclaredConstructor(String.class,int.class);  
        //通过构造方法创建实例  
        User u = (User)cons.newInstance("jack",33);  
        System.out.println("创建实例:name="+u.getName()+",age="+u.getAge());  
    }  

3. 利用反射构造泛型数组——类Array

在程序运行过程中,如果需要构建一个数组,我们可以采用Object[] objs = new Object[length];的方法进行构建,但是这样构建的数组是不可以转换成某一个类的数组的,因此,要构建泛型数组,就要采用Array类。具体涉及的方法如下:

  • public boolean isArray​() //Class类
  • public Class<?> getComponentType​() //Class类
  • public static Object newInstance​(Class<?> componentType,int length) //Array类
import java.lang.reflect.Array;  

public class ArrayTest {  

    public static void main(String[] args) {  
        String[] aa = {"aa","bb"};  
        Class c1 = aa.getClass();  
        System.out.println("是否是数值:"+c1.isArray());  //判断是否为数组类
        System.out.println("数组组件类型的 Class:"+c1.getComponentType());  
        //初始化数值  
        String[] arr = (String[])Array.newInstance(c1.getComponentType(), 2);  
        //数组设值  
        Array.set(arr, 0, "111");  
        Array.set(arr, 1, "222");  
        //访问  
        System.out.println(arr[0]);  
        System.out.println(Array.get(arr, 1));  
    }  

}

*部分代码参考Java反射(java.lang.reflect)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值