java反射机制

反射机制

Java Reflection

①反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性以及方法。反射在设计和框架底层都会到。

②加载类之后,在堆中就产生一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射。

查看源图像

反射相关的主要类

java.lang.Class:代表一个类,Class对象表示某个类加载在堆中的对象

java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法

java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量

java.lang.reflect.Consturtor:代表类的构造方法,Constructor对象表示构造器

 Class类

class也是类,因此也继承Object类

Class类对象不是new,而是系统创建的(ClassLoader)类加载时创建

对于某个类的Class类对象,在内存中只有一份,因为类只加载一次

每个类的实例都会记得自己是由哪个Class实例所生成

通过Class可以完整地得到一个类的完整结构,通过一系列API

Class对象是存放在堆中

类的字节码二进制数据,是放在方法区(元数据)。

获取Class对象

①前提:已知一个类的全名类,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException异常。

使用方法如下:

Class cls = Class.forName("com.xiaoha.reflect.Cat");

应用场景:多用于配置文件,读取类全路径,加载类。

②前提:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高。

使用方法如下:

Class cls  = Cat.class;

应用场景:多用于参数传递,比如通过反射得到对应构造器对象。

③前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象。

使用方法如下:

        Cat cat = new Cat();
        Class cls  = cat.getClass();
        System.out.println(cls);

④其他方法

        ClassLoader cl  = new Test04().getClass().getClassLoader();
        Class cls = cl.loadClass("com.xiaoha.annimal.Cat");

⑤基本数据(int,char,boolean,float,double,byte,long,short)方式得到对应Class类对象

Class cls  = 基本数据类型.class

⑥基本数据类型对应的包装类,可以通过.type得到Class对象

Class cls =包装类.TYPE (得到数据类型)

反射中的常见方法

①第一组:java.lang.Class类

  • getName:获取全类名
  • getSimpleName:获取简单类名
  • getFields:获取所有public修饰的属性,包含本类以及父类的
  • getDeclaredFields:获取本类所有属性,只有本类的属性
  • getMethods:获取所有所有public修改的方法,包含本类以及父类
  • getDeclaredMethod:获取本类所有方法,只有本类的方法
  • getConstructors:获取所有public修饰的构造器,包含本类
  • getDeclareConstructors:获取本类中所有构造器
  • getPackage:以Package形式返回信息
  • getSuperClass:以Class形式返回父类信息
  • getInterfaces:以Class[]形式返回接口信息
  • getAnnotations:以Annotation[]形式返回注解信息

②第二组 java.lang.reflect.Field类 

  • getModifiers:以int形式返回修饰符
  • 默认修饰符:0 ,public:1 ,private:2 , protect:4  ,static:8 ,final:16
  • 出现两个修改符时输出结果是两个修饰符的值的累加
  • getType:以Class形式返回类型
  • getName:返回属性名

③第三组 java.lang.reflect.Method类 

  • getModifiers:以int形式返回修饰符
  • 默认修饰符:0 ,public:1 ,private:2 , protect:4  ,static:8 ,final:16
  • 出现两个修改符时输出结果是两个修饰符的值的累加
  • getType:以Class形式返回类型
  • getName:返回属性名
  • getParmeterTypes:以Class[]返回参数类型数组

④第四组 java.lang.reflect.Constructor类 

  • getModifiers:以int形式返回修饰符
  • 默认修饰符:0 ,public:1 ,private:2 , protect:4  ,static:8 ,final:16
  • 出现两个修改符时输出结果是两个修饰符的值的累加
  • getType:以Class形式返回类型
  • getName:返回属性名
  • getParmeterTypes:以Class[]返回参数类型数组

创建对象方法

方式一:调用类中的public修饰的无参构造器 

方式二:调用类中的指定构造器

Class类相关方法:

newInstance:调用类中的无参构造器,获取对应类的对象

通过下面两行代码,通过调用有参构造器

getConstruct(Class...clazz)/getDeclaredConstructor(Class...clazz)

newInstance(Object...obj):调用构造器

使用如下:

//获取构造器 
Constructor constructor = cls.getConstructor(String.class);
        System.out.println(constructor);
//调用构造器
        Cat cat1 = (Cat) constructor.newInstance("123");
        System.out.println(cat1);

反射调用方法

使用invoke(Object obj,实参)方法调用方法

实现方法如下:


public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, 
InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.xiaoha.reflect.Dog");
        Dog dog = (Dog) cls.newInstance();
        Method play = cls.getMethod("play");
        play.invoke(dog);
    }
}

class Dog{
    public Dog(){

    }

    public void play(){
        System.out.println("狗狗喜欢玩球");
    }
}

反射优缺点

优点:

可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支持,本质就是解耦,提高程序的可扩展性。

缺点:

使用反射机制是解释执行,对执行速度有影响。

但是通过setAccessible(true)方法进行提高速度,简称暴力反射。

采用1亿次进行调用方法进行测试。
传统方法被调用了3
反射方法调用=115
反射方法调用优化后=92

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值