Java中的反射机制

一、反射的定义:
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

二、反射实现的原理:
class对象:JAVA语言中,在每个对象里边都会有一个类型指针,通过对象的类型指针,我们可以知道这个对象所属的类,才能调用正确的方法表,而这个类型指针就是class对象。

class类的几个特性:
1、Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性
2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
4、Class 对象只能由系统建立对象
5、一个类在 JVM 中只会有一个Class实例

class类的对象在java应用程序中代表一个类或者一个接口(基本类型也有其对应的class对象存在)。

三、如何获取某一个类的class对象:
获取class对象有三种方式:
1、通过“类名.class”获取class对象。
例:

Class cla = Student.class;
//获取了student类的class对象。

2、通过“class.forname(“路径名”)”
注:这个路径名是类所在的包。
例:

Class class2 = Class.forName("com.sebase.Student");

3、通过实例化对象的getclass:
例:

Student stu = new Student();
Class class3 = stu.getClass();

注意:不管是通过这些种方式取得了多少个指向Class对象的引用,只要使用这些方式的目标是同一个类或者这个类的实例化对象,那么这些引用就是相同的。因为Java中每个类只能拥有一个其对应的Class对象。
例:上边我们分别用了三种方法对student类进行了取class对象的操作,但是因为目标都是student类,所以得到的三个class对象是相同的。

四、反射的使用:
1、类的属性,Java中类的属性都存在于Field类中。
2、构造函数,Java中类的构造函数都存在于Constructor类中。
3、类的方法,Java中类的构造函数都存在于Method类中。

注意:因为Java的构造函数都是属于Constructor类的,所以在获取构造函数之后,我们要把构造函数赋值给一个Constructor类的对象。对于属性和方法来说也是一样,也要把它们赋值给对应的类的实例化对象。

获取构造函数:
getDeclaredConstructors 是获取该类全部的构造函数。
getConstructors 仅获取public的构造函数。
getDecalaredConstructor(Class…parameter type),括号里是我们要获取的构造函数需要的参数类型的class对象。
例:

Constructor[] constructors = cla.getDeclaredConstructors();
//cla是类的class对象。
for(Constructor c: constructors){
    System.out.println(c);
}//getDeclaredConstructors 获取全部的构造函数

Constructor[] constructors1 = cla.getConstructors();
for(Constructor c: constructors1){
    System.out.println(c);
}//getConstructors 获取public的构造函数
Constructor constructor = cla.getDeclaredConstructor(String.class, int.class, String.class);
//getDecalaredConstructor(Class...parameter type)
//括号里的参数意思是获取一个由String类型,int整型,String类型的参数的构造函数

通过反射获得的构造函数来创建对象:
通过class类里边的newInstance方法或者constructor构造函数类的newInstance方法
(1)、constructor构造函数类的newInstance方法:
格式:(强制转换)constructor.newInstance(构造函数所需参数);
注意:需要加强制转换。因为newInstance返回的是一个Object类的对象。

Student s = (Student)constructor.newInstance("zhangsan", 19, "shannxi");

(2)、class类的newInstance方法:
格式:(强制转换)class类的对象.newInstance;
注意:class类的newInstance方法只能调用无参数的构造函数,也就是说实际上创建的对象里边的属性都是默认的零值。

Student s1 = (Student)cla.newInstance();

获取类的属性:
getDeclaredFields 获取全部的属性。
getFields 获取public属性。
getDeclaredField() 获取某个指定的属性。
例:

Field[] fields = cla.getDeclaredFields();//cla是类的class对象。
    for(Field f: fields){
        System.out.println(f);
    }
//getDeclaredFields 获取全部的属性。

Field[] fields1 = cla.getFields();
    for(Field f: fields1){
        System.out.println(f);
    }
//getFields 仅获取public属性。

Field field = cla.getDeclaredField("要获取的属性的名称");
//getDeclaredField()  获取某个指定的属性。

通过Field类的set方法来设置属性。
格式:Field类的对象.set(要改变属性的对象,要改变为的属性的值)
结果:将要改变的对象的Field对象里边储存的属性改变为新的值。

例:

Field field = cla.getDeclaredField("name");
Student stu = (Student) cla.newInstance();
field.set(stu, "lisi");
//将field里边储存的name属性的值改为了“lisi”

注意:如果要改变的这个属性是private的,那么我们在使用set方法之前还要加上一句“需要改变的Flied类的对象.setAccessible(true);”。这是因为这句话让我们使用反射对象的时候JVM不会去检查Java语言权限控制(但是注意该方法会导致安全隐患),如果没有该方法,我们无法对私有属性访问。

例:如果把name属性改为private。

Field field = cla.getDeclaredField("name");
field.setAccessible(true);
//让我们越过访问权限去对私有属性访问。
Student stu = (Student) cla.newInstance();
field.set(stu, "lisi");

获取类的方法:
getDeclaredMethods 获取所有的方法。
getMethods 获取public的方法 (包括从基类继承而来的)。
getDeclaredMethod() 获取某个指定的方法。
getDeclaredMethod()的格式:
Method method = cla.getDeclaredMethod(“要获取的方法的名称”,这个方法需要的参数的类型的class对象);
注意:传入所需的参数类型的class对象,一定要传全部的参数。

通过Method类的invoke方法来调用我们需要的方法:
格式:Method类的实例化对象.invoke(对象的实例,方法的参数)。
调用了Method类的对象里边的方法。

例:

Method[] methods = cla.getDeclaredMethods();
for(Method m: methods){
    System.out.println(m);
}
//getDeclaredMethods 获取所有的方法。

Method[] methods1 = cla.getMethods();
for(Method m: methods1){
    System.out.println(m);
}
//getMethods 获取public的方法 (包括从基类继承而来的)。

Method method = cla.getDeclaredMethod("eat", String.class);
//getDeclaredMethod() 获取某个指定的方法。
//这里是获取了一个名为eat,参数是一个字符串的方法。

method.invoke(cla.newInstance(), "beef");
//我们通过invoke方法调用了我们刚刚获取的eat方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值