1、反射是什么
反射机制是在运行状态中,对任意的一个类,都可以知道这个类的所有方法和属性; 对于任何一个对象,都可以调用他的任意方法和属性,这种的信息以及动态调用对象的方法称为java的反射机制。
2、反射的作用- 1、反编译: .class–>java
- 2、通过反射机制访问对象的属性,方法,构造方法等
- java.lang.Class;
- java.lang.reflect.Constructor;
- java.lang.reflect.Field;
- java.lang.reflect.Method;
- java.lang.reflect.Modifier;
由于任何类都是Object的子类而Object中有getClass可以获取Class
对象 - public final native Class getClass();
-
package com.chb.reflectTest;
public class Test {
public static void main(String[] args) throws Exception {
//第一种方式:
Class c1 = Class.forName("com.chb.reflectTest.Test");
//第二种方式:java中每个类都有class属性
Class c2 = Test.class;
//第三种方式:每个对象都与getClass()方法
Class c3 = new Test().getClass();
}
}
3.3创建对象
获取Class对象以后,使用它创建对象,通过newInstance()调用无参构造函数进行创建对象,newInstance()返回一个Object对象:
Class c1 = Class.forName("com.chb.reflectTest.Test");
Object o1 = c1.newInstance();
3.4、获取数据
分为所有属性和制定的属性
3.4.1、获取所有属性获取修饰
- 首先通过属性的getModifiers()获取修饰对象,
- 再通过java.long.reflect.Modifier的toString()打印类,属性的修饰(public , static ,final等)。
获取属性
- 获取所有属性:通过Class对象的getDeclaedFields(),返回一个Filed的数组**。
获取属性的类型:
- 通过属性对象(Field对象)的getType()
Class cString = Class.forName("java.lang.String");
//获取累的修饰和名称
System.out.print(Modifier.toString(cString.getModifiers())+" class " + cString.getSimpleName()+"{\n");
//获取所有属性
Field[] fields = cString.getDeclaredFields();
for (Field field : fields) {
System.out.print("\t");
System.out.print(
Modifier.toString(field.getModifiers())+" "//属性的修饰
+ field.getType().getSimpleName()+" "
+ field.getName()+"\n");
}
System.out.println("}");
3.4.2 获取指定属性
创建测试对象: 注意: 我在Use类中定义了两个属性, 一个public ,一个private ,是为了下一个测试反射可以打破封装性
package com.chb.reflectTest;
public class User {
private String name;
public String nickName;
public User() {}
public User(String name, String nickName) {
this.name = name;
this.nickName = nickName;
}
setter getter...
}
传统属性的获取和通过反射获取对比:
package com.chb.reflectTest;
import java.lang.reflect.Field;
public class Test1 {
public static void main(String[] args) throws Exception {
//传统获取属性的值
//1、通过getter,setter
User user1 = new User();
user1.setName("lisi");
System.out.println(user1.getName());
//2、直接调用属性
User user2 = new User();
user2.nickName = "癞皮狗";
System.out.println(user2.nickName);
//=========================================
//通过反射来设置,获取属性。
Class c1 = (Class) Class.forName("com.chb.reflectTest.User");
User user = c1.newInstance();
Field nickField = c1.getDeclaredField("nickName");
nickField.set(user, "123");
System.out.println(nickField.get(user));
Field nameFiled = c1.getDeclaredField("name");
//Exception in thread "main" java.lang.IllegalAccessException: Class com.chb.reflectTest.Test1 can not access a member of class com.chb.reflectTest.User with modifiers "private"
nameFiled.setAccessible(true);
nameFiled.set(user, "oup");
System.out.println(nameFiled.get(user));
}
}
通过反射来设置属性的值, 区别属性的修饰范围, 私有的不可以直接设置 会出现访问错误, 也就是java的安全访问机制,报错:
Exception in thread "main" java.lang.IllegalAccessException: Class com.chb.reflectTest.Test1 can not access a member of class com.chb.reflectTest.User with modifiers "private"
我们通过一个方法·来打破java的封装性:
nameFiled.setAccessible(true);