目录
- 1.什么是反射
- 2.获取Class对象的三种方式
- 3.反射获取构造方法
- 4.反射获取成员变量
- 5.反射获取成员方法
- 6.反射的作用
1.什么是反射
在Java中,反射是指程序在运行时动态地获取类的信息、调用方法和访问属性的能力。
通过反射,可以在运行时获取类的构造函数、方法和字段
等信息,并且可以在运行时动态地创建对象、调用方法和访问属性
,而不需要在编译时知道类的具体信息。
反射提供了一种机制,使得编写通用的、灵活的代码成为可能,但同时也会增加代码的复杂性和性能开销。
反射允许对封装类的字段(成员变量),方法(成员方法)和构造函数(构造方法)的信息进行编程访问。
2.获取Class对象的三种方式
①
Class.forName("全类名");
//全类名:包名+类名Class clazz1 = Class.forName("case11.Student");//最常用
②
类名.class
//一般当作参数进行传递Class clazz2 = Student.class;
③
对象.getClass();
Student s = new Student();Class clazz3 = s.getClass();
3.反射获取构造方法
创建一个Student类:定义多种构造方法
public class Student {private String name;private int age;public Student() {}public Student(String name) {this.name = name;}protected Student(int age) {this.age = age;}private Student(String name, int age) {this.name = name;this.age = age;}
}
主函数:演示反射获取构造方法的各种函数
public class Main{public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//获取class字节码文件对象Class clazz = Class.forName("case11.Student");//获取public构造方法Constructor[] cons = clazz.getConstructors();for (Constructor con : cons) {System.out.println(con);}System.out.println("-------------------------");//获取所有构造方法Constructor[] con1 = clazz.getDeclaredConstructors();for (Constructor constructor : con1) {System.out.println(constructor);}System.out.println("-------------------------");//获取空参构造方法Constructor con2 = clazz.getDeclaredConstructor();System.out.println(con2);System.out.println("-------------------------");//获取带参数的构造方法System.out.println(clazz.getDeclaredConstructor(String.class));System.out.println(clazz.getDeclaredConstructor(int.class));Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class);System.out.println(con3);System.out.println("------------------------");//获取构造方法的权限修饰符int modifiers = con3.getModifiers();System.out.println(modifiers);//获取构造方法的参数Parameter[] parameters = con3.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//暴力反射:临时取消权限的校验con3.setAccessible(true);//创建对象Student student = (Student) con3.newInstance("张三", 123);System.out.println(student);}
}
4.反射获取成员变量
①Class类中用于获取成员变量的方法:
Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields(): 返回所有成员变量对象的数组
Field getField(String name): 返回单个公共成员变量对象
Field getDeclaredField(String name): 返回单个成员变量对象
②Field类中用于创建对象的方法:
void set(Object obj,Object value): 赋值
Object get(Object obj) 获取值。
创建一个Student类:
public class Student {private String name;private int age;public String gender;public Student() {}public Student(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}
主函数:利用反射修改成员变量
public class Main{public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {//获取class字节码文件的对象Class<?> clazz = Class.forName("case12.Student");//获取公共的成员变量Field[] fields = clazz.getFields();for (Field field : fields) {System.out.println(field);//public java.lang.String case12.Student.gender}//获取所有的成员变量Field[] fields1 = clazz.getDeclaredFields();//获取单个的成员变量Field gender = clazz.getField("gender");//获取私有的成员变量Field name = clazz.getDeclaredField("name");//获取权限修饰符int modifiers = name.getModifiers();//获取成员变量名name的值String n = name.getName();//获取成员变量数据类型Class<?> type = name.getType();System.out.println(type);//class java.lang.String//获取成员变量记录的值Student s = new Student("zhangsan", 23, "男");//临时取消访问权限name.setAccessible(true);Object value = name.get(s);System.out.println(value);//zhangsan//修改对象里面记录的值name.set(s, "lisi");System.out.println(s);//Student{name = lisi, age = 23, gender = 男}}
}
5.反射获取成员方法
①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对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写
返回值:方法的返回值(如果没有就不写)
定义一个Student类:
public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}/*** 获取** @return name*/public String getName() {return name;}/*** 设置** @param name*/public void setName(String name) {this.name = name;}/*** 获取** @return age*/public int getAge() {return age;}/*** 设置** @param age*/public void setAge(int age) {this.age = age;}public void sleep() {System.out.println("睡觉");}private void eat(String something) throws IOException, NullPointerException, ClassCastException {System.out.println("在吃" + something);}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}
主函数:演示反射获取成员方法
public class Main{public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {//获取class字节码文件对象Class<?> clazz = Class.forName("case13.Student");//获取公共的所有的方法对象Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method);//包含了父类中的所有的公共方法}//获取所有的方法但不能获取父类的方法,但可以获取本类中私有方法Method[] methods1 = clazz.getDeclaredMethods();//获取私有的单个方法Method m = clazz.getDeclaredMethod("eat", String.class);//获取方法的修饰符int modifiers = m.getModifiers();//获取方法的名字String name = m.getName();//获取方法的形参Parameter[] parameters = m.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);//java.lang.String arg0}//获取方法抛出的异常Class[] exceptionTypes = m.getExceptionTypes();for (Class exceptionType : exceptionTypes) {System.out.println(exceptionType);}//运行方法//定义方法的调用者Student s = new Student();//临时取消私有方法的访问权限m.setAccessible(true);m.invoke(s, "汉堡包");//在吃汉堡包}
}
6.反射的作用
①获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
②结合配置文件,动态的创建对象并调用方法
在Java中,反射可以用于获取和操作类的信息,包括类的属性、方法、构造函数等。
动态获取类的信息
:使用反射可以在运行时动态获取类的信息,例如获取类的属性、方法、构造函数等,并可以通过反射来创建类的实例。动态创建对象
:通过反射可以在运行时动态创建一个类的对象,而无需在编译时提前知道需要创建哪个类的对象。调用对象的方法
:通过反射可以调用一个类的方法,包括公有方法和私有方法。这使得我们可以在运行时根据需要动态调用不同的方法。修改私有属性
:通过反射可以修改一个类的私有属性的值,即使这个属性没有提供公开的set方法。- 扩展应用:反射还可以用于实现一些框架和工具,例如注解处理器、对象序列化、单元测试等。
需要注意的是,反射使用起来较为复杂,在性能上也比直接调用方法要慢。因此,在使用反射时应该谨慎,并在必要的情况下才使用。