资讯专栏INFORMATION COLUMN

Java 反射(Reflection)

shengguo / 3076人阅读

摘要:效率运行效率使用反射减低程序的运行效率。开发效率由于反射运用到各个框架中,大大加快了开发的效率。

反射的核心就是Class对象,每一个类被jvm加载都会有一个对应的class对象,这个class对象包含了这个类的结构信息,反射就是会通过反射api反复操作这个class对象(属性,方法,注解,构造器,泛型),但是反射会降低程序的运行效率,比普通方法要慢30倍,通过setAccessble(true) 跳过安全检查(可以读取private 的属性),提高4倍的程序运行效率
反射将普遍运用到各个类型的框架。
效率:
1,运行效率:使用反射 减低程序的运行效率。
2,开发效率:由于反射运用到各个java框架中,大大加快了开发的效率。

下面就是一些简单的例子来具体阐述反射的一些特点:

 package com.mk;
     public class Test{
     public static void main(String [] args){
        Foo foo = new Foo();//foo 表示foo的实例对象
        //任何一个类都是class的实例对象,有3钟表达方式
        //1,任何一个类都有一个隐含的成员变量Class
        Class c1 = Foo.class;
        //2,通过getClass方法获得
        Class c2 = foo.getClass();
        //不管是c1还是c2都代表Foo类的类类型,一个类只能是Class的实例对象
        System.out.println(c1==c2);//true
        //3,第三种表达方式
        Class c3 = null;
        try {
            c3 = Class.forName("com.mk.Foo");//类的全称
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c2==c3);//true

        //可以通过类的类类型创建该类的对象实例
        try {
            Foo f1 = (Foo) c1.newInstance();//需要无参数的构造方法
            f1.print();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
     }
    }
       class Foo{
        void print(){
        System.out.println("print parent");
       }
    }

动态加载类
new 创建对象 是静态的加载类,在编译的时刻就需要加载 所有可能使用到的类
通过动态的加载类可以解决这个问题
运行时刻加载 就是想用哪个就加载哪个,不用就不加载。
通过反射api 操作类的方法

method.invoke(对象,参数列表)
    package com.mk;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    public class Test1 {
    public static void main(String[]args) throws
      NoSuchMethodException,      
        InvocationTargetException,
     IllegalAccessException {
        A a1 = new A();
        Class c = a1.getClass();//得到类类型
        Method m = c.getMethod("print",int.class,int.class);
        //方法的反射操作
        //a1.print(10,20);方法的反射操作是用m对象进行方法的调用,和a1.print()的调用效果相同
        //方法如果没有返回值返回null,如果有返回值就返回具体的值
        //Object obj = m.invoke(a1,new Object[]{10,20});
        //或者有几个参数传几个参数
        Object ob = m.invoke(a1,10,20);
      }
     }
    class A{
    public void print(int a,int b){
        System.out.println(a+b);
      }
    }

通过class,method来认识泛型的本质

 package com.mk;
    java.lang.reflect.Method;
    java.util.ArrayList;
    class test2 {
    public static void main(String[] arg){
        ArrayList list = new ArrayList();
        ArrayList ls = new ArrayList();
        ls.add("hello");
        //ls.add(20);//泛型检查错误,20是加不进去的
        Class c1 = list.getClass();
        Class c2 = ls.getClass();
        System.out.println(c1==c2);//反射的操作都是编译之后的操作
        /**
         * c1==c2 结果返回true说明编译之后的集合的泛型是去泛型化的,java中
         * 集合的泛型,是防止错误输入的,只有在编译阶段是有效的,在其他的阶段都是
         * 无效的
         * 可以通过方法的反射来操作 绕过编译
         */
          try {
            Method m = c2.getMethod("add",Object.class);
            m.invoke(ls,100);
            System.out.println(ls.size());
            System.out.println(ls);//[hello, 100] 结果int 是可以加进去的
         } catch (Exception e) {
            e.printStackTrace();
        }

      }
    }

如何通过反射api 操作属性,构造器

public class User {
    private int id;
    private String name;
    //javabean 无参构造器,用于java的反射机制的初始化
    public User() {
        
    }
    public User(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
        Class clazz 
             = Class.forName("com.test.reflection.Bean.User");
        //获取名字
        System.out.println(clazz.getName());//包名+类名
        System.out.println(clazz.getSimpleName());
        //获取属性方法(重载,根据参数找方法)
        Field [] fs = clazz.getDeclaredFields();
        System.out.println(fs.length);//获取所有的fields,不论public还是private
        Field [] field = clazz.getFields();//获取公共属性
        for(Field fields:fs){
            System.out.println("属性:"+fields);
        }
        //获取方法信息
        Method [] method 
             = clazz.getDeclaredMethods();//获取所有的方法
        Method m1 = 
                clazz.getDeclaredMethod("getName",null);
        for(Method m:method){
            System.out.println("方法:"+m);
        }
        //获取构造器
        Constructor c1 = clazz.getConstructor(null);
        System.out.println("无参构造器:"+c1);
        Constructor c2 = clazz.getConstructor(int.class,String.class);
        System.out.println("有参构造器:"+c2);
        Constructor [] constructors 
            = clazz.getDeclaredConstructors();
        for(Constructor c:constructors){
            System.out.println("构造器:"+c);
        }
        
        
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

 //动态操作构造器
      try {
        //通过反射api调用构造方法
        User user = (User) clazz.newInstance();//其实是调用了user的无参构造方法
        System.out.println(user);
        //调用有参构造器
        Constructor constructor 
            = clazz.getDeclaredConstructor(int.class,String.class);
        User u 
            = (User) constructor.newInstance(12,"michael");
        System.out.println(u.getName());
        //通过反射api调用普通的方法
        User u1 
             = (User)clazz.newInstance();
        Method method 
             = clazz.getDeclaredMethod("setName", String.class);
        method.invoke(u1, "mike");//setName("mike");
        System.out.println(u1.getName());
        //通过反射操作属性
        User u2 = (User) clazz.newInstance();
        Field  f 
             = clazz.getDeclaredField("name");//属性必须是public的
        f.setAccessible(true);//不需要安全检查,直接访问
        f.set(u2, "mike2");
        System.out.println(u2.getName());//通过反射直接读动态值
        System.out.println(f.get(u2));
    } catch (Exception e) {
        e.printStackTrace();
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64741.html

相关文章

  • ReflectionJava反射机制的应用场景

    近期在维护公司项目的时候遇到一个问题,因为实体类中的 set 方法涉及到了业务逻辑,因此在给对象赋值的过程中不能够使用 set 方法,为了实现功能,所以采用了反射的机制给对象属性赋值,借此机会也了解了反射的一些具体用法和使用场景,分以下两点对反射进行分析: 反射的优势和劣势 反射的应用场景 反射的优势和劣势   个人理解,反射机制实际上就是上帝模式,如果说方法的调用是 Java 正确的打开方式...

    浠ラ箍 评论0 收藏0
  • Java动态性(2) - 之反射机制(Reflection)

    摘要:的动态性反射机制动态编译动态执行代码动态字节码操作动态语言程序运行时可以改变程序得结构或变量类型典型语言等如下代码不是动态语言但有一定的动态性我们可以利用反射机制字节码操作获得类似动态语言的特性的动态性让编程的时候更加灵活反射机制反射机制指 1.Java的动态性 反射机制 动态编译 动态执行JavaScript代码 动态字节码操作 2.动态语言 程序运行时,可以改变程序得结构或变量...

    妤锋シ 评论0 收藏0
  • ReflectionJava反射机制基础

    摘要:反射机制是什么反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意一个方法和属性这种动态获取的信息以及动态调用对象的方法的功能称为语言的反射机制反射机制能做什么反射机制主要提供了以下功 反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种...

    hizengzeng 评论0 收藏0
  • Java 反射教程

    摘要:反射非常强大和有用。另外,反射可以用在映射结果集的列名到对象的方法。本教程将深入介绍反射。本教程还将清除一些关于范型信息在运行时可用性的认知混淆。类对象使用反射时,起点通常是需要使用反射检视的类的对象。 Java反射可以在运行时检视类、接口、属性和方法,而无需在编译时知道类名、方法名等等。它也同样使用反射支持实例化新的对象、调用方法和get/set属性值。 Java反射非常强大和有用...

    klivitamJ 评论0 收藏0
  • 通过Class.newInstance()和Constructor.newInstance()两种反

    首先两种方式在源码里所在的位置: Class.newInstance() → Inside java.lang 包Constructor.newInstance() → Inside java.lang.reflect 包 使用方法: Class.newInstance(): Class.forName(HelloWorld).newInstance(); 或者 HelloWorl...

    dreamans 评论0 收藏0

发表评论

0条评论

shengguo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<