一、什么是反射?
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
二、反射的三种方式
所谓反射其实是获取类的字节码文件,也就是.class文件,那么我们就可以通过Class这个对象进行获取。
1、第一种方式
public class Test02 {
public static void main(String\[\] args) {
// 创建一个对象
Test02 t = new Test02();
// 获取该对象的Class对象
Class c = t.getClass();
// 获取类名称
System.out.println(c.getName()); // com.ms.Test02
}
}
2、第二种方式
public static void main(String\[\] args) {
Class c = Test02.class;
// 获取类名称
System.out.println(c.getName()); // com.ms.Test02
}
3、第三种
这里需要注意,通过类的全路径名获取Class对象会抛出一个异常,如果根据类路径找不到这个类那么就会抛出这个异常
public static void main(String\[\] args) {
try {
// 根据类的全路径名获取
Class c = Class.forName("com.ms.Test02");
// 获取类名称
System.out.println(c.getName()); // com.ms.Test02
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
三、通过反射获取类的构造方法、方法以及属性
1、获取构造方法
public static void main(String\[\] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException {
// 加载Class对象
Class c = Class.forName("com.reflect.User");
System.out.println("===========================获取所有公用的构造方法==============================");
// 获取所有公用的构造方法
Constructor\[\] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("=============================获取所有的构造方法============================");
// 获取所有的构造方法
Constructor\[\] declaredConstructors = c.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("=============================获取公有 & 无参的构造方法============================");
Constructor constructor = c.getConstructor(null);
System.out.println(constructor);
System.out.println("=============================获取公有 & 有参的构造方法============================");
Constructor constructor1 = c.getConstructor(new Class\[\]{String.class, Integer.class, String.class});
System.out.println(constructor1);
System.out.println("=============================获取私有 & 有参 构造方法============================");
Constructor declaredConstructor1 = c.getDeclaredConstructor(new Class\[\]{String.class});
System.out.println(declaredConstructor1);
}
2、获取类属性
public static void main(String\[\] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
// 获取Class对象
Class<?> clazz = Class.forName("com.reflect.User");
System.out.println("=====获取所有的公共字段=====");
Field\[\] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("=====获取所有的字段(公开的、私有的)=====");
Field\[\] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("=====获取公有字段并使用=====");
// 获取指定公有字段
Field field = clazz.getField("name");
// 获取一个公有构造方法,然后实例化
Object obj = clazz.getConstructor().newInstance();
// 为属性设置值
field.set(obj, "张三");
// 测试,看设置的值是否成功
User user = (User) obj;
System.out.println(user.getName());
System.out.println("=====获取私有字段并使用=====");
Field field1 = clazz.getDeclaredField("sex");
// 获取构造函数,实例化对象
Object obj1 = clazz.getConstructor().newInstance();
// 暴力反射
field1.setAccessible(true);
// 给属性设置值
field1.set(obj1, "男");
// 测试
User u = (User) obj1;
System.out.println(u.getSex());
}
五、总结
使用反射获取一些属性方法,其实我们平时写代码很少用到反射技术,但是在我们使用的一些主流框架中反射技术应用是非常广泛的,所以学好反射也是非常有必要的。
评论