Java反射

概念

java是面向对象的编程语言,对象,是一种具体的概念
类:类是对具有相同特征或属性,具有相同行为能力的一类事物的描述或称呼
对象:对象是这一类事物带有属性值,具有具体行为的个体或实例

面向对象编程的语言

package test;

//定义一个类
public class Phone {
    
    //添加一些属性
    public String name;
    public double weight;
    
    //无参构造器
    public Phone(){
    }
    //有参构造器
    public Phone(String name,double weight){
        this.name = name;
        this.weight = weight;
    }

    //写入一些方法
    public void dianyuan(){
        System.out.println("开机");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }
}


Java中的反射机制

反射允许对封装类的字段,方法和构造函数的信息进行编程访问。

反射允许对成员变量,成员方法和构造方法的信息进行编程访问
通俗点说,是从类里面拿东西,把成员变量,成员方法和构造方法获取出来(获取其所有信息)
获取是从class字节码文件中去获取的

反射获取class对象的三种方式

  1. Class.forName("全类名");
  2. 类名+class
  3. 对象+getClass();

image.png
三种方式分别对应三个阶段

public class phone_tes2 {
    public static void main(String[] args) throws Exception{
        //获取类
        //1.使用class.forName()方法
        //最为常用的
        Class p = Class.forName("test.Phone");
        
        //2.使用类的class方法
        //一般更多的是当前参数进行传递
        Class p3 = Phone.class;

        //3.使用实例化对象的getClass()方法
        //当我们已经有了这个类的对象时才使用
        Phone p1 = new Phone();
        Class p2 = p1.getClass();
    }
}

反射获取构造方法

image.png

package test;

public class Phone {
    public String name;
    public double weight;
    //无参构造器
    public Phone(){
    }
    //有参构造器
    public Phone(String name){
        this.name = name;
    }

    protected Phone(double weight){
        this.weight = weight;
    }

    private Phone(String name,double weight){
        this.name = name;
        this.weight = weight;
    }
}
package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

public class phone_tes3 {
    public static void main(String[] args) throws Exception{
        //1.获取class字节码文件对象
        Class clazz = Class.forName("test.Phone");

        //2.获取public构造方法
        Constructor[] cons = clazz.getConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }

        //2.获取所有构造方法
        Constructor[] cons2 = clazz.getDeclaredConstructors();
        for (Constructor con : cons2) {
            System.out.println(con);
        }

        //3.获取单个构造方法
        Constructor con3 = clazz.getDeclaredConstructor(double.class);
        System.out.println(con3);

        Constructor con4 = clazz.getDeclaredConstructor(String.class,double.class);
        //获取权限修饰符对应的数字
        int modifiers = con4.getModifiers();
        System.out.println(modifiers);

        Parameter[] parameters = con4.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }

        //暴力反射:临时取消权限校验(即可用私有的构造方法创建对象)
        con4.setAccessible(true);
        Phone iphone = (Phone) con4.newInstance("enya", 88891);
        System.out.println(iphone);


    }
}

image.png

反射获取成员变量

image.png

package test2;

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 String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

package test2;

import java.lang.reflect.Field;

public class ste_tes1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //1.获取class字节码文件的对象
        Class clazz = Class.forName("test2.Student");

        //2.获取所有的成员变量
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            System.out.println(field);
        }

        //获取单个成员变量
        Field name = clazz.getDeclaredField("name");
        System.out.println(name);

        //获取权限修饰符
        int modifiers = name.getModifiers();
        System.out.println(modifiers);

        //获取成员变量名
        String name1 = name.getName();
        System.out.println(name1);

        //获取成员变量数据类型
        Class<?> type = name.getType();
        System.out.println(type);

        //获取成员变量记录的值
        Student s = new Student("ENYA",19,"女");
        name.setAccessible(true);
        String value = (String) name.get(s);
        System.out.println(value);

        //修改对象里面记录的值
        name.set(s,"Iris");
        System.out.println(s.getName());

    }
}

image.png

反射获取成员方法

image.png

package test2;

import java.io.IOException;

public class Student {
    private String name;
    private int age;


    public Student(){
    }
    public Student(String name,int age,String gender){
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void sleep(){
        System.out.println("睡觉");
    }
    private String eat(String somethimg)throws IOException,NullPointerException,ClassCastException {
        System.out.println("在吃"+somethimg);
        return "yummy!!";
    }
}

package test2;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class ste_tes2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.获取class字节
        Class clazz = Class.forName("test2.Student");

        //2.获取所有方法对象(包含父类中所有的公共方法)
//        Method[] methods = clazz.getMethods();
//        for (Method method : methods) {
//            System.out.println(method);
//        }

        //2.获取所有方法对象(不能获取父类的,但是可以获取本类中私有的方法)
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //获取指定的单一方法
        Method m = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(m);

        //获取方法的修饰符
        int modifiers = m.getModifiers();
        System.out.println(modifiers);

        //获取方法的名字
        String name = m.getName();
        System.out.println(name);

        //获取方法的形参
        Parameter[] parameters = m.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }

        //获取方法抛出的异常
        Class<?>[] exceptionTypes = m.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

        //方法运行
        Student s = new Student();
        m.setAccessible(true);
        //参数一表示方法的调用者,参数二表示在调用方法的时候传递的实际参数
        Object result = m.invoke(s, "汉堡包");
        System.out.println(result);

    }
}

image.png
image.png

练习

保存信息

对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
image.png

package test3;

public class Phone {
    public String name;
    public double weight;
    //无参构造器
    public Phone(){
    }
    //有参构造器
    public Phone(String name){
        this.name = name;
    }

    protected Phone(double weight){
        this.weight = weight;
    }

    Phone(String name, double weight){
        this.name = name;
        this.weight = weight;
    }
    public void dianyuan(){
        System.out.println("开机");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }
}


package test3;

import java.io.IOException;

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 String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void sleep(){
        System.out.println("睡觉");
    }
    private String eat(String somethimg)throws IOException,NullPointerException,ClassCastException {
        System.out.println("在吃"+somethimg);
        return "yummy!!";
    }
}

package test3;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;

public class demo1 {
    public static void main(String[] args) throws IllegalAccessException, IOException {

        Student s = new Student("enya",19,"女");
        Phone t = new Phone("apple",1987);

        saveobject(s);

    }

    //把对象里面所有的成员变量名和值保存到本地文件中
    public static void saveobject(Object obj) throws IllegalAccessException, IOException {
        //1.获取字节码文件的对象
        Class clazz = obj.getClass();

        //创建IO流
        BufferedWriter bw = new BufferedWriter(new FileWriter("demo1\\a.txt"));

        //2.获取所有的成员变量
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            //获取成员变量的名字
            String name = field.getName();
//            System.out.println(name);
            //获取成员变量的值
            Object value = field.get(obj);
            //写入数据
            bw.write(name + "=" + value);
            bw.newLine();

        }
        bw.close();

    }
}

运行结果:

name=enya
age=19
gender=女

跟配置文件结合动态创建

反射可以跟配置文件结合的方式,动态创建对象,并调用方法

package test4;

public class Phone {
    public String name;
    public double weight;
    //无参构造器
    public Phone(){
    }
    //有参构造器
    public Phone(String name){
        this.name = name;
    }

    protected Phone(double weight){
        this.weight = weight;
    }

    Phone(String name, double weight){
        this.name = name;
        this.weight = weight;
    }
    public void dianyuan(){
        System.out.println("手机正在开机");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }
}


package test4;

import java.io.IOException;

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 String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void sleep(){
        System.out.println("学生正在睡觉");
    }

}

classname=test4.Phone
method=dianyuan
package test4;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class demo {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
    /*
        反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
     */

        //1.读取配置文件中的信息
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream("demo1\\prop.properties");
        prop.load(fis);
        fis.close();
        System.out.println(prop);

        //2.获取全类名和方法名
        String classname = (String) prop.get("classname");
        String methodname = (String) prop.get("method");
        System.out.println(classname);
        System.out.println(methodname);

        //3.利用反射创建对象并运行方法
        Class clazz = Class.forName(classname);
//        Method m = clazz.getDeclaredMethod(methodname);
//        Student s = new Student();
//        m.setAccessible(true);
//        Object o = m.invoke(s);
//        System.out.println(o);

        //获取构造方法
        Constructor con = clazz.getDeclaredConstructor();
        Object o = con.newInstance();
        System.out.println(o);

        //获取成员变量并运行
        Method method = clazz.getDeclaredMethod(methodname);
        method.setAccessible(true);
        method.invoke(o);

    }
}

image.png

小结

image.png

posted @ 2024-07-20 21:36  1nnya  阅读(29)  评论(0)    收藏  举报