概述

  反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,都能够调用它的任意一个方法。在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

转|java反射方法和使用详解的更多相关文章

  1. JAVA反射概念及使用详解(超详细)

    JAVA反射概念及使用详解 一.什么是反射? 反射:框架设计的灵魂 框架:半成品软件.可以在框架的基础上进行软件开发,简化编码 反射:将类的各个组成部分封装为其他对象,这就是反射机制 ​ 好处: ​ ...

  2. Java反射Reflect的使用详解

    目录 一. 什么是反射 二. 反射的基础Class 2.1 Class类概述 2.2 Class类对象获取的三种方式 三. 反射-构造函数 3.1 getDeclaredConstructor(Cla ...

  3. Java ”框架 = 注解 + 反射 + 设计模式“ 之 注解详解

    Java "框架 = 注解 + 反射 + 设计模式" 之 注解详解 每博一文案 刹那间我真想令时光停住,好让我回顾自己,回顾失去的年华,缅怀哪个穿一身短小的连衣裙 和瘦窄的短衫的小 ...

  4. Java基础-面向接口编程-JDBC详解

    Java基础-面向接口编程-JDBC详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JDBC概念和数据库驱动程序 JDBC(Java Data Base Connectiv ...

  5. Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

    Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...

  6. java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了!      社区福利快来领取免费参加MDCC大会机会哦    Tag功能介绍—我们 ...

  7. Java开发利器Myeclipse全面详解

    Java开发利器Myeclipse全面详解: Ctrl+1:修改代码错误 Alt+Shift+S:Source命令 Ctrl+7:单行注释 Ctrl+Shift+/ :多行注释 Ctrl+I :缩进( ...

  8. [译]Java Thread join示例与详解

    Java Thread join示例与详解 Java Thread join方法用来暂停当前线程直到join操作上的线程结束.java中有三个重载的join方法: public final void ...

  9. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  10. Java面试题04-final关键字详解

    Java面试题04-final关键字详解 本篇博客将会讨论java中final关键字的含义,以及final用在什么地方,感觉看书总会有一些模糊,而且解释的不是很清楚,在此做个总结,以备准备面试的时候查 ...

随机推荐

  1. .NET10 - 预览版1新功能体验(一)

    .NET 10 首个预览版已经在前两天发布,该版本在 .NET Runtime.SDK.libraries.C#.ASP.NET Core.Blazor 和 .NET MAUI 等多个方面都有重大改进 ...

  2. go语言实现终端里的倒计时

    最近在更新系统的时候发现pacman的命令行界面变了,我有很久没更新过设备上的Linux系统了,所以啥时候变的不好说.但这一变化成功勾起了我的好奇心.新版的更新进度界面如下: 新的更新进度界面能同时显 ...

  3. Easyexcel(5-自定义列宽)

    注解 @ColumnWidth @Data public class WidthAndHeightData { @ExcelProperty("字符串标题") private St ...

  4. 【CIM信息整合】关于三维建筑模型

    还是无暇细细检索并总结列出有逻辑的明确表述,以下很多地方都是人云亦云的复制,自己也没太搞清 1.5 三维建筑模型 CIM中三维建筑模型主要表达建(构)筑物的空间位置.几何形态及外观效果等. 在建筑相关 ...

  5. 华为云windows server 2008 迁机遇到字符串问题

    问题 使用主机迁移服务迁移windows server 2008出现问题 2.按照教程安装Windows Agent(Python2)下载后,在源主机上运行agent-start.exe,输入ak后, ...

  6. helm install 从多种源进行安装

    Helm 提供了多种方法来从不同的源安装 charts.以下是一些常见的安装方法: Helm官方仓库 从 Helm 官方仓库(Helm Hub)安装:Helm Hub 是 Helm 官方维护的一个公共 ...

  7. laravel The Process class relies on proc_open, which is not available on your PHP installation.

    解决办法: 在php.ini中,找到disable_functions选项,看看后面是否有proc_open函数被禁用了,去掉proc_get_status,proc_open即可

  8. MFC中AfxBeginThread、AfxEndThread、GetExitCodeThread的配合使用(工作者线程)

    //线程入口函数(全局) UINT MyThreadProc(LPVOID pParam) { //在需要添加返回值的地方 if (...) { AfxEndThread(0); return 0; ...

  9. oracle中的aix,Oracle在AIX上一些处理

    一.Oracle在aix上连接 1.su - oracle  //进入oracle用户: 2.export ORACLE_SID=house  //指定实例,多个实例的情况下: 3.sqlplus / ...

  10. oracle调整sga、pga大小

    展开修改sga大小1-1查看当前sga大小SQL> show parameter sga1-2修改sga_max_size为24GSQL> alter system set sga_max ...