java反射
1、反射概述
- JAVA反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能通过反射够调用它的任意一个方法和属性;
- 要想解剖一个类,必须先要获取到该类的字节码文件对象。
2、获取字节码对象三种方式
- Object类的getClass()方法,判断两个对象是否是同一个字节码文件
- 静态属性class,锁对象
- Class类中静态方法forName()
public static void main(String[] args) throws ClassNotFoundException { //1.Object类的getClass()方法 Person p = new Person(); Class clz1 = p.getClass(); //2.静态属性clas Class clz2 = Person.class; //3.Class类中静态方法forName() /** * 参数 forName(String className) 传类全路路(包名+类名) */ Class clz3 = Class.forName("lesson05.Person"); //4.字节码对象在内存中只有一个 System.out.println("clz1:" + clz1.hashCode()); System.out.println("clz2:" + clz2.hashCode()); System.out.println("clz3:" + clz3.hashCode()); }
3、案例读取配置文件创建字节码对象
//1.读取info.txt文件内容 FileReader fr = new FileReader("info.txt"); BufferedReader br = new BufferedReader(fr); String className = br.readLine(); br.close(); //2.获取字节码对象 Class clz = Class.forName(className); System.out.println(clz); info.txt lesson6.Person
4、通过反射获取参构造方法
使用要点:
1.如果要使用反射,先要获取字节码对象
2.通过字节码对象的getConstructor()可以获取到构造方法对象
3.构造方法对象(Contructor),有个newInstance方法创建这个字节码对象
4.反射是在java.lang.reflect这个包中
5.反射的作用一般是用于写框架(ssh,ssm)
代码:
//1.获取字节码对象 Class clz = Teacher.class; //2.获取构造方法 //2.1 无参构造方法 Constructor c1 = clz.getConstructor(); //2.2 通过构造方法创建对象 Teacher teacher1 = (Teacher) c1.newInstance(); System.out.println("teacher1:" + teacher1); //2.3 获取有参构造方法 /** * parameterType 参数类型 */ Constructor c2 = clz.getConstructor(String.class,String.class); Teacher teacher2 = (Teacher) c2.newInstance("gyf","梅州");//相当于调用new Teacher("gyf","梅州") System.out.println("teacher2:" + teacher2); Constructor c3 = clz.getConstructor(String.class,double.class); Teacher teacher3 = (Teacher) c3.newInstance("gyf",1.70);//相当于调用new Teacher("gyf","梅州") System.out.println("teacher3:" + teacher3);
5、通过反射获取类属性
使用要点
1.Class的getField(String)方法可以获取类中的指定字段(可见的),
2.如果是私有的,可以用getDeclaedField("name")方法获取
3.通过set(obj, "李四")方法可以设置指定对象上该字段的值
4.如果是私有的需要先调用setAccessible(true)设置访问权限,
5.调用get(obj)可以获取指定对象中该字段的值
代码
//1.获取字节码对象 Class clz = Teacher.class; //2.获取color字段 Field colorField = clz.getField("color"); System.out.println(colorField); //3.通过反射给字段赋值 Teacher teacher = new Teacher(); //teacher.color = "白色"; colorField.set(teacher, "黄色"); //4.获取私有name属性 Field nameField = clz.getDeclaredField("name"); System.out.println(nameField); //5.通过反射给私有属性赋值 nameField.setAccessible(true);//设置私有属性可以访问 nameField.set(teacher, "gyf"); System.out.println(teacher); //6.通过反射获取私有属性的值 Object value = nameField.get(teacher); System.out.println(value);
6、通过反射获取方法并使用
使用要点
1.反射中通过Method类描述方法【构造方法:Contructor,字段:Field】
2.通过Class的getMethod可以获取一个方法
3.通过getDeclaredMethod可以获取私有方法
4.如果要调用私有方法,设置访问权限setAccessible
代码
//1.获取字节码对象 Class clz = Teacher.class; Teacher teacher = new Teacher(); /* teacher.say1(); teacher.say2("小黄鸭"); teacher.say3("小黄鸭",2);*/ //2.通过反射调用方法 //2.1 获取无参方法 Method m1 = clz.getDeclaredMethod("say1"); //2.1 获取有参方法 Method m2 = clz.getDeclaredMethod("say2", String.class); Method m3 = clz.getDeclaredMethod("say3", String.class,int.class); //设置私有方法可以访问 m1.setAccessible(true); m2.setAccessible(true); m3.setAccessible(true); //3.2 调用方法 m1.invoke(teacher); m2.invoke(teacher, "小猪"); m3.invoke(teacher, "小狗",98);
7、案例越过泛型的检查
//1.声明泛型集合 List<Integer> list = new ArrayList<Integer>(); list.add(110); list.add(120); list.add(130); //list.add("gyf"); //2.通过反射往集合添加字符串 //2.1 获取字节码对象(Class) Class clz = list.getClass(); //2.2 通过反射获取方法 Method method = clz.getMethod("add", Object.class); //2.3 调用方法 method.invoke(list, "gyf"); System.out.println(list);
8、写一个通用的方法,设置对象的属性值