Java基础-反射机制

上一篇 <<<设计模式总览
下一篇 >>>代理模式(Proxy Pattern)


1.反射机制获取类的三种方法

//第一种方式:  
Classc1 = Class.forName("Employee");  
//第二种方式:  
//java中每个类型都有class 属性.  
Classc2 = Employee.class;  
//第三种方式:  
//java语言中任何一个java对象都有getClass 方法  
Employee e = new Employee();  
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)

三种方式取得的结果都是一样,就像Spring容器通过名字、bean的class等获取结果一样,都存放在堆中的唯一空间。
反射操作就是利用堆中的class信息进行实例化及相关操作。

优点:能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
缺点:
1.反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
2.反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

2.利用反射机制创建对象

Class<?> forName = Class.forName("com.jarye.entity.User");
// 实例化无参构造函数
Object newInstance = forName.newInstance();
// 实例化有参构造函数
Class<?> forName = Class.forName("com.jarye.entity.User");
Constructor<?> constructor = forName.getConstructor(String.class, String.class);
User newInstance = (User) constructor.newInstance("123", "123");

3.反射常用方法

反射获取构造方法
(1)批量获取的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
(2)单个获取的方法,并调用:
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
(3) 调用构造方法:
Constructor-->newInstance(Object... initargs)
newInstance是 Constructor类的方法(管理构造函数的类)
api的解释为:newInstance(Object... initargs) ,使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象,并为之调用。
获取成员变量并调用:
  1.批量的
    1.1.Field[] getFields():获取所有的"公有字段"
    1.2.Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
  2.获取单个的:
   2.1.public Field getField(String fieldName):获取某个"公有的"字段;
   2.2.public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
 3.设置字段的值 需要注意权限问题:
  3.1.Field --> public void set(Object obj,Object value):
  3.2.参数说明:
  3.3.obj:要设置的字段所在的对象;
获取成员方法并调用:
 1.所有的方法:
   1.1.public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
   1.2.public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
  2.获取单个的方法:
    2.1.public Method getMethod(String name,Class<?>... parameterTypes):
                    参数:
                        name : 方法名;
                        Class ... : 形参的Class类型对象
        public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
  
     调用方法:
        Method --> public Object invoke(Object obj,Object... args):
                    参数说明:
                    obj : 要调用方法的对象;

4.反射底层原理

反射机制底层其实走的是MethodAccessor,分为2步:
a、访问控制检查(判断该方法的修饰符modifiers是否为public)
b、调用MethodAccessor.invoke()实现方法执行,创建MethodAccessor有两种选择

  • sun.reflect.noInflation的设置为true,则ReflectionFactory利用MethodAccessor的字节码生成类MethodAccessorGenerator直接创建一个代理类,通过间接调用原方法完成invoke()任务【使用Java代码生成】
  • sun.reflect.noInflation的设置为false或未达到设置值(默认15次)时,创建DelegatingMethodAccessorImpl委托类,并将执行invoke()方法的具体内容交由NativeMethodAccessorImpl实现【使用Native代码生成】
参数 说明
sun.reflect.noInflation 是控制是否立即进行类膨胀
sun.reflect.inflationThreshol 类膨胀阈值
可以通过启动参数-Dsun.reflect.noInflation=false -Dsun.reflect.inflationThreshold=15

5.反射应用

<dependencies>
        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.10</version>
        </dependency>
    </dependencies>
public class ReflexUtils {
    public static Set<Class> getInterfaceImpls(Class c) {
        Reflections reflections = new Reflections("cn.jarye");
        //Filter是个接口,获取在指定包扫描的目录所有的实现类
        Set<Class> classes = reflections.getSubTypesOf(c);
        return classes;
    }
    public static void main(String[] args) {
        //        ReflexUtils.getInterfaceImpls(MsgObServer.class)
        //        interfaceImpls.forEach((t) -> {
        //            System.out.println("name:" + t.getSimpleName());
        //        });
    }
}

相关文章链接:
<<<Java基础-字节码技术
<<<Java基础-创建对象的方式汇总
<<<Java基础-对象布局
<<<Java基础-对象的引用类型
<<<Class文件分析一个类为啥最多支持65535个接口
<<<为什么重写equals还要重写hashcode方法
<<<如何自定义注解
<<<十大经典排序算法汇总-动画演示
<<<JDK8十大新特性

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345