1.什么是反射?
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
2.反射的三种方式
获取Class对象的3中方式
* 结论:
* 同一个字节码文件(*.class)再一次程序的运行过程中,只会被加载一次。
* 任何方式获得的是同一个Class对象
//1.Class.forname("全类名")
//多用于配置文件,读取文件,加载类
Class clazz1 = Class.forName("com.hdh.domain.User");
System.out.println(clazz1.hashCode());
//2.类名.class
//多用于参数的传递
Class clazz2 = User.class;
System.out.println(clazz2.hashCode());
//3.对象.getclass()
User user = new User();
Class clazz3 = user.getClass();
System.out.println(clazz3.hashCode());
Class中常见的方法
Class userClass = User.class;
3获取成员变量
.getField();
.getFields();
//1.获取指定名称的public修饰的成员变量
Field userField = userClass.getField("gender");
System.out.println(userField);
//2.获取所有public修饰的成员变量
Field[] fields = userClass.getFields();
for (Field field1 : fields) {
System.out.println(field1);
}
4.获取成员方法
.getDeclaredField()
.getDeclaredFields()
//获取指定的成员变量(包括私有的)
Field gender = userClass.getDeclaredField("gender"); System.out.println(gender); //获取所有的成员变量(包括私有的) Field[] declaredFields = userClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); }
访问私有的所有属性时无法获取和修改值,但可以通过设置.setAccessible()为true,忽略访问修饰符安全
//私有的不能获得值和设置值 但可以忽略安全
Field user1 = userClass.getDeclaredField("name");
//暴力反射 忽略访问权限修饰符的安全
user1.setAccessible(true);
System.out.println( user1.get(user));
5.获取构造方法
.getConstructor 创建对象.newInstance()
.getConstructors
//获取构造方法 用来创建对象
Constructor constructor = userClass.getConstructor(String.class, int.class);
System.out.println(constructor);
Object user2 = constructor.newInstance("张三", 20);
System.out.println(user2);
// 推荐使用Class的方法userClass.newInstance()
//获取所有的构造方法
Constructor[] constructors = userClass.getConstructors();
6获取方法
.getMethod() 执行方法.invoke()
.getMethods()
//获取方法 无参数
Method eat1 = userClass.getMethod("eat");
eat1.invoke(user);
//获取方法 有参数
Method eat2 = userClass.getMethod("eat",String.class);
eat2.invoke(user,"大便");
//获取所有方法名称
Method[] methods = userClass.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
7.获取类名 获取包名
.getName()
.getPackage()
//获取类名 获取包名
String name = userClass.getName();
System.out.println(name);
Package aPackage = userClass.getPackage();
System.out.println(aPackage);
8.获取properties.properties中的属性文件。className和methodName通过反射执行method方法
public class ReflexDemo3 {
public static void main(String[] args) throws Exception {
//使用反射 创建一个任意对象 执行对象中的方任意法
//1.加载配置文件 创建properties对象
Properties properties = new Properties();
//获得类加载器
ClassLoader classLoader = ReflexDemo3.class.getClassLoader();
//通过类加载器得到 properties的字节流
InputStream rs = classLoader.getResourceAsStream("properties.properties");
properties.load(rs);
//获取配置文件中定义的数据
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
//通过类的全路径名 加载字节码文件
Class clazz = Class.forName(className);
//创建一个类的新实例
Object o = clazz.newInstance();
Method method = clazz.getMethod(methodName);
//执行方法
method.invoke(o);
}
}