Java - 反射机制

java的反射机制原理

一反射机制的概念:指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法.这种动态获取信息,以及动态调用对象方法的功能叫java语言的反射机制.java反射机制是围绕Class类展开的,在深入java反射原理之前,需要对类加载机制有一个大致的了解。jvm使用ClassLoader将字节码文件(class文件)加载到方法区内存中:Class clazz = ClassLoader.getSystemClassLoader().loadClass("com.mypackage.MyClass");可见ClassLoader根据类的完全限定名加载类并返回了一个Class对象,而java反射的所有起源都是从这个class类开始的。看个列子://1.获取类

 Class c = Class.forName("_12_CustomerService");

//获取某个特定的方法

//通过:方法名+形参列表

 Method m = c.getDeclaredMethod("login",String.class,String.class);

//通过反射机制执行login方法.

Object o = c.newInstance();

//调用o对象的m方法,传递"admin""123"参数,方法的执行结果是retValue

Object retValue = m.invoke(o, "admin","123");

System.out.println(retValue); //true

二.反射机制的作用

1.在运行时判断任意一个对象所属的类;

2.在运行时获取类的对象;

3.在运行时访问java对象的属性,方法,构造方法等。

三.反射机制的优点与缺点

首先要搞清楚为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。静态编译:在编译时确定类型,绑定对象,即通过。动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。 

反射机制的优点:可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象

反射机制的缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。

1.通过一个对象获得完整的包名和类名

添加一句:所有类的对象其实都是Class的实例。

class Demo{ //other codes...  } class hello{public static void main(String[] args) {Demo demo=new Demo();       System.out.println(demo.getClass().getName());}}

2.实例化Class类对象

public static void main(String[] args) {

Class<?> demo1=null;

Class<?> demo2=null;

Class<?> demo3=null;

try{

//一般尽量采用这种形式

 demo1=Class.forName("Reflect.Demo");

}catch(Exception e){

e.printStackTrace();

}

emo2=new Demo().getClass();

demo3=Demo.class;

System.out.println("类名称   "+demo1.getName());

System.out.println("类名称   "+demo2.getName());

System.out.println("类名称   "+demo3.getName());

【运行结果】:

类名称Reflect.Demo

类名称Reflect.Demo

类名称Reflect.Demo


3.通过Class实例化其他类的对象

class Person{

      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;

     }

     @Override

     public String toString(){

         return "["+this.name+"  "+this.age+"]";

     }

     private String name;

     private int age;

 }


 class hello{

     public static void main(String[] args) {

         Class<?> demo=null;

         try{

            demo=Class.forName("Reflect.Person");

         }catch (Exception e) {

             e.printStackTrace();

         }

         Person per=null;

         try {

            per=(Person)demo.newInstance();

         } catch (InstantiationException e) {

             // TODO Auto-generated catch block

             e.printStackTrace();

         } catch (IllegalAccessException e) {

             // TODO Auto-generated catch block

             e.printStackTrace();

         }

         per.setName("Rollen");

         per.setAge(20);

         System.out.println(per);

     }

 }

4.通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

package Reflect;


import java.lang.reflect.Constructor;


class Person{

    public Person() {


    }

    public Person(String name){

        this.name=name;

    }

    public Person(int age){

        this.age=age;

    }

    public Person(String name, int age) {

        this.age=age;

        this.name=name;

    }

    public String getName() {

        return name;

    }

    public int getAge() {

        return age;

    }

    @Override

    public String toString(){

        return "["+this.name+"  "+this.age+"]";

    }

    private String name;

    private int age;

}


class hello{

    public static void main(String[] args) {

        Class<?> demo=null;

        try{

            demo=Class.forName("Reflect.Person");

        }catch (Exception e) {

            e.printStackTrace();

        }

        Person per1=null;

        Person per2=null;

        Person per3=null;

        Person per4=null;

//取得全部的构造函数

        Constructor<?> cons[]=demo.getConstructors();

        try{

            per1=(Person)cons[0].newInstance();

            per2=(Person)cons[1].newInstance("Rollen");

            per3=(Person)cons[2].newInstance(20);

            per4=(Person)cons[3].newInstance("Rollen",20);

        }catch(Exception e){

            e.printStackTrace();

        }

        System.out.println(per1);

        System.out.println(per2);

        System.out.println(per3);

        System.out.println(per4);

    }

}

5.取得其他类中的父类

class hello{

    public static void main(String[] args) {

        Class<?> demo=null;

        try{

            demo=Class.forName("Reflect.Person");

        }catch (Exception e) {

            e.printStackTrace();

        }

//取得父类

        Class<?> temp=demo.getSuperclass();

System.out.println("继承的父类为:   "+temp.getName());

    }

}

//【运行结果】

//继承的父类为:   java.lang.Object

6.通过反射操作属性

class hello {

    public static void main(String[] args) throws Exception {

        Class<?> demo = null;

        Object obj = null;

        demo = Class.forName("Reflect.Person");

        obj = demo.newInstance();

        Field field = demo.getDeclaredField("sex");

        field.setAccessible(true);

field.set(obj, "男");

        System.out.println(field.get(obj));

}

7.通过反射调用其他类中的方法

class hello {

    public static void main(String[] args) {

        Class<?> demo = null;

        try {

            demo = Class.forName("Reflect.Person");

        } catch (Exception e) {

            e.printStackTrace();

        }

        try{

//调用Person类中的sayChina方法

            Method method=demo.getMethod("sayChina");

            method.invoke(demo.newInstance());

//调用Person的sayHello方法

            method=demo.getMethod("sayHello", String.class,int.class);

            method.invoke(demo.newInstance(),"Rollen",20);

        }catch (Exception e) {

            e.printStackTrace();

        }

    }

}

//【运行结果】:

//hello ,china

//Rollen  20

用几句话总结反射的实现原理:

1.反射类及反射方法的获取,都是通过从列表中搜寻查找匹配的方法,所以查找性能会随类的大小方法多少而变化;

2.每个类都会有一个与之对应的Class实例,从而每个类都可以获取method反射方法,并作用到其他实例身上;

3.反射也是考虑了线程安全的,放心使用;

4.反射使用软引用relectionData缓存class信息,避免每次重新从jvm获取带来的开销;

5.反射调用多次生成新代理Accessor, 而通过字节码生存的则考虑了卸载功能,所以会使用独立的类加载器;

6.当找到需要的方法,都会copy一份出来,而不是使用原来的实例,从而保证数据隔离;

7.调度反射方法,最终是由jvm执行invoke0()执行;

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