`

深入理解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 反射机制

    java 反射机制深入理解,java 反射机制深入理解,java 反射机制深入理解,

    候捷谈Java反射机制

    候捷谈Java反射机制 有助深入理解Java新特性

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

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

    java学习资料-反射机制深入理解剖析

    java学习资料—反射机制深入理解剖析;java学习资料—反射机制深入理解剖析;java学习资料—反射机制深入理解剖析;java学习资料—反射机制深入理解剖析;java学习资料—反射机制深入理解剖析;

    深入理解Java反射

    另一种是反射机制,它允许我们在运行时发现和使用类的信息。  1、Class对象  理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息。Class...

    Java反射机制 深入浅出

    1、到底什么叫反射 2、Class类的作用 3、Class类的实例化三种...Class类在一般的基本开发是不会有任何作用的,完全可以不会,但是,对于一些高端的开发框架,所有的基本的核心原理都在于反射机制的应用上。 8、代理模式

    Java反射机制深入理解

    主要介绍了Java反射机制深入理解的相关资料,希望通过本文大家能理解这部分内容,需要的朋友可以参考下

    java深入学习教程书籍ppt及pdf集合

    java反射机制总结pdf java数据结构上机实践指导教程pdf java网络编程pdf jvm内存问题最佳实践ppt jvm实现机制ppt jvm调优word tomcat详细资料word tomcat源码研究 java类库简介和数据结构类使用ppt 深入java虚拟机...

    深入理解Java类型信息(Class对象)与反射机制

    本篇主要是深入对Java中的Class对象进行分析,这对后续深入理解反射技术非常重要,主要内容如下:认识Class对象之前,先来了解一个概念,RTTI(Run-TimeTypeIdentification)运行时类型识别,对于这个词一直是C++中...

    【大厂面试题总结】JavaSE面试题总结详细教程

    深入理解Java的反射机制 深入理解Java异常体系 谈谈NIO的理解 谈一谈对JUC的理解 ArrayList的底层原理 HashMap的底层原理 iava单例模式详解 JAVA的内存结构 java队列 Java基础思考之数据传递 JAVA内存泄漏详解 java...

    【大厂面试题总结】JavaSE面试题合集及其答案,基本包括javaSE所有知识点和详细解释

    深入理解Java的反射机制 深入理解Java异常体系 谈谈NIO的理解 谈一谈对JUC的理解 ArrayList的底层原理 HashMap的底层原理 iava单例模式详解 JAVA的内存结构 java队列 Java基础思考之数据传递 JAVA内存泄漏详解 java...

    java基础.txt 百度云

    Java 基础语法 Java 面向对象 深入面向对象和数组 ...深入理解 Java 注解+反射 Java23 种设计模式 学会 Java 正则表达式 JDBC 详解 Java 数据结构和算法 深入理解 Java 虚拟机 Java 解析XML文件

    史上最详细的【一线大厂面试题】详解及其答案

    4、深入理解Java的反射机制 5、深入理解Java异常体系 6、谈谈NIO的理解 7、谈一谈对JUC的理解 8、ArrayList的底层原理 9、HashMap的底层原理 10、Java单例模式详解 11、JAVA的内存结构 12、java队列 13、Java基础...

    【Java面试+Java学习指南】 一份涵盖大部分Java程序员所需要掌握的核心知识

    ava基础 基础知识 ...Java集合详解5:深入理解LinkedHashMap和LRU缓存 Java集合详解6:TreeMap和红黑树 Java集合详解7:HashSet,TreeSet与LinkedHashSet Java集合详解8:Java集合类细节精讲 JavaWeb

    Java工程师面试复习指南

    【Java工程师面试复习指南】本仓库架构大部分Java工程师所需要掌握的核心知识,整合了互联网上的很多优质Java技术文章,力求打造为最完整最实用的Java开发者学习指南,如果对你有...Java集合详解:深入理解LinkedHas

    Java开发详解.zip

    031504_【第15章:Java反射机制】_Java反射机制的深入研究笔记.pdf 031505_【第15章:Java反射机制】_动态代理笔记.pdf 031506_【第15章:Java反射机制】_工厂设计模式笔记.pdf 031601_【第16章:Annotation】_系统...

    java面试题参考及解答

    该资源涵盖了Java的基础知识点,如数据类型、运算符、控制流程等,以及Java的面向对象编程、异常处理、多线程、反射机制、集合框架等高级主题。每个面试题都配有答案与解析,以帮助读者深入理解问题的背景和解决方法...

Global site tag (gtag.js) - Google Analytics