• 转|java反射方法和使用详解


    概述

      反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。反射是框架设计的灵魂,它功能很强大,我们学会了它就可以搭配很多东西一起使用,下面一起来学习使用反射吧!

      使用Book类来练习反射,代码如下:
       

    public class Book {
        private Integer id;
        private String name;
        public Integer age;
    
        public Book() {
            System.out.println("Public 无参构造函数");
        }
        public Book(String name) {
            System.out.println("Public 带参构造函数");
        }
        private Book(String name,Double price){
            System.out.println("Private 带两参构造函数");
        }
    
        public void printAll(){
            System.out.println("公开方法");
        }
    
        private void printOne(){
            System.out.println("私有方法");
        }
    }
    

    获取类的三种方式

    若想使用反射,必须先得到代表类的字节码的Class对象,Class类用于表示.class文件(字节码)。

    第一种:使用Class.forName

    使用 Class.forName(String classPath)时,请求参数classPath写需要反射的类名,一般是以包名.类名。

     try {
        Class clz = Class.forName("com.entity.Book");
      } catch (ClassNotFoundException e) { 
        e.printStackTrace();
      }
    

    第二种:使用类名.class

    使用这种方法时,需要知道有这个类。

    Class clz = Book.class;

    第三种:对象.getClass()

    使用的前提是对象已经被实例化。

    Book book = new Book();
    Class clz = book.getClass();   
        
    总结:这三种方法各有千秋,我们一般使用第一种方式,在开发中,请按照自己的实际需求去使用。

    获取构造函数

    getDeclaredConstructors(); 获取所有的构造函数
    getDeclaredConstructor(参数类型); 获取一个指定参数类型的构造函数
    getConstructors(); 获取所有公共的构造函数
    getConstructor(参数类型); 获取一个指定参数类型的、public修饰的构造函数
     
    使用方法:

      //获取所有的构造函数
            Constructor[] constructors = clz.getDeclaredConstructors();
            //获取单个所有的构造函数
            try {
                Constructor constructor =               
                clz.getDeclaredConstructor(String.class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
    
            //获取所有的公开构造函数
            Constructor[] constructors1 = clz.getConstructors();
            //获取单个公开构造函数
            try {
                Constructor constructor = clz.getConstructor(String.class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }        
    

    获取名字

    返回类型:String,可以反射类名、方法名和构造函数名等等。

    getName();    //获取全名  例如:com.bean.Book
    getSimpleName()  //获取类名 例如:Book
        

    Class clz = Book.class;
    String name1 = clz.getName();
    String name2 = clz.getSimpleName();
    

    获取包

       
    返回类型:Package
       

    Package aPackage = clz.getPackage();

    获取接口

     
    getInterfaces(),
    返回类型:Class[] interfaces

    Class[] interfaces = clz.getInterfaces();

    获取父类/超类

    getSuperclass()
    返回类型:Class superclass
       

    Class superclass = clz.getSuperclass();

    实例化对象

    语法糖:newInstance(Object initargs)
       
    第一种方式
      

    Class clz = Book.class;
      Object obj =  clz.newInstance(); //将创建一个无参book对象
     
    第二种方式

    Class clz = Book.class;
    Constructor constructor = clz.getDeclaredConstructor();   //获得无参构造
    Object obj = constructor.newInstance();    //实例化book对象

    设置访问属性

       

    clz.setAccessible(true)  //可访问
    clz.setAccessible(false)  //不可访问

    //默认是false   
    Field id = clz.getField("age"); //age字段  
    id.setAccessible(true); //设为可访问
    id.setAccessible(false);    //设为不可访问
    

    获取方法

       

    • getMethods():获取所有的公共方法,注意,它会将系统自带的方法也得到
    • getMethod(String name):获取单个公共方法,由参数指定方法名
    • getDeclaredMethods():获取所有的方法,注意:它不会获取系统自带的方法
    • getDeclaredMethod(String name):获取单个的所有方法 参数是可指定方法名
       Class clz = Class.forName("Book");
       Method[] methods = clz.getMethods();    //获取所有的公共方法
       for (Method method : methods) {
           System.out.println(method.getName());
       } 
        Method method = clz.getMethod("printAll"); // 获取单个公共方法
        method.invoke(clz.newInstance(), null); // 调用方法
    
    Method[] methods = clz.getDeclaredMethods(); //获取所有方法
    for (Method method1 : methods) {
       System.out.println(method1.getName());
    }
    Method method1 = clz.getDeclaredMethod("printOne");    //获取单个公共方法
    System.out.println(method1.getName());
    

    调用方法

    method.invoke(Object obj,Object... args)
    obj:如果是实例方法,则传入该方法的类对象;如果是静态方法,写null。
    args:方法的参数值,没有写null,或不写都行

    // 获取单个的public方法,无法获取private方法
    Method method = clz.getMethod("printAll");
    //使用方法
    method.invoke(clz.newInstance(),null); 
    

    反射面试题

    Q:Java反射创建对象效率高,还是new创建对象的效率高?
    A: 通过new创建对象的效率比较高。通过反射时,先查找类资源,使用类加载器创建,过程比较繁琐,所以效率较低。

    Q:Java反射的作用是?
    A: 反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。

    Q:哪里会用到反射机制?
    A: 加载MySQL的驱动类,如Hibernate、MyBatis等框架中会使用。动态代理设计模式也采用了反射机制。

    例1:加载MySQL的驱动类,Class.forName('com.mysql.jdbc.Driver.class');
    例2:使用反射机制,根据这个字符串获得某个类的Class实例;

    Q:反射机制的优缺点是?
    A: 优点 能够运行时动态获取类的实例,提高灵活性;与动态编译结合。可以解耦,提高程序的可扩展性。

    缺点 使用反射性能较低,需要解析字节码,将内存中的对象进行解析;相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)

    提升性能解决方案:通过setAccessible(true),关闭JDK的安全检查来提升反射速度。第一次反射后,会有缓存,下次反射会快很多。ReflflectASM工具类,通过字节码生成的方式加快反射速度

    结束语

      对于Java反射,您怎么看?欢迎参与话题互动讨论,分享你的观点和看法, 评论区留言哦,喜欢小编文章的朋友请点赞,谢谢您的参与!

    Reference

    [1] https://www.cnblogs.com/liweixml/p/11462813.html

  • 相关阅读:
    树——题解汇总
    element ui实现手动上传文件,且只能上传单个文件,并能覆盖上传
    浏览器缓存
    websocket协议
    session
    cookie
    作用域插槽
    时间格式化函数
    Neo4j快速入门
    线性空间
  • 原文地址:https://www.cnblogs.com/east7/p/15887320.html
Copyright © 2020-2023  润新知