Java反射的详细解析之三

文章介绍了Java反射的基本概念,包括如何通过反射访问类的私有成员、泛型擦除、动态创建对象和调用方法,以及如何结合配置文件。还涉及了字符串的不可变性和如何使用反射修改其内容。最后展示了反射与配置文件的结合应用以及如何保存对象信息。
摘要由CSDN通过智能技术生成

面试题:

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

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

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

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 + "}";
    }
}

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向着五星的方向

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值