反射知识总结
反射概念
一.java运行时如何识别对象和类的信息?
- 传统的RTTI(Run-Time Type Identification),通过运行时类型判定,该机制在运行时识别一个对象的类型,它假定我们在编译时已经知道了所有类的信息。
- 反射机制,它允许我们在运行时发现和使用类的信息。
二.反射机制的作用
- 在运行时分析类的能力。
- 在运行时查看对象。例如,编写一个toString方法供所有类使用。
- 实现通用的数组操作代码。
- 利用Method对象。
Class类
在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行的类型标识。这个信息跟踪每对象所属的类。然而,可以通过专门的Java类访问这些信息。
反射机制
- 指的是可以运行时加载,使用编译期间完全未知的类。
- 程序在运行状态中,可以动态加载一个只有名称的类。
- 加载完类之后,在堆中就包含了完整的类的结构信息。我们可以通过对象看到类的结构。
( !!这个对象就像一面镜子,所以,形象的称之为:反射。)
获取Class对象
1.对象.getClass();
String path = "reflectionbean.User";
Class strClz1 = path.getClass();
2.T.class;
Class strClz = String.class;
–>注意:
- 如果T是任意的java(数据)类型(或void关键字),T.class 将代表匹配的类对象。
3.(最常用) Class.forName(包名.类名);
String path = "reflectionbean.User";
Class clz = Class.forName(path);
注意
1.一个Class对象实际上表示的一是个类型,而这个类型未必一定是一种类。例如:int不是类,但int.class是一个Class类型的对象。
2.方法二创建Class对象的引用时,不会自动初始化该Class对象,使用forName()会自动初始化该Class对象。
反射机制的相关类
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
反射和泛型
现在,Class类是泛型的。例如,String.class实际上是一个Class< String >类的对象(事实上,是唯一的对象)。
newInstace方法返回一个实例,这个实例所属的类由默认的构造器获得。它的返回类型目前被声明为T,其类型与Class< T > 描述的类相同,这样就免除了类型转换。
实例
为了演示反射的使用,首先构造一个与书籍相关的model——Person.java,然后通过反射方法示例创建对象、反射私有构造方法、反射私有属性、反射私有方法。
被反射类Person.java
public class Person {
private String name = "小明";
public void print(){
System.out.println(this.name);
}
public Person(){
}
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
反射相关操作
public class Test01 {
public static void main(String[] args) throws Exception{
Person p = new Person();
try {
Class<Person> clz = (Class<Person>) Class.forName("person.Person");
/**
* 通过反射得到属性以及属性值
*/
Field[] fields = clz.getDeclaredFields();
for(Field f:fields){
//打开私有访问
f.setAccessible(true);
//获取属性
String name = f.getName();
//获取属性值
Object value = f.get(p);
System.out.println(name+":"+value);
}
/**
* 通过反射构造对象
*/
Constructor<Person> c = clz.getDeclaredConstructor(String.class);
Person p1 = c.newInstance("coucou");
p1.print();
/**
* 通过反射调用普通方法
*/
Person p2 = clz.newInstance();
Method m = clz.getDeclaredMethod("setName", String.class);
m.invoke(p2,"coucou1");
System.out.println(p2.getName());
p2.print();
/**
* 通过反射操作属性
*/
// Field f = clz.getDeclaredField("id");
// f.setAccessible(true);
// f.set(p2,56);
// System.out.println(p2.getId());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
总结
Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。