Java反射

反射:框架设计的灵魂

  • 框架:半成品软件。可以在框架的基础上进行开发,简化编码

  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制

    • 好处:可以在程序运行中,操作这些对象。

    • 可以解耦,提高程序的可扩展性

Java代码在计算机中运行的三个阶段

在这里插入图片描述

获取Class对象的三个方式:

  1. Class.forName(“全类名”)

    *多用于配置文件,将类名定义在配置文件中,返回class对象

  2. 类名.class:通过类名的属性class获取

    *多用于参数的传递

  3. 对象.getClass():getClass()方法在Object类中定义着。

    *多用户对象的获取字节码的方式

    package domian;
    
    public class Person {
        private String name;
        private int 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 Person() {
    
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    public class ReflectDemo1 {
        public static void main(String[] args) throws Exception {
            //1.Class.forName("全类名")
            Class cls1= Class.forName("domian.Person");
            System.out.println(cls1);  //class domian.Person
            //2.类名.class
            Class cls2 = Person.class;
            System.out.println(cls2);  //class domian.Person
            //3.对象.getClass()
            Person person = new Person();
            Class cls3=person.getClass();
            System.out.println(cls3);  //class domian.Person
    
            System.out.println(cls1==cls2);//true
            System.out.println(cls1==cls3);//true
        }
    }
    

    结论:

    同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式

*Class对象的使用

​ *获取功能:

  1. 获取成员变量们

    • Field[] getFields() 获取所有public的成员变量

    • Field getField(String name) 获取单个public的成员变量

    • Field getDeclaredField(String name) 获取单个成员变量,不考虑修饰符

    • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符

  2. 获取构造方法们

    • Constructor<?>[] getConstructors()

    • Constructor getConstructor(类<?>… parameterTypes)

    • Constructor<?>[] getDeclaredConstructors()

    • Constructor getDeclaredConstructor(类<?>… parameterTypes)

  3. 获取成员方法们

    • Method getMethod(String name, 类<?>… parameterTypes)

    • Method[] getMethods()

    • Method getDeclaredMethod(String name, 类<?>… parameterTypes)

    • Method[] getDeclaredMethods()

  4. 获取类名

    • String getName()

*Field:成员变量

​ *操作:

​ 1.设置值

​ *void set(Object obj,object value)

​ 2.获取值

​ *get (Object obj)

​ 3.忽略访问修饰权限符的安全检查

​ *setAccessible(true):暴力反射

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

    public String a;
    protected String b;
    String c;
    private String d;

    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 Person() {

    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
}
public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        //获取Person的Class对象
        Class personClass= Person.class;
        /**
         * 获取成员变量们
         *Field[]  getFields()
         *Field getField(String name)
         *
         *Field getDeclaredField(String name)
         *Field[] getDeclaredFields()
         */
        //1.Field[]  getFields()
        Field[] fields =personClass.getFields();
        for (Field field:fields){
            System.out.println(field);  //public java.lang.String domian.Person.a
        }

        //2.Field getField(String name)
        Field a = personClass.getField("a");
        System.out.println(a);

        //获取成员变量a的值
        Person p=new Person();
        Object value = a.get(p);
        System.out.println(value);

        //设置值
        a.set(p,"张三");
        System.out.println(p);
        
        //Field[] getDeclaredFields()
        Field[] declaredFields = personClass.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println(declaredField);
        }
        //Field getDeclaredField(String name)
        Field d=personClass.getDeclaredField("d");
        //忽略访问权限修饰符的安全检查
        d.setAccessible(true);  //暴力反射
        Object value2=d.get(p);
        System.out.println(value2);


    }
}

*Constructor:构造方法

​ *创建对象:

​ * T newInstance()

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        //获取Person的Class对象
        Class personClass= Person.class;
        /**
         获取构造方法们

         - Constructor<?>[] getConstructors()

         - Constructor<T> getConstructor(类<?>... parameterTypes)

         - Constructor<?>[] getDeclaredConstructors()

         - Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
         */
        //Constructor<T> getConstructor(类<?>... parameterTypes)
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象
        Object person = constructor.newInstance("张三", 23);
        System.out.println(person); //Person{name='张三', age=23, a='null', b='null', c='null', d='null'}


        //空参数创建
        Constructor constructor1 = personClass.getConstructor();
        Object person1 = constructor1.newInstance();
        System.out.println(person1); //Person{name='null', age=0, a='null', b='null', c='null', d='null'}
        //简化的空参创建对象
        Object o=personClass.newInstance();
        System.out.println(o);//Person{name='null', age=0, a='null', b='null', c='null', d='null'}
    }
}

*Method:方法对象

​ *执行方法:

​ *Object invoke(object obj,Object… args)

​ *获取方法名称:

​ *String getName()

*获取类名String getName()

public void eat(){
    System.out.println("eat...");
}
public void eat(String food){
    System.out.println("eat..."+food);
}
public class ReflectDemo4 {
    public static void main(String[] args) throws Exception {
        //获取Person的Class对象
        Class personClass = Person.class;
        /**
         - Method getMethod(String name, 类<?>... parameterTypes)
         - Method[] getMethods()

         - Method getDeclaredMethod(String name, 类<?>... parameterTypes)
         - Method[] getDeclaredMethods()
         */
        //获取指定方法的名称
        Method eat_method=personClass.getMethod("eat");
        //执行方法
        Person person=new Person();
        eat_method.invoke(person);

        Method eat2_method=personClass.getMethod("eat",String.class);
        eat2_method.invoke(person,"饭");

        //获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for(Method method:methods){
            System.out.println(method); //也打印从Object继承的方法
            //获取方法的名称
            String name = method.getName();
            System.out.println(name);
        }

        //获取类名
        String name = personClass.getName();
        System.out.println(name);  //domian.Person

    }
}

*案例:

​ *需求:写一个“框架",可以帮我们创建任意类的对象,并且执行其中任意方法

​ *实现:

​ 1.配置文件

​ 2.反射

​ *步骤:

​ 1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中

​ 2.在程序中加载读取配置文件

​ 3.使用反射技术来加载类文件进内存

​ 4.创建对象

​ 5.执行方法

在src包下创建一个domain包,下面创建两个类

package domian;
public class Student {
    public void sleep(){
        System.out.println("sleep...");
    }
}
package domian;
public class Person {
    public void eat(){
        System.out.println("eat...");
    }
}

在src下创建一个pro.properties的文件,存放包名和方法名

className=domian.Student
methodName=sleep

创建一个类测试

package reflect;

import domian.Person;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectTest {
    //创建任意类的对象,可以执行任意方法
    public static void main(String[] args) throws Exception {
        //1.加载配置文件
        //1.1创建Properties对象,Properties实际上是Map的一个子类
        Properties pro = new Properties();
        //1.2加载配置文件,转化为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();  //加载进内存
        InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
        pro.load(resourceAsStream);

        //2.获取配置文件中的定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3.加载该类进内存
        Class cls = Class.forName(className);
        //4.创建对象
        Object o = cls.newInstance();
        //5.获取方法对象
        Method method = cls.getMethod(methodName);
        //6.运行方法
        method.invoke(o);
    }
}

运行代码:sleep…

修改pro.properties

className=domian.Person
methodName=eat

运行代码:eate…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值