`

深入理解java的反射机制

    博客分类:
  • java
阅读更多

今天将从以下4方面来系统的学习一下java的反射机制:

  • java反射是什么

  • java反射(Reflection)底层实现原理

  • java反射的简单演示

  • java反射的应用场景

 

1,java反射是什么

 

首先大家应该先了解两个概念,编译期运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

 

2,java反射(Reflection)的底层实现原理

 

众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象

 

而这个Class 类十分特殊。它和一般类一样继承自Object,当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。

而Class对象是java反射故事起源。Class类提供了大量的实例方法来获取该Class对象所对应的详细信息,我们只是做简单的介绍,详细请参考JDK文档,这边提供一个在线的中文文档给大家如下:

 

http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

这边列了下Class类其中的很少yibufen方法,

获取公共构造器 getConstructors()
获取所有构造器 getDeclaredConstructors
获取包含的方法 getMethod()
获取包含的属性 getField(String name)
获取内部类 getDeclaredClasses()
获取外部类 getDeclaringClass()
获取所实现的接口 getInterfaces()
获取修饰符 getModifiers()
获取所在包 getPackage()
获取类名包含包路径  getName()
类名不包含包路径  getSimpleName()

 

3,java反射的简单演示

 

上面介绍了下java反射的实现机制,接下来我主要来演示一下反射的使用

首先定义一个user对象类如下:

 

 

/**
* 定义一个用户对象
*
* @author zhangqh
* @date 2018年4月24日
*/

public class User implements Serializable {
   /**
    *
    */

   private static final long serialVersionUID = 1L;
   /**
    * 用户id
    */

   private Integer userId;
   /**
    * 用户名称
    */

   private String userName;

   /**
    * 公共元素
    */

   public String age;

   private User(Integer userId){}

   public User(){}
   public User(Integer userId, String userName) {
       super();
       this.userId = userId;
       this.userName = userName;
   }
   /**
    * @return the userId
    */

   public Integer getUserId() {
       return userId;
   }
   /**
    * @param userId the userId to set
    */

   public void setUserId(Integer userId) {
       this.userId = userId;
   }
   /**
    * @return the userName
    */

   public String getUserName() {
       return userName;
   }
   /**
    * @param userName the userName to set
    */

   public void setUserName(String userName) {
       this.userName = userName;
   }

}

 

测试反射类:

 

/**
* 测试反射类
*
* @author zhangqh
* @date 2018年4月25日
*/

public class Test {
   public static void main(String[] args) throws ClassNotFoundException {
       // 第一种方法 直接通过类名获取class (一般不会这么用,因为实例都获取到了没必要多此一举)
       User user = new User();
       Class class1 = user.getClass();
       System.out.println("我是方法1反射处理的类 = "+class1);
       System.out.println("我是方法1反射处理的类的父类 = "+class1.getSuperclass());
       System.out.println("----------------------------------------------------");
       // 第二种办法通过类名的方法获取class 需要增加对应的类引用
       Class class2 = User.class;
       System.out.println("我是方法2反射处理的类 = "+class2);
       System.out.println("我是方法2反射处理的类的父类 = "+class2.getSuperclass());
       System.out.println("----------------------------------------------------");
       // 第三种办法通过全类名获取,用的比较多,也推荐使用这种方式
       Class class3 = Class.forName ("com.zhang.reflection.User");
       System.out.println("我是方法3反射处理的类 = "+class3);
       System.out.println("我是方法3反射处理的类的父类 = "+class3.getSuperclass());
       System.out.println("----------------------------------------------------");
       // 反射获取User对象的公共构造器
       Constructor<User>[] constructors = class3.getConstructors();
       for(int i=0;i<constructors.length;i++){
           System.out.println("我是公共构造器"+(i+1)+" = "+constructors[i]);
       }
       System.out.println("----------------------------------------------------");
       //反射获取User对象的所有构造器
       Constructor<User>[] dconstructors = class3.getDeclaredConstructors();
       for(int i=0;i<dconstructors.length;i++){
           System.out.println("我是所有构造器"+(i+1)+" = "+dconstructors[i]);
       }
       System.out.println("----------------------------------------------------");
       // 反射获取User对象的 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
       Method[]  methods = class3.getMethods();
       for(int i=0;i<methods.length;i++){
           System.out.println("我是公共方法"+(i+1)+" = "+methods[i]);
       }
       System.out.println("----------------------------------------------------");
       // 反射获取User对象的 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
       Method[]  dmethods = class3.getDeclaredMethods();
       for(int i=0;i<dmethods.length;i++){
           System.out.println("我是所有的方法"+(i+1)+" = "+dmethods[i]);
       }
       System.out.println("----------------------------------------------------");
       // 获取包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
       Field[] fields = class3.getFields();
       for(int i=0;i<fields.length;i++){
           System.out.println("我是公共的field"+(i+1)+" = "+fields[i]);
       }
       System.out.println("----------------------------------------------------");
       Field[] dfields = class3.getDeclaredFields();
       for(int i=0;i<dfields.length;i++){
           System.out.println("我是所有的field"+(i+1)+" = "+dfields[i]);
       }
       System.out.println("----------------------------------------------------");
       String sname = class3.getSimpleName();
       System.out.println("我是类名不包含包路径 = "+sname);
       System.out.println("----------------------------------------------------");
       String name = class3.getName();
       System.out.println("我是类名包含包路径 = "+name);
       System.out.println("----------------------------------------------------");
       Package packA=class3.getPackage();
       System.out.println("我是类的包路径 = "+packA.getName());
       System.out.println("----------------------------------------------------");
       Class<?>[] interfaces=class3.getInterfaces();
       for(int i=0;i<interfaces.length;i++){
           System.out.println("我是实现的接口"+(i+1)+" = "+interfaces[i]);
       }
       System.out.println("----------------------------------------------------");
       // 返回此类或接口以整数编码的 Java 语言修饰符。修饰符由 Java 虚拟机的 public、 protected、 private、 final、 static、 abstract 和 interface 对应的常量组成;
       // 它们应当使用 Modifier 类的方法来解码
       Integer modefiers = class3.getModifiers();
       System.out.println("我是类的modefiers = "+modefiers);
   }
}

 

以上代码中有详细的代码注释,这边就不过多的解释了

 

4,java反射的应用场景

 

a,注解的使用

 

不知道大家是否有看过之前写的深入理解java注解的实现原理它的底层实现就是java反射,主要有如下方法:

 

getAnnotations()
getAnnotation(Class annotationClass) 
getDeclaredAnnotations() 
isAnnotation() 
isAnnotationPresent(Class annotationClass)

 

b,编写基础框架

 

有一句话这么说来着:反射机制是很多Java框架的基石,经典的就是在xml文件或者properties里面写好了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,spring,Hibernate底层都有类似的实现

 

c,其他在编码阶段不知道那个类名,要在运行期从配置文件读取类名配置

 

如下:这段代码想必大家肯定都有写过,这个数据库的连接驱动类就是编译的时候不知道你到底是用的mysql,oracle还是其他数据库,而是由运行期动态加载的

 

 

// 1.加载驱动程序
       Class.forName("com.mysql.jdbc.Driver");
       // 2.获得数据库的连接
       Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);
       // 3.通过数据库的连接操作数据库,实现增删改查
       Statement stmt = conn.createStatement();
       ResultSet rs = stmt
               .executeQuery("select user_name,age from user");
       while (rs.next()) {// 如果对象中有数据,就会循环打印出来
           System.out.println(rs.getString("user_name") + ","
                   + rs.getInt("age"));
       }

 

注:以上介绍了反射的应用场景,程序猿开发业务代码中应尽量少用反射,一个是代码可读性不是特别好,第二是反射需要运行期jvm去重新解析性能上也没有直接使用好,唯一比较合理的地方是业务中需要用到AOP可以大大简化业务代码建议使用

 

以上是今天文章的所有内容,欢迎大家吐槽

 

如果觉得文章对你有帮助,欢迎转发或关注如下公众号阅读更多优质文章

分享到:
评论

相关推荐

    一个例子让你了解Java反射机制

    通过8个demo,你可以逐步深入理解Java反射机制,从简单的获取类信息,到创建对象,调用方法,访问字段,再到处理注解和泛型,全方位掌握这一强大的工具。每个demo都应该设计为解决一个特定的问题,例如如何动态调用...

    JAVA反射机制动态调用 计算器对象的加法,减法函数;JAVA反射机制修改一个学生对象 的私有数据成员

    首先,让我们深入理解Java反射机制。在Java中,`java.lang.Class`类是所有类的通用表示,它包含了关于类的所有信息。我们可以通过类的名字获取到`Class`对象,然后通过这个对象来访问类的方法和字段。`Method`类代表...

    java面试题--反射机制

    这是因为Java反射机制不仅是Java语言的一项重要特性,也是理解Java动态特性的关键所在。通过本文,我们将深入探讨Java反射机制的核心概念、基本原理及其应用场景。 #### 二、Java反射机制简介 Java反射机制允许...

    java反射机制原理1

    首先,让我们深入理解Java反射机制的基本概念: 1. **Class对象**:每个类在Java中都有一个对应的Class对象,它包含了该类的所有信息,如类名、方法、字段等。我们可以通过`Class.forName(String className)`或`...

    Java反射机制概述.zip

    在深入理解Java反射机制之前,我们首先要明白几个关键概念: 1. **类加载器(Class Loader)**:Java程序中的类并非一开始就全部加载到内存,而是根据需要由类加载器动态加载。这为反射提供了基础。 2. **类对象...

    深入理解Java的反射机制Java系列2021.pdf

    对于理解Java反射机制,需要掌握以下核心知识点: 1. 反射机制基础: Java程序在编译期和运行期有不同的处理过程。编译期是将源代码转换为字节码的过程,而运行期是执行这些字节码的过程。Java反射机制是指在程序...

    Java 基础(7-8) - 反射机制详解.pdf

    "Java 反射机制详解" Java 反射机制是在运⾏状态中,对于任意⼀个类,都能够知道这个类的所有属性和⽅法;...深入理解 Java 反射机制可以帮助我们更好地使用 Java 语言,提高编程效率和代码质量。

    JAVA反射机制与动态代理综合资料

    首先,让我们深入理解Java反射机制。反射的核心是`java.lang.Class`类,它代表了运行时的类信息。通过Class对象,我们可以获取类的名称、构造器、方法和字段等信息,并能在运行时创建和调用类的对象。以下是一些关键...

    Java中的反射机制Reflect

    在深入理解Java反射机制之前,我们首先需要知道什么是类的元数据,即关于类本身的信息。Java的反射机制就是通过这些元数据来操作类的实例。 在Java中,`java.lang.Class` 类是所有类的通用表示,它代表了Java运行时...

    基于Java反射机制的“微型”Ioc实现

    这个“微型”Ioc实现的源代码,可以帮助开发者深入理解Java反射机制如何用于构建简单的Ioc容器,对于学习和实践Java设计模式,尤其是依赖注入和控制反转,是非常有价值的参考资料。通过阅读和分析源代码,我们可以...

    JAVA反射机制的入门代码

    总的来说,"JAVA反射机制的入门代码"是初学者理解Java反射机制的好教材,通过它,你可以学习如何动态地操作Java类,提高代码的灵活性,并掌握处理`properties`文件的基础方法。在深入学习和实践中,你将进一步理解...

    java反射调用实例代码

    这个"java反射调用实例代码"应该包含了以上介绍的各种反射操作,可以帮助学习者深入理解Java反射机制,并在实际项目中灵活运用。通过研究和实践这些代码,你可以更好地掌握Java反射的精髓,提升你的编程技能。

    Java 反射机制 代码的实例

    Java反射机制是Java编程语言中的一个强大特性,...通过学习和实践Java反射机制,你可以更深入地理解Java的运行机制,并在需要动态性、灵活性的场景中发挥其强大的功能。不过,使用反射时也应注意潜在的风险和性能影响。

    北大青鸟java反射机制

    在"北大青鸟java反射机制"的学习资料中,我们将会深入探讨这一核心特性。 首先,我们要理解反射的核心概念:在程序运行时,通过Class对象获取类的信息,包括类名、属性、方法等,并能够动态地创建对象和调用方法。...

    Java反射机制学习(二)

    这篇博文"Java反射机制学习(二)"可能深入探讨了如何利用反射进行动态类型处理、访问私有成员以及创建对象等核心概念。在这里,我们将详细讨论Java反射的基本用法及其在实际开发中的应用。 1. **什么是反射**: ...

    java反射机制原理和反射机制总结

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段以及方法等对象。这一机制的核心在于`java.lang.Class`类...学习和理解反射机制对于深入理解Java以及开发复杂系统至关重要。

    java学习笔记 - 反射机制,头大的难

    在深入理解Java反射机制之前,我们先要明白类加载的过程。当Java程序运行时,JVM会将.class文件加载到内存中,形成类的字节码,反射就是在此基础上进行的。 在Java中,`java.lang.Class` 类是所有类的通用表示,...

    java-fanshejizhi.rar_java 反射

    通过阅读"java-fanshejizhi.docx"文档和参考"www.pudn.com.txt"中的资源,你将深入理解Java反射机制的原理和实践应用。这些文件会提供更具体的示例和详细解释,帮助你在实际项目中有效利用反射。

    利用java反射机制的建议计算器源码

    在这个“利用java反射机制的建议计算器源码”中,我们将深入探讨如何使用反射来构建一个可扩展的计算器,帮助新手更好地理解这一概念。 首先,让我们解释什么是反射。在Java中,反射机制允许我们获取类的信息(如...

Global site tag (gtag.js) - Google Analytics