首页 > 编程语言 > 详细

java反射

时间:2020-12-19 18:13:57      阅读:35      评论:0      收藏:0      [点我收藏+]

Class类:

对象照镜子后可以得到的信息:

某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含 了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。

? Class本身也是一个类

? Class 对象只能由系统建立对象

? 一个加载的类在 JVM 中只会有一个Class实例

? 一个Class对象对应的是一个加载到JVM中的一个.class文件

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

? 通过Class可以完整地得到一个类中的所有被加载的结构

? Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的 Class对象

Class类常用方法

技术分享图片

 

 

 

 获取Class类实例方法:

1)Class clazz = String.class

2)Class clazz = 某类实例.getClass();

3)Class clazz = Class.forName(“java.lang.String”); //最为常用

拥有Class对象的类型:
各种类 基本数据类型 接口 数组 枚举 注解 

对于数组数组只要元素类型与维度一样,就是同一个Class

对这些基本类型Class延申参考https://www.cnblogs.com/jpfss/p/11382043.html

Class与class字节码的联系在类的加载阶段有体现:

加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时 数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载的 过程需要类加载器参与。

三种类加载器ClassLoader:

引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来装载核心类 库。该加载器无法直接获取

扩展类加载器:负责jre/lib/ext目录下的jar包或 – D java.ext.dirs 指定目录下的jar包装入工作库

系统类加载器:负责java –classpath 或 –D java.class.path所指的目录下的类与jar包装入工 作 ,是最常用的加载器

private Person(String name) {
        this.name = name;
    }

 

创建运行时类的对象:

1)无参构造器,类的构造器的访问权限需要足够:

直接调用Class对象的newInstance()方法,比较简单。

2)有参构造器,足够访问权限

先获取带有指定参数类型的构造器,在创建实例

Class clazz = Person.class;
//1.通过反射,创建Person类的对象
Constructor cons = clazz.getConstructor(String.class,int.class);
Object obj = cons.newInstance("Tom", 12);
Person p = (Person) obj;

3)有参构造器,私有权限

private Person(String name) {
        this.name = name;
    }

使用反射,强行开放权限(注意 Declared 后面马上解释)

Constructor cons1 = clazz.getDeclaredConstructor(String.class);
cons1.setAccessible(true);
Person p1 = (Person) cons1.newInstance("Jerry");

调用运行时类指定结构:

i 调用指定方法:

通过反射,调用类中的方法,通过Method类完成。步骤:

1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得 一个Method对象,并设置此方法操作时所需要的参数类型。

2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中 传递要设置的obj对象的参数信息。

技术分享图片

getMethod 返回所有public方法, getDeclaredMethod返回所有方法。

Object invoke(Object obj, Object[] args)

说明:

1.Object 对应原方法的返回值,若原方法无返回值,此时返回null

2.若原方法若为静态方法,此时形参Object obj可为null

3.若原方法形参列表为空,则Object[] args为null

4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。

private String showNation(String nation){
        System.out.println("我的国籍是:" + nation);
        return nation;
    }
Method showNation = clazz.getDeclaredMethod("showNation", String.class);
        showNation.setAccessible(true);
        String nation = (String) showNation.invoke(p1,"中国");//相当于String nation = p1.showNation("中国")
        System.out.println(nation);

ii 调用指定属性:

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和 get()方法就可以完成设置和取得属性内容的操作。

? public Field getField(String name) 返回此Class对象表示的类或接口的指定的 public的Field。

? public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。

获取到Filed后,执行Field上面的方法:

? public Object get(Object obj) 取得指定对象obj上此Field的属性内容,注意get不用传入Class对象

? public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1,"HanMeimei");
System.out.println(p1);

关于于setAccessible方法:

? Method和Field、Constructor对象都有setAccessible()方法。

? setAccessible启动和禁用访问安全检查的开关。

? 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。

? 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被 调用,那么请设置为true。 ? 使得原本无法访问的私有成员也可以访问

? 参数值为false则指示反射的对象应该实施Java语言访问检查。

一句话就是设置为True,私有就不私有了

 

反射最重要的应用是在动态代理,请移步:https://www.cnblogs.com/wangid3/p/14159821.html

 

java反射

原文:https://www.cnblogs.com/wangid3/p/14159834.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!