学习目标:
搞懂什么是反射
学习内容:
一.关于反射的一些概念
1.反射:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。也就是能够自描述和自控制。
2.JAVA反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
3.类对象: 所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
4.实现Java反射机制的API在Java.lang.reflect包下,具有以下几点。
(1)Class类:代表一个类。
(2)Filed类:代表类的成员变量。
(3)Method类:代表类的方法。
(4)Constructor类:代表类的构造方法。
(5)Array类:提供了动态创建数组及访问数组元素的静态方法。该类中的所有方法都是静态的。
二.获取类对象
获取类对象有3种方式
1.Class.forName(包名)
2.类名称.class
3.new 类名称().getClass()
public class TestReflection {
public static void main(String[] args) {
String className = "包名";
try {
Class pClass1=Class.forName(className);
Class pClass2=Hero.class;
Class pClass3=new Hero().getClass();
System.out.println(pClass1==pClass2);//true
System.out.println(pClass1==pClass3);//true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
获取类对象,会导致静态属性被初始化,而且只会执行一次。(除了直接使用 Class c = 类名称.class
这种方式,这种方式不会导致静态属性被初始化)
三.创建对象
与传统的通过new 来获取对象的方式不同
反射机制,会先拿到一个“类对象”,然后通过类对象获取“构造器对象”,再通过构造器对象创建一个对象。
public class TestReflection {
public static void main(String[] args) {
//传统的使用new的方式创建对象
Hero h1 =new Hero();
h1.name = "teemo";
System.out.println(h1);//Hero [name=teemo, hp=0.0, damage=0]
try {
//使用反射的方式创建对象
String className = "包名";
//类对象
Class pClass=Class.forName(className);
//构造器
Constructor c= pClass.getConstructor();
//通过构造器实例化
Hero h2= (Hero) c.newInstance();
h2.name="gareen";
System.out.println(h2);//Hero [name=gareen, hp=0.0, damage=0]
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
四.访问属性
public class test1 {
public static void main(String[] args) {
Hero h =new Hero();
//使用传统方式修改name的值为garen
h.name = "garen";
try {
//获取类Hero的名字叫做name的字段
Field f1= h.getClass().getDeclaredField("name");
//修改这个字段的值
f1.set(h, "teemo");
//打印被修改后的值
System.out.println(h.name);//teemo
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- getField和getDeclaredField的区别:
这两个方法都是用于获取字段。
getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。( 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
五.调用方法
public class r_test {
public static void main(String[] args) {
Hero h = new Hero();
try {
// 获取这个名字叫做setName,参数类型是String的方法
Method m = h.getClass().getMethod("setName", String.class);
// 对h对象,调用这个方法
m.invoke(h, "盖伦");
// 使用传统的方式,调用getName方法
System.out.println(h.getName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
六.用反射的作用
- 在运行时判断任意一个对象所属的类型。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法,甚至可以调用private方法。
另:
- 反射是Java语言很重要的特性。
- 反射在性能方面会有一定的损耗。
- Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,
无需提前硬编码目标类。这些特性使得反射特别适用于创建以普通方式与对象协作的库。(这一条我没搞懂)