反射:框架设计的灵魂

反射这个概念之前听说过,但却是第一次真正接触,记录下学习过程。


一、概述

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

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

这样的概念有些抽象,不妨先了解下java代码在计算机中经历的三个阶段:

①Source源代码阶段:

//Person.java
public class Person{
    private String name;
    private int age;

    public Person(){}
    public void eat(){}
}

==>>javac编译

//Person.class

private String name;

private int age;

public Person(){}
public void eat(){}

==>>类加载器ClassLoader(将Person.class字节码文件加载到内存)

②Class类对象阶段:

//Class类对象

成员变量  Field[] fields
构造方法  Constructor[] cons
成员方法  Method[] methods

==>>创建对象

③Runtime运行时阶段:

Person对象

new Person();

通常我们只关注第一和第三阶段,那么第二阶段将类的成员变量封装为Field对象,将构造方法封装为Constructor对象,将成员方法封装为Method对象就是我们说的反射机制。

那么为什么要用反射呢?

反射的好处:

1、可以在程序运行过程中,操作这些对象;

     例如定义一个字符串,在运行中将String类加载到内存中,通过“.”操作其提供的方法都可直接使用。

2、可以解耦,提高程序的可扩展性。

二、获取Class类对象

方式:1、Class.forName("全类名"):将字节码文件加载进内存,返回Class对象。

                       多用于配置文件,将类名定义在配置文件中。读取文件,加载类。

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

                       多用于参数的传递。

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

                       多用于对象的获取字节码的方式。

结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

public class Reflectdemo{
    public static void main(String[] args) throws Exception {
        //1、Class.forName("全类名")
        Class cls1=Class.forName("cn.itcast.demo.Person");
        System.out.println(cls1);//class cn.itcast.demo.Person
        //2、类名.class
        Class cls2= Person.class;
        System.out.println(cls2);//class cn.itcast.demo.Person
        //3、对象.getClass()
        Person p=new Person();
        Class cls3=p.getClass();
        System.out.println(cls3);//class cn.itcast.demo.Person

        //比较三个对象
        System.out.println(cls1==cls2);//true
        System.out.println(cls1==cls3);//true

    }
}

Class对象功能:

获取功能:1、获取成员变量们;  

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

                                Field getField(String name) :获取指定名称的public修饰的成员变量

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

                                Field getDeclaredField(String name)

                        2、获取构造方法们;

                                Constructor<?>[] getConstructors()

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

                                Constructor<?>[] getDeclaredConstructors():返回结果没有参数类型的过滤

                                Constructor<T> getDeclaredConstructor(类<?>... parameterTypes):返回指定参数类型的所有构造器

                        3、获取成员方法们;

                                Method[] getMethods()

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

                                Method[] getDeclaredMethods()

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

                       4、获取类名

                                String getName()

Field:成员变量

                   操作:1、设置值   void set(Object obj,Object value)

                             2、获取值   get(Object obj)

                             3、忽略访问权限修饰符的安全检查   setAccessible(true)//暴力反射

public class Reflectdemo{

    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass=Person.class;
        //1.Field[] getFields() :获取所有public修饰的成员变量
        Field[] fields=personClass.getFields();
        for(Field field:fields){
            System.out.println(field);
        }
        System.out.println("------------------");
        //2.Field getField(String name)
        Field a=personClass.getField("a");
          //获取变量a的值
        Person p=new Person();
        Object value=a.get(p);
        System.out.println(value);
          //设置a的值
        a.set(p,22);
        System.out.println(p);
        System.out.println("------------------");
        //3.Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
        Field[] declaredFields=personClass.getDeclaredFields();
        for(Field declaredField:declaredFields){
            System.out.println(declaredField);
        }
        //4.Field getDeclaredField(String name)
        Field d=personClass.getDeclaredField("d");
          //忽略访问权限修饰符的安全检查
        d.setAccessible(true);//暴力反射
        Object value2=d.get(p);
        System.out.println(value2);

    }
}

Constructor:构造方法

                  创建对象:T newInstance(Object... initargs)   

                               如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

public class Reflectdemo{

    public static void main(String[] args) throws Exception {
        Constructor constructor=personClass.getConstructor(String.class,int.class);
        System.out.println(constructor);
        //创建对象
        Object person=constructor.newInstance("张三",13);
        System.out.println(person);
        
        System.out.println("----------------");

        Constructor constructor1=personClass.getConstructor();
        System.out.println(constructor1);
        //创建对象
        Object person1=constructor1.newInstance();
        System.out.println(person1);
          //等同于
        Object o=personClass.newInstance();
        System.out.println(o);
   }
}

Method:方法对象

                 执行方法:  Object invoke(Object obj,Object... args)

                 获取方法名称:   String getName:获取方法名

public class Reflectdemo{

    public static void main(String[] args) throws Exception {
        //获取指定名称的方法
        Method eat_method=personClass.getMethod("eat");
        Person p=new Person();
        //执行方法
        eat_method.invoke(p);
        System.out.println("------------------------");

        Method eat_method2=personClass.getMethod("eat",String.class);
        //执行方法
        eat_method2.invoke(p,"饭");

        System.out.println("------------------------");

        //获取所有public修饰的方法
        Method[] methods=personClass.getMethods();
        for(Method method:methods){
            System.out.println(method);

            //String name=method.getName();
            //System.out.println(name);
        }
   }
}

获取类名

        //获取类名
        String className=personClass.getName();
        System.out.println(className);//cn.itcast.demo.Person

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值