- 什么是反射?
反射就是加载类,并允许以编程的方式剖析类中的各种成分(成员变量、构造方法和成员方法)。 - 我们要学习什么?
1.加载类,获取类的字节码:Class对象
2.获取类的构造器:Constructor对象
3.获取类的成员变量:Field对象
4.获取类的成员方法:Method对象
获取Class对象
- Class c1 = 类名.class
- Class提供的方法:
public static Class<?> forName(String className)
- Object提供的方法:
public final native Class<?> getClass()
public class Main {
public static void main(String[] args) throws Exception {
Class c1 = Student.class;
System.out.println(c1.getName());// 全名
System.out.println(c1.getSimpleName());
Class c2 = Class.forName("Student");
System.out.println(c2 == c1);// true
Student s = new Student();
Class c3 = s.getClass();
System.out.println(c2 == c3);// true
}
}
获取类的构造器Constructor对象
public class Main {
public static void main(String[] args) throws Exception {
// 先获取Class对象
Class c = Student.class;
// 获取类的全部构造方法
Constructor[] constructor = c.getConstructors();
for (Constructor constructor1 : constructor) {
System.out.println(constructor1.getName() + "---->" +
constructor1.getParameterCount());
}
// 获取无参构造器
Constructor constructor1 = c.getConstructor();
// 获取有参构造器
Constructor constructor2 = c.getConstructor(String.class, int.class);
}
}
Constructor对象的功能:返回一个初始化对象。
哪怕Constructor对象拿到的构造方法是私有的,也可以通过暴力反射创建对象,这也就破环了封装性。
public class Main {
public static void main(String[] args) throws Exception {
Class c = Student.class;
// 获取无参构造器
Constructor constructor1 = c.getConstructor();
constructor1.setAccessible(true);
Student student = (Student) constructor1.newInstance();
System.out.println(student);
// 获取有参构造器
Constructor constructor2 = c.getConstructor(String.class, int.class);
constructor2.setAccessible(true);
Student student2 = (Student) constructor2.newInstance("张三", 20);
System.out.println(student2);
}
}
获取类的成员变量Field对象
Class c = Student.class;
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getType() + " " + field.getName());
}
成员变量对象Field功能:赋值、取值。
Class c = Student.class;
Field name = c.getDeclaredField("name");
// 创建一个学生对象,为他赋值
Student s = new Student();
name.setAccessible(true);
name.set(s, "张三");
System.out.println(s);
//取值
String str = (String) name.get(s);
System.out.println(str);
获取类的成员方法Method对象
Class c = Student.class;
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
成员方法Method对象的功能:调用方法。
应用场景
- 基本作用:可以得到类的全部成分然后操作
- 破环类的封装性
- 最常用:适合做框架,基本上,主流的框架是根据反射设计出一些通用的功能
需求:对于任意一个对象,把对象的字段和对应的值保存到文件中去。
public class Main {
public static void main(String[] args) throws Exception {
Student s = new Student("张三",20);
ObjectSave.save(s);
People p = new People();
ObjectSave.save(p);
}
}
public class ObjectSave {
public static void save(Object o) {
try(
PrintWriter pw = new PrintWriter(new FileWriter("src/test.txt", true));
) {
Class<?> aClass = o.getClass();
String className = aClass.getSimpleName();
Field[] declaredFields = aClass.getDeclaredFields();
pw.println("-------" + className + "--------");
for (Field declaredField : declaredFields) {
// 成员变量名
String name = declaredField.getName();
// 成员变量值
declaredField.setAccessible(true);
String value = declaredField.get(o) +"";
pw.println(name + " = " + value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}