一、反射的概述
什么是反射?
发射允许对封装类的字段,方法和构造函数的信息进行编程访问。
二、获取class对象的三种方式
public static void main(String[] args) throws ClassNotFoundException {
//1.第一种方式 Class.forName("全类名")
//全类名 = 包名 + 类名
Class clazz = Class.forName("myReflect.ReflectDemo1.Student");
System.out.println(clazz); // class myReflect.ReflectDemo1.Student
//第二种方式 类名.class
Class clazz2 = Student.class;
System.out.println(clazz2); //class myReflect.ReflectDemo1.Student
//第三种方式 对象.getClass()
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3); //class myReflect.ReflectDemo1.Student
}
三、反射获取构造方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//0.获取class字节码文件对象
Class clazz = Class.forName("myReflect.ReflectDemo2.Student");
//获取构造方法
Constructor[] cons = clazz.getConstructors();
System.out.println(Arrays.toString(cons)); // [public myReflect.ReflectDemo2.Student(), public myReflect.ReflectDemo2.Student(java.lang.String)]
Constructor[] dcons = clazz.getDeclaredConstructors();
System.out.println(Arrays.toString(dcons)); // [public myReflect.ReflectDemo2.Student(), private myReflect.ReflectDemo2.Student(java.lang.String,int), protected myReflect.ReflectDemo2.Student(int), public myReflect.ReflectDemo2.Student(java.lang.String)]
Constructor con1 = clazz.getDeclaredConstructor();
System.out.println(con1); // public myReflect.ReflectDemo2.Student()
Constructor con2 = clazz.getDeclaredConstructor(String.class);
System.out.println(con2); //public myReflect.ReflectDemo2.Student(java.lang.String)
Constructor con3 = clazz.getDeclaredConstructor(int.class);
System.out.println(con3); //protected myReflect.ReflectDemo2.Student(int)
Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(con4); // private myReflect.ReflectDemo2.Student(java.lang.String,int)
//获取权限修饰符
int modifiers = con4.getModifiers();
System.out.println(modifiers); // 2
//获取参数信息
Parameter[] parameters = con4.getParameters();
System.out.println(Arrays.toString(parameters));
//获取学生对象
//暴力反射:临时取消权限校验
con4.setAccessible(true);
Student s1 = (Student) con4.newInstance("张三", 23);
System.out.println(s1);
}
四、反射获取成员变量
public static void main(String[] args) throws Exception {
//获取class字节码文件对象
Class clazz = Class.forName("myReflect.ReflectDemo3.Student");
//获取成员变量
Field[] f1 = clazz.getFields();
System.out.println(Arrays.toString(f1)); // [public java.lang.String myReflect.ReflectDemo3.Student.gender]
Field[] f2 = clazz.getDeclaredFields();
System.out.println(Arrays.toString(f2)); //[private java.lang.String myReflect.ReflectDemo3.Student.name, private int myReflect.ReflectDemo3.Student.age, public java.lang.String myReflect.ReflectDemo3.Student.gender]
Field gender = clazz.getField("gender");
System.out.println(gender);
Field name = clazz.getDeclaredField("name");
System.out.println(name);
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
//获取成员变量的名字
String name1 = name.getName();
System.out.println(name1);
//获取成员变量的类型
Class<?> type = name.getType();
System.out.println(type);
//获取成员变量记录的值
Student s = new Student("zhangsan",23,"男");
name.setAccessible(true);
Object value = name.get(s);
System.out.println(value);
//修改对象里面记录的值
name.set(s,"lisi");
System.out.println(s);
}
五、反射获取成员方法
public static void main(String[] args) throws Exception {
//获取class字节码文件对象
Class clazz = Class.forName("myReflect.ReflectDemo4.Student");
//获取所有的方法对象(包含父类中的方法)
Method[] methods = clazz.getMethods();
/*for (Method method : methods) {
System.out.println(method);
}*/
//获取所有的方法对象(不包含父类中的方法,但是可以获取本类中私有的方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
/*for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}*/
//获取单个方法
Method m = clazz.getDeclaredMethod("eat", String.class);
// System.out.println(m);
//获取修饰符
int modifiers = m.getModifiers();
System.out.println(modifiers);
//获取方法的名字
String name = m.getName();
System.out.println(name);
//获取方法的形参
Parameter[] parameters = m.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//获取方法抛出的异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
//方法运行
Student s = new Student();
m.setAccessible(true);
//参数一s:表示方法的调用者
//参数二"烤肠":表示在调用方法时传递的实际参数
Object result = m.invoke(s, "烤肠");
//获取方法的返回值
System.out.println(result);
}
六、反射的作用
public static void main(String[] args) throws IllegalAccessException, IOException {
Student s = new Student("小A", 23, "女", 167.5, "睡觉");
Teacher t = new Teacher("波妞", 10000);
saveObject(s);
}
//把对象里所有的成员变量名和值保存到文件中
private static void saveObject(Object obj) throws IllegalAccessException, IOException {
//获取字节码文件的对线
Class<?> clazz = obj.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("day33_code/a.txt", true));
//获取所有的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
String name = declaredField.getName();
Object value = declaredField.get(obj);
bw.write(name+"="+value);
bw.newLine();
}
bw.close();
}
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//读取配置文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("day33_code\\prop.properties");
prop.load(fis);
// System.out.println(prop);
//获取全类名和方法名
String className = (String) prop.get("classname");
String methodName = (String) prop.get("method");
// System.out.println(className);
// System.out.println(methodName);
//利用发射创建对象并运行方法
Class<?> clazz = Class.forName(className);
//获取构造方法
Constructor<?> con = clazz.getDeclaredConstructor();
Object obj = con.newInstance();
System.out.println(obj);
//获取成员方法并运行
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(obj);
}