面试题:
你觉得反射好不好?好,有两个方向
第一个方向:无视修饰符访问类中的内容。但是这种操作在开发中一般不用,都是框架底层来用的。
第二个方向:反射可以跟配置文件结合起来使用,动态的创建对象,动态的调用方法。
1.11 练习泛型擦除(掌握概念,了解代码)
理解:(掌握)
集合中的泛型只在java文件中存在,当编译成class文件之后,就没有泛型了。
代码示例:(了解)
package com.itheima.reflectdemo; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; public class ReflectDemo8 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //1.创建集合对象 ArrayList<Integer> list = new ArrayList<>(); list.add(123); // list.add("aaa"); //2.利用反射运行add方法去添加字符串 //因为反射使用的是class字节码文件 //获取class对象 Class clazz = list.getClass(); //获取add方法对象 Method method = clazz.getMethod("add", Object.class); //运行方法 method.invoke(list,"aaa"); //打印集合 System.out.println(list); } }
1.12 练习:修改字符串的内容(掌握概念,了解代码)
在这个练习中,我需要你掌握的是字符串不能修改的真正原因。
字符串,在底层是一个byte类型的字节数组,名字叫做value
private final byte[] value;
真正不能被修改的原因:final和private
final修饰value表示value记录的地址值不能修改。
private修饰value而且没有对外提供getvalue和setvalue的方法。所以,在外界不能获取或修改value记录的地址值。
如果要强行修改可以用反射:
代码示例:(了解)
String s = "abc"; String ss = "abc"; // private final byte[] value= {97,98,99}; // 没有对外提供getvalue和setvalue的方法,不能修改value记录的地址值 // 如果我们利用反射获取了value的地址值。 // 也是可以修改的,final修饰的value // 真正不可变的value数组的地址值,里面的内容利用反射还是可以修改的,比较危险 //1.获取class对象 Class clazz = s.getClass(); //2.获取value成员变量(private) Field field = clazz.getDeclaredField("value"); //但是这种操作非常危险 //JDK高版本已经屏蔽了这种操作,低版本还是可以的 //临时修改权限 field.setAccessible(true); //3.获取value记录的地址值 byte[] bytes = (byte[]) field.get(s); bytes[0] = 100; System.out.println(s);//dbc System.out.println(ss);//dbc
1.13 练习,反射和配置文件结合动态获取的练习(重点)
需求: 利用反射根据文件中的不同类名和方法名,创建不同的对象并调用方法。
分析:
①通过Properties加载配置文件
②得到类名和方法名
③通过类名反射得到Class对象
④通过Class对象创建一个对象
⑤通过Class对象得到方法
⑥调用方法
代码示例:
public class ReflectDemo9 { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { //1.读取配置文件的信息 Properties prop = new Properties(); FileInputStream fis = new FileInputStream("day14-code\\prop.properties"); prop.load(fis); fis.close(); System.out.println(prop); String classname = prop.get("classname") + ""; String methodname = prop.get("methodname") + ""; //2.获取字节码文件对象 Class clazz = Class.forName(classname); //3.要先创建这个类的对象 Constructor con = clazz.getDeclaredConstructor(); con.setAccessible(true); Object o = con.newInstance(); System.out.println(o); //4.获取方法的对象 Method method = clazz.getDeclaredMethod(methodname); method.setAccessible(true); //5.运行方法 method.invoke(o); } } 配置文件中的信息: classname=com.itheima.a02reflectdemo1.Student methodname=sleep
1.14 利用发射保存对象中的信息(重点)
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(); //2. 创建IO流 BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\a.txt")); //3. 获取所有的成员变量 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); //获取成员变量的名字 String name = field.getName(); //获取成员变量的值 Object value = field.get(obj); //写出数据 bw.write(name + "=" + value); bw.newLine(); } bw.close(); } } public class Student { private String name; private int age; private char gender; private double height; private String hobby; public Student() { } public Student(String name, int age, char gender, double height, String hobby) { this.name = name; this.age = age; this.gender = gender; this.height = height; this.hobby = hobby; } /** * 获取 * @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; } /** * 获取 * @return gender */ public char getGender() { return gender; } /** * 设置 * @param gender */ public void setGender(char gender) { this.gender = gender; } /** * 获取 * @return height */ public double getHeight() { return height; } /** * 设置 * @param height */ public void setHeight(double height) { this.height = height; } /** * 获取 * @return hobby */ public String getHobby() { return hobby; } /** * 设置 * @param hobby */ public void setHobby(String hobby) { this.hobby = hobby; } public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + ", hobby = " + hobby + "}"; } } public class Teacher { private String name; private double salary; public Teacher() { } public Teacher(String name, double salary) { this.name = name; this.salary = salary; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return salary */ public double getSalary() { return salary; } /** * 设置 * @param salary */ public void setSalary(double salary) { this.salary = salary; } public String toString() { return "Teacher{name = " + name + ", salary = " + salary + "}"; } }