1.什么是反射?
反射允许对一个类的成员变量,成员方法和构造方法的信息进行编程访问,你就把反射理解成一个人它可以把类里面的东西都拿出来进行操作。
2.拿出来有什么用?
1.例如IDEA对于一个对象get还有set时,提出出来的成员变量就是这样提示出来的。
2.我们new出来的对象有时候忘记传什么形参,按住ctrl+p就能提示出来,那么IDEA就是通过反射来得到的。
3.获取class字节码文件三种方式
package com.itheima.myreflect1;
/**
* @author JiaWei
*/
public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
/**
* 获取class对象的三种方式:
* 1. class.forName("全类名“)
* 2. 类名.class
* 3. 对象.getClass();
*/
//1.包名加类名
Class<?> class1 = Class.forName("com.itheima.myreflect1.Student");
System.out.println(class1);
//2.第二种方式
Class<Student> clazz2 = Student.class;
System.out.println(clazz2);
//3.第三种方式
Student s = new Student();
Class class3 = s.getClass();
System.out.println(class1 == clazz2);
System.out.println(clazz2 == class3);
}
}
4.从字节码文件里面获取构造方法、成员变量、成员方法
package com.itheima.myreflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class MyReflectDemo {
public static <Student> void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/*
Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors() 返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes) 返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回单个构造方法对象
Constructor类中用于创建对象的方法
T newInstance(Object... initargs) 根据指定的构造方法创建对象
setAccessible(boolean flag) 设置为true,表示取 消访问检查
*/
//1.获取class字节码文件对象
Class clazz = Class.forName("com.itheima.myreflect2.Student");
//2.获取构造方法公有的 public
Constructor[] cons = clazz.getConstructors();
for (Constructor con : cons) {
// System.out.println(con);
}
//3.获取所有构造方法包括私有
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
// System.out.println(con);
}
//4.获取单个的构造方法 默认获取共有public的无参
Constructor con1 = clazz.getDeclaredConstructor();
// System.out.println(con1);
Constructor con2 = clazz.getDeclaredConstructor(String.class);
// System.out.println(con2);
//
Constructor con3 = clazz.getDeclaredConstructor(int.class);
// System.out.println(con3);
Constructor con4 = clazz.getDeclaredConstructor(String.class,int.class);
// System.out.println(con4);
int modifiers = con4.getModifiers();
// System.out.println(modifiers);
//5.获取所有参数类型 作用就是IDEA传参按住ctrl+p显示参数类型一样
Parameter[] parameters = con4.getParameters();
for (Parameter parameter : parameters) {
// System.out.println(parameter);
}
//6.暴力反射:表示临时取消权限校验
con4.setAccessible(true);
Student stu = (Student) con4.newInstance("张三", 23);
System.out.println(stu);
}
}
4.对成员变量进行操作
package com.itheima.myreflect3;
import java.lang.reflect.Field;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
/*
Class类中用于获取成员变量的方法
Field[] getFields(): 返回所有公共成员变量对象的数组
Field[] getDeclaredFields(): 返回所有成员变量对象的数组
Field getField(String name): 返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象
Field类中用于创建对象的方法
void set(Object obj, Object value):赋值
Object get(Object obj) 获取值
*/
//1.获取class字节码文件的对象
Class clazz = Class.forName("com.itheima.myreflect3.Student");
//2.获取所有的成员变量 无论共有私有
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// System.out.println(field);
}
//3.获取指定共有的成员变量
Field gender = clazz.getField("gender");
// System.out.println(gender);
//4.获取指定私有的成员变量
Field name = clazz.getDeclaredField("name");
// System.out.println(name);
//5.获取权限修饰符 私有的为2
int modifiers = name.getModifiers();
// System.out.println(modifiers);
//6.获取成员变量名称
String nameName = name.getName();
// System.out.println(nameName);
//7.获取成员变量数据类型
Class<?> type = name.getType();
System.out.println(type);
//8.获取成员变量记录的值
Student s = new Student("zhangsan",23,"男");
name.setAccessible(true);
Object value = name.get(s);
// System.out.println(value);
//9.修改对象里面记录的值
name.set(s,"lisi");
System.out.println(s);
}
}
5.反射获取成员方法
package com.itheima.myreflect4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
/*
Class类中用于获取成员方法的方法
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes) :返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象
Method类中用于创建对象的方法
Object invoke(Object obj, Object... args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
获取方法的修饰符
获取方法的名字
获取方法的形参
获取方法的返回值
获取方法的抛出的异常
*/
//1. 获取class字节码文件对象
Class clazz = Class.forName("com.itheima.myreflect4.Student");
//2.获取里面所有的方法对象也就是equals或者hashCode(包含父类中所有的公共方法,且不包含私有的)
// Method[] methods = clazz.getMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//3.获取里面所有的方法对象(不能获取父类的,但是可以获取本类中私有的)
// Method[] methods = clazz.getDeclaredMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//4.获取指定的单一方法
Method m = clazz.getDeclaredMethod("eat",String.class,int.class);
// System.out.println(m);
//5.获取方法的修饰符 2为私有的private
int modifiers = m.getModifiers();
// System.out.println(modifiers);
//6.获取方法的名字
String name = m.getName();
// System.out.println(name);
//7.获取方法的形参类型
Parameter[] parameters = m.getParameters();
for (Parameter parameter : parameters) {
// System.out.println(parameter);
}
//8.获取方法抛出的异常
Class[] exceptionTypes = m.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
// System.out.println(exceptionType);
}
//9.通过反射将指定类的方法参数进行修改
//s 表示方法的调用者 汉堡包表示在调用方法的时候传递的实际参数
Student s = new Student();
m.setAccessible(true);
String result = (String) m.invoke(s, "汉堡包");
System.out.println(result);
}
}
6.获取一个类所有信息保存到文件案例
package com.itheima.myreflect5;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class MyReflectDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
/*
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
*/
Student s = new Student("小A", 23, '女', 167.5, "睡觉");
Teacher t = new Teacher("播妞", 10000);
saveObject(s);
}
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.获取字节码文件的对象
Class clazz = obj.getClass();
BufferedWriter writer = new BufferedWriter(new FileWriter("D:\\网络编程\\代码\\myreflect\\myreflect\\a.txt"));
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
//获取成员变量的值
Object value = field.get(obj);
writer.write(name + "=" + value);
writer.flush();
writer.newLine();
}
writer.close();
}
}
7.反射搭配配置文件,动态的创建对象,并调用方法
package com.itheima.myreflect6;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class MyReflectDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/*
反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
*/
//1.读取配置文件信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("D:\\网络编程\\代码\\myreflect\\myreflect\\prop.properties");
prop.load(fis);
fis.close();
// System.out.println(prop);
//2.获取全类名和方法名
String className = (String) prop.get("classname");
String methodName = (String) prop.get("method");
// System.out.println(className);
// System.out.println(methodName);
//3.利用反射创建对象并运行方法
Class clazz = Class.forName(className);
//4.获取构造方法
Constructor con = clazz.getDeclaredConstructor();
Object o = con.newInstance();
// System.out.println(o);
//获取成员方法并运行
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(o);
}
}