• Java反射的详细解析之三


    面试题:

    你觉得反射好不好?好,有两个方向

    第一个方向:无视修饰符访问类中的内容。但是这种操作在开发中一般不用,都是框架底层来用的。

    第二个方向:反射可以跟配置文件结合起来使用,动态的创建对象,动态的调用方法。

    1.11 练习泛型擦除(掌握概念,了解代码)

    理解:(掌握)

    集合中的泛型只在java文件中存在,当编译成class文件之后,就没有泛型了。

    代码示例:(了解)

    1. package com.itheima.reflectdemo;
    2. import java.lang.reflect.InvocationTargetException;
    3. import java.lang.reflect.Method;
    4. import java.util.ArrayList;
    5. public class ReflectDemo8 {
    6.    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    7.        //1.创建集合对象
    8.        ArrayList list = new ArrayList<>();
    9.        list.add(123);
    10. //       list.add("aaa");
    11.        //2.利用反射运行add方法去添加字符串
    12.        //因为反射使用的是class字节码文件
    13.        //获取class对象
    14.        Class clazz = list.getClass();
    15.        //获取add方法对象
    16.        Method method = clazz.getMethod("add", Object.class);
    17.        //运行方法
    18.        method.invoke(list,"aaa");
    19.        //打印集合
    20.        System.out.println(list);
    21.   }
    22. }

    1.12 练习:修改字符串的内容(掌握概念,了解代码)

    在这个练习中,我需要你掌握的是字符串不能修改的真正原因。

    字符串,在底层是一个byte类型的字节数组,名字叫做value

    private final byte[] value;

    真正不能被修改的原因:final和private

    final修饰value表示value记录的地址值不能修改。

    private修饰value而且没有对外提供getvalue和setvalue的方法。所以,在外界不能获取或修改value记录的地址值。

    如果要强行修改可以用反射:

    代码示例:(了解)

    1. String s = "abc";
    2. String ss = "abc";
    3. // private final byte[] value= {97,98,99};
    4. // 没有对外提供getvalue和setvalue的方法,不能修改value记录的地址值
    5. // 如果我们利用反射获取了value的地址值。
    6. // 也是可以修改的,final修饰的value
    7. // 真正不可变的value数组的地址值,里面的内容利用反射还是可以修改的,比较危险
    8. //1.获取class对象
    9. Class clazz = s.getClass();
    10. //2.获取value成员变量(private)
    11. Field field = clazz.getDeclaredField("value");
    12. //但是这种操作非常危险
    13. //JDK高版本已经屏蔽了这种操作,低版本还是可以的
    14. //临时修改权限
    15. field.setAccessible(true);
    16. //3.获取value记录的地址值
    17. byte[] bytes = (byte[]) field.get(s);
    18. bytes[0] = 100;
    19. System.out.println(s);//dbc
    20. System.out.println(ss);//dbc

    1.13 练习,反射和配置文件结合动态获取的练习(重点)

    需求: 利用反射根据文件中的不同类名和方法名,创建不同的对象并调用方法。

    分析:

    ①通过Properties加载配置文件

    ②得到类名和方法名

    ③通过类名反射得到Class对象

    ④通过Class对象创建一个对象

    ⑤通过Class对象得到方法

    ⑥调用方法

    代码示例:

    1. public class ReflectDemo9 {
    2.    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    3.        //1.读取配置文件的信息
    4.        Properties prop = new Properties();
    5.        FileInputStream fis = new FileInputStream("day14-code\\prop.properties");
    6.        prop.load(fis);
    7.        fis.close();
    8.        System.out.println(prop);
    9.        String classname = prop.get("classname") + "";
    10.        String methodname = prop.get("methodname") + "";
    11.        //2.获取字节码文件对象
    12.        Class clazz = Class.forName(classname);
    13.        //3.要先创建这个类的对象
    14.        Constructor con = clazz.getDeclaredConstructor();
    15.        con.setAccessible(true);
    16.        Object o = con.newInstance();
    17.        System.out.println(o);
    18.        //4.获取方法的对象
    19.        Method method = clazz.getDeclaredMethod(methodname);
    20.        method.setAccessible(true);
    21.        //5.运行方法
    22.        method.invoke(o);
    23.   }
    24. }
    25. 配置文件中的信息:
    26. classname=com.itheima.a02reflectdemo1.Student
    27. methodname=sleep

    1.14 利用发射保存对象中的信息(重点)

    1. public class MyReflectDemo {
    2.    public static void main(String[] args) throws IllegalAccessException, IOException {
    3.    /*
    4.        对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
    5.    */
    6.       Student s = new Student("小A",23,'女',167.5,"睡觉");
    7.       Teacher t = new Teacher("播妞",10000);
    8.       saveObject(s);
    9.   }
    10.    //把对象里面所有的成员变量名和值保存到本地文件中
    11.    public static void saveObject(Object obj) throws IllegalAccessException, IOException {
    12.        //1.获取字节码文件的对象
    13.        Class clazz = obj.getClass();
    14.        //2. 创建IO流
    15.        BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\a.txt"));
    16.        //3. 获取所有的成员变量
    17.        Field[] fields = clazz.getDeclaredFields();
    18.        for (Field field : fields) {
    19.            field.setAccessible(true);
    20.            //获取成员变量的名字
    21.            String name = field.getName();
    22.            //获取成员变量的值
    23.            Object value = field.get(obj);
    24.            //写出数据
    25.            bw.write(name + "=" + value);
    26.            bw.newLine();
    27.       }
    28.        bw.close();
    29.   }
    30. }
    31. public class Student {
    32.    private String name;
    33.    private int age;
    34.    private char gender;
    35.    private double height;
    36.    private String hobby;
    37.    public Student() {
    38.   }
    39.    public Student(String name, int age, char gender, double height, String hobby) {
    40.        this.name = name;
    41.        this.age = age;
    42.        this.gender = gender;
    43.        this.height = height;
    44.        this.hobby = hobby;
    45.   }
    46.    /**
    47.     * 获取
    48.     * @return name
    49.     */
    50.    public String getName() {
    51.        return name;
    52.   }
    53.    /**
    54.     * 设置
    55.     * @param name
    56.     */
    57.    public void setName(String name) {
    58.        this.name = name;
    59.   }
    60.    /**
    61.     * 获取
    62.     * @return age
    63.     */
    64.    public int getAge() {
    65.        return age;
    66.   }
    67.    /**
    68.     * 设置
    69.     * @param age
    70.     */
    71.    public void setAge(int age) {
    72.        this.age = age;
    73.   }
    74.    /**
    75.     * 获取
    76.     * @return gender
    77.     */
    78.    public char getGender() {
    79.        return gender;
    80.   }
    81.    /**
    82.     * 设置
    83.     * @param gender
    84.     */
    85.    public void setGender(char gender) {
    86.        this.gender = gender;
    87.   }
    88.    /**
    89.     * 获取
    90.     * @return height
    91.     */
    92.    public double getHeight() {
    93.        return height;
    94.   }
    95.    /**
    96.     * 设置
    97.     * @param height
    98.     */
    99.    public void setHeight(double height) {
    100.        this.height = height;
    101.   }
    102.    /**
    103.     * 获取
    104.     * @return hobby
    105.     */
    106.    public String getHobby() {
    107.        return hobby;
    108.   }
    109.    /**
    110.     * 设置
    111.     * @param hobby
    112.     */
    113.    public void setHobby(String hobby) {
    114.        this.hobby = hobby;
    115.   }
    116.    public String toString() {
    117.        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + ", hobby = " + hobby + "}";
    118.   }
    119. }
    120. public class Teacher {
    121.    private String name;
    122.    private double salary;
    123.    public Teacher() {
    124.   }
    125.    public Teacher(String name, double salary) {
    126.        this.name = name;
    127.        this.salary = salary;
    128.   }
    129.    /**
    130.     * 获取
    131.     * @return name
    132.     */
    133.    public String getName() {
    134.        return name;
    135.   }
    136.    /**
    137.     * 设置
    138.     * @param name
    139.     */
    140.    public void setName(String name) {
    141.        this.name = name;
    142.   }
    143.    /**
    144.     * 获取
    145.     * @return salary
    146.     */
    147.    public double getSalary() {
    148.        return salary;
    149.   }
    150.    /**
    151.     * 设置
    152.     * @param salary
    153.     */
    154.    public void setSalary(double salary) {
    155.        this.salary = salary;
    156.   }
    157.    public String toString() {
    158.        return "Teacher{name = " + name + ", salary = " + salary + "}";
    159.   }
    160. }
    
                    
  • 相关阅读:
    R155法规有没有要求上Secure Boot功能?
    适用于多类移动场景的融合认证机制设计
    Go语言学习笔记—xorm
    10年经验总结:数据分析师7种工具,因果分析划重点!
    LeetCode刷题---合并两个有序链表
    模块化开发_php中使用redis
    【Java】封装、继承、多态
    工厂模式:简化对象创建的设计思想 (设计模式 四)
    【每天学习一点新知识】CC攻击和DDoS的区别
    一星级挑战:14 数字加密
  • 原文地址:https://blog.csdn.net/qq_69748833/article/details/133779474