Java -反射实例详解

1.概述

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

        我们知道在idea里面编写Java代码的时候,编辑器会给我们提供一些编程的提示,这些其实就是底层用反射实现的。

2.获取class对象的三种方式

  • Class.forName("全类名");    ---源代码阶段
  • 类名.class;   ---加载阶段
  • 对象.getClass();    --运行阶段

  • 样例代码:

        Student类:

package com.qcby.MyReflect;

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

    public Student() {
    }

    public Student(String name, int age) {
        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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

        测试类:

package com.qcby.MyReflect;

public class MyReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
        method1();
        method2();
        method3();
    }
    /**
     * 反射的第一种方式
     * 最常用
     */
    public static void method1() throws ClassNotFoundException {
        System.out.println("第一种方式:");
        //全类名:  包名+类名
        Class clazz= Class.forName("com.qcby.MyReflect.Student");
        System.out.println("反射的类:"+clazz);
    }
    /**
     * 反射的第二种方式
     * 一般更多的是当做参数来传递
     */
    public static void method2(){
        System.out.println("第二种方式:");
        Class clazz= Student.class;
        System.out.println("反射的类:"+clazz);
    }
    /**
     * 反射的第三种方式
     * 当已经有了一个类的实例的时候,使用方式三
     */
    public static void method3(){
        System.out.println("第三种方式:");
        Student student=new Student();
        Class clazz= student.getClass();
        System.out.println("反射的类:"+clazz);
    }
}

3.反射获取构造方法

        代码示例:

package com.qcby.MyReflect;

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

public class MyConstructorReflect {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取class字节码文件对象
        Class clazz=Class.forName("com.qcby.MyReflect.Student");
        //获取所有公有构造方法
        System.out.println("获取所有公有构造方法");
        Constructor[] cons=clazz.getConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }
        System.out.println("获取所有构造方法");
        Constructor[] cons2=clazz.getDeclaredConstructors();
        for (Constructor con : cons2) {
            System.out.println(con);
        }
        System.out.println("----------");
        //通过无参数来获取无参构造函数
        Constructor con3=clazz.getDeclaredConstructor();
        System.out.println(con3);
        System.out.println("----------");
        //获取参数为String类型的构造函数,如果有多个参数,可以传递多个class对象
        Constructor con4=clazz.getDeclaredConstructor(String.class);
        System.out.println(con4);
        System.out.println("----------");
        Constructor con5=clazz.getDeclaredConstructor(String.class,int.class);
        System.out.println(con5);
        System.out.println("----------");
        //权限修饰符用整数来代表
        //public --->  1
        //private --->  2
        System.out.println("获取权限修饰符:");
        int modifiers=con5.getModifiers();
        System.out.println(modifiers);
        System.out.println("----------");
        System.out.println("获取参数:");
        Parameter[] parameters=con5.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }
        //利用构造方法创建对象实例
        System.out.println("----------");
        System.out.println("创建对象示例:");
        con5.setAccessible(true);//设置该构造方法可得,即使是私有方法也可以执行,如果没有,就只能执行公有方法
        Student student= (Student) con5.newInstance("张三", 12);
        System.out.println(student);
    }
}

4.反射获取成员变量

        代码示例:

package com.qcby.MyReflect;

import java.lang.reflect.Field;

public class MyClassItemReflect {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        System.out.println("获取公共成员变量:");
        //1.获取class字节码文件的对象
        Class Clazz = Class.forName("com.qcby.MyReflect.Student");
        //2.获取成员变量(所有公共属性的)
        Field[] fields= Clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("--------------");
        System.out.println("获取所有成员变量:");
        Field[] fields2= Clazz.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
        System.out.println("--------------");
        System.out.println("获取单个公共属性的成员变量:");
        Field field=Clazz.getField("gender");
        System.out.println(field);
        System.out.println("--------------");
        System.out.println("获取单个任意属性的成员变量:");
        Field field2=Clazz.getDeclaredField("age");
        System.out.println(field2);
        System.out.println("--------------");
        System.out.println("获取成员变量的权限修饰符:");
        int modifiers=field2.getModifiers();
        System.out.println(modifiers);
        System.out.println("--------------");
        System.out.println("获取成员变量名和类型:");
        String age = field2.getName();
        Class type = field2.getType();
        System.out.println(age+"  "+type);
        System.out.println("--------------");
        System.out.println("获取成员变量所记录的值:");
        Student student=new Student("张三",18,"男");
        field2.setAccessible(true);//因为age成员变量是私有属性的
        Object o = field2.get(student);
        System.out.println(o);
        System.out.println("--------------");
        System.out.println("修改成员变量所记录的值:");
        field2.set(student,20);
        System.out.println(student);
    }
}

        Student类:

package com.qcby.MyReflect;

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

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(int age) {
        this.age = age;
    }

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

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

5.反射获取成员方法

        代码示例:

package com.qcby.MyReflect;

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

public class MyItemMethodReflect {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.获取class字节码文件对象
        Class Clazz = Class.forName("com.qcby.MyReflect.Student");
        System.out.println("获取类中所有公有的方法对象:");
        Method[] methods = Clazz.getMethods();//包含父类中所有的公共方法
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("--------");
        System.out.println("获取类中所有的方法对象:");
        Method[] declaredMethods = Clazz.getDeclaredMethods();//不包含父类中的方法
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("--------");
        System.out.println("获取类中某一个方法对象:");
        Method eat = Clazz.getMethod("eat", String.class);//方法名+参数类型,防止重载函数
        System.out.println(eat);
        System.out.println("--------");
        System.out.println("获取类中某一个任意属性的方法对象:");
        Method eat2 = Clazz.getDeclaredMethod("eat", String.class);//方法名+参数类型,防止重载函数
        System.out.println(eat2);
        System.out.println("--------");
        System.out.println("获取方法对象的权限修饰符:");
        int modifiers = eat.getModifiers();
        System.out.println(modifiers);
        System.out.println("--------");
        System.out.println("获取方法对象的名字:");
        String name = eat.getName();
        System.out.println(name);
        System.out.println("--------");
        System.out.println("获取方法对象的参数:");
        Parameter[] parameters = eat.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }
        System.out.println("--------");
        System.out.println("获取方法对象抛出的异常:");
        Class[] exceptionTypes = eat.getExceptionTypes();
        for (Class exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }
        System.out.println("--------");
        System.out.println("运行方法:");
        Student student=new Student("张三",15,"男");
        eat.setAccessible(true);
        //参数一:表示方法的调用者
        //方法二:表示该方法的参数
        eat.invoke(student,"麻辣烫");
    }
}

        Student类:

package com.qcby.MyReflect;

public class Student {
    private String name;
    private int age;
    private String gender;
    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(int age) {
        this.age = age;
    }

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

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }

    public void sleep(){
        System.out.println("睡觉");
    }
    public void eat(String something) throws IllegalArgumentException,NoSuchMethodException,NoSuchFieldException{
        System.out.println("在吃"+something);
    }
}

6.总和案例一 ---  保存对象任意数据

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

        代码:

package com.qcby.MyReflect.Practice;


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

public class MyTest {
    public static void main(String[] args) throws IllegalAccessException, IOException {
        Student student=new Student("小A",23,'女',167.5,"睡觉");
        Teacher teacher=new Teacher("老王",10000);
        saveObject(student);
    }
    //把对象里面所有的成员变量和值保存在本地文件中
    public static void saveObject(Object obj) throws IllegalAccessException, IOException {
        //1.获取字节码文件的对象
        Class clazz = obj.getClass();

        //创建IO流
        BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("D:\\JavaProject\\qcby-l\\out.txt"));

        //2.获取所有的成员变量
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);//临时取消访问权限,即取消私有属性
            //获取成员变量的名字
            String name = declaredField.getName();
            //获取成员变量的值
            Object value = declaredField.get(obj);
            System.out.println(name+"="+value);
            bufferedWriter.write(name+"="+value);//写入
            bufferedWriter.newLine(); //换行
        }
        
        bufferedWriter.close();
    }
}

        Student类:

package com.qcby.MyReflect.Practice;

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

    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 char getGender() {
        return gender;
    }

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

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", height=" + height +
                ", hobby='" + hobby + '\'' +
                '}';
    }
}

        Teacher类:

package com.qcby.MyReflect.Practice;

public class Teacher {
    private String name;
    private double salary;

    public Teacher() {
    }

    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }
}

7.总和案例二 --- 利用反射动态的创建对象和运行方法

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

package com.qcby.MyReflect.Practice2;

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 MyTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.读取配置文件中的信息
        Properties prop=new Properties();
        FileInputStream fileInputStream=new FileInputStream("prop.properties");
        prop.load(fileInputStream);
        fileInputStream.close();
        System.out.println(prop);
        //2.获取全类名和方法名
        String className = (String) prop.get("classname");
        String methodName=(String) prop.get("method");
        System.out.println(className+"  "+methodName);
        //3.利用反射创建对象并运行方法
        Class clazz = Class.forName(className);
        //获取构造方法
        Constructor declaredConstructor = clazz.getDeclaredConstructor();
        Object obj = declaredConstructor.newInstance();
        System.out.println(obj);

        //获取成员方法并运行
        Method declaredMethod = clazz.getDeclaredMethod(methodName);
        declaredMethod.setAccessible(true);
        declaredMethod.invoke(obj);
    }
}

        配置文件-  prop.properties

classname=com.qcby.MyReflect.Practice2.Student
method=study

        Student类:

package com.qcby.MyReflect.Practice2;

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

    public Student() {
    }

    public Student(String name, int age) {
        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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public void study(){
        System.out.println(this.name+"正在学习");
    }
}

        Teacher类:

package com.qcby.MyReflect.Practice2;

public class Teacher {
    private String name;
    private double salary;

    public Teacher() {
    }

    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }
    public void teach(){
        System.out.println(this.name+"正在教书");
    }
}

8.总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值