深入理解java的反射机制(转载)

Love The Way You Lie 2022-05-04 15:28 398阅读 0赞

原文路径:http://blog.51cto.com/4247649/2109128

今天将从以下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对象类如下:

  1. /**
  2. * 定义一个用户对象
  3. *
  4. * @author zhangqh
  5. * @date 2018年4月24日
  6. */
  7. public class User implements Serializable {
  8. /**
  9. *
  10. */
  11. private static final long serialVersionUID = 1L;
  12. /**
  13. * 用户id
  14. */
  15. private Integer userId;
  16. /**
  17. * 用户名称
  18. */
  19. private String userName;
  20. /**
  21. * 公共元素
  22. */
  23. public String age;
  24. private User(Integer userId){}
  25. public User(){}
  26. public User(Integer userId, String userName) {
  27. super();
  28. this.userId = userId;
  29. this.userName = userName;
  30. }
  31. /**
  32. * @return the userId
  33. */
  34. public Integer getUserId() {
  35. return userId;
  36. }
  37. /**
  38. * @param userId the userId to set
  39. */
  40. public void setUserId(Integer userId) {
  41. this.userId = userId;
  42. }
  43. /**
  44. * @return the userName
  45. */
  46. public String getUserName() {
  47. return userName;
  48. }
  49. /**
  50. * @param userName the userName to set
  51. */
  52. public void setUserName(String userName) {
  53. this.userName = userName;
  54. }
  55. }

测试反射类:

  1. /**
  2. * 测试反射类
  3. *
  4. * @author zhangqh
  5. * @date 2018年4月25日
  6. */
  7. public class Test {
  8. public static void main(String[] args) throws ClassNotFoundException {
  9. // 第一种方法 直接通过类名获取class (一般不会这么用,因为实例都获取到了没必要多此一举)
  10. User user = new User();
  11. Class class1 = user.getClass();
  12. System.out.println("我是方法1反射处理的类 = "+class1);
  13. System.out.println("我是方法1反射处理的类的父类 = "+class1.getSuperclass());
  14. System.out.println("----------------------------------------------------");
  15. // 第二种办法通过类名的方法获取class 需要增加对应的类引用
  16. Class class2 = User.class;
  17. System.out.println("我是方法2反射处理的类 = "+class2);
  18. System.out.println("我是方法2反射处理的类的父类 = "+class2.getSuperclass());
  19. System.out.println("----------------------------------------------------");
  20. // 第三种办法通过全类名获取,用的比较多,也推荐使用这种方式
  21. Class class3 = Class.forName ("com.zhang.reflection.User");
  22. System.out.println("我是方法3反射处理的类 = "+class3);
  23. System.out.println("我是方法3反射处理的类的父类 = "+class3.getSuperclass());
  24. System.out.println("----------------------------------------------------");
  25. // 反射获取User对象的公共构造器
  26. Constructor<User>[] constructors = class3.getConstructors();
  27. for(int i=0;i<constructors.length;i++){
  28. System.out.println("我是公共构造器"+(i+1)+" = "+constructors[i]);
  29. }
  30. System.out.println("----------------------------------------------------");
  31. //反射获取User对象的所有构造器
  32. Constructor<User>[] dconstructors = class3.getDeclaredConstructors();
  33. for(int i=0;i<dconstructors.length;i++){
  34. System.out.println("我是所有构造器"+(i+1)+" = "+dconstructors[i]);
  35. }
  36. System.out.println("----------------------------------------------------");
  37. // 反射获取User对象的 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
  38. Method[] methods = class3.getMethods();
  39. for(int i=0;i<methods.length;i++){
  40. System.out.println("我是公共方法"+(i+1)+" = "+methods[i]);
  41. }
  42. System.out.println("----------------------------------------------------");
  43. // 反射获取User对象的 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
  44. Method[] dmethods = class3.getDeclaredMethods();
  45. for(int i=0;i<dmethods.length;i++){
  46. System.out.println("我是所有的方法"+(i+1)+" = "+dmethods[i]);
  47. }
  48. System.out.println("----------------------------------------------------");
  49. // 获取包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
  50. Field[] fields = class3.getFields();
  51. for(int i=0;i<fields.length;i++){
  52. System.out.println("我是公共的field"+(i+1)+" = "+fields[i]);
  53. }
  54. System.out.println("----------------------------------------------------");
  55. Field[] dfields = class3.getDeclaredFields();
  56. for(int i=0;i<dfields.length;i++){
  57. System.out.println("我是所有的field"+(i+1)+" = "+dfields[i]);
  58. }
  59. System.out.println("----------------------------------------------------");
  60. String sname = class3.getSimpleName();
  61. System.out.println("我是类名不包含包路径 = "+sname);
  62. System.out.println("----------------------------------------------------");
  63. String name = class3.getName();
  64. System.out.println("我是类名包含包路径 = "+name);
  65. System.out.println("----------------------------------------------------");
  66. Package packA=class3.getPackage();
  67. System.out.println("我是类的包路径 = "+packA.getName());
  68. System.out.println("----------------------------------------------------");
  69. Class<?>[] interfaces=class3.getInterfaces();
  70. for(int i=0;i<interfaces.length;i++){
  71. System.out.println("我是实现的接口"+(i+1)+" = "+interfaces[i]);
  72. }
  73. System.out.println("----------------------------------------------------");
  74. // 返回此类或接口以整数编码的 Java 语言修饰符。修饰符由 Java 虚拟机的 public、 protected、 private、 final、 static、 abstract 和 interface 对应的常量组成;
  75. // 它们应当使用 Modifier 类的方法来解码
  76. Integer modefiers = class3.getModifiers();
  77. System.out.println("我是类的modefiers = "+modefiers);
  78. }
  79. }

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

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

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

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

发表评论

表情:
评论列表 (有 0 条评论,398人围观)

还没有评论,来说两句吧...

相关阅读

    相关 深入理解Java反射机制

    Java的反射机制是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息,并且还可以动态调用这些元素。 以下是深入理解Java反射机制的关键点: 1. 类加载:任何使

    相关 Java反射机制深入理解

    Java反射机制是Java语言提供的一种能力,它允许我们在运行时动态地获取类的信息、创建对象以及调用方法等。 以下是对Java反射机制深入理解的关键点: 1. 类加载:当J

    相关 深入理解Java反射机制

    Java的反射机制是一种强大的工具,它允许我们在运行时动态地检查类、方法和字段的信息。 以下是深入理解反射机制的关键点: 1. **Class对象**:在Java中,每一个

    相关 Java反射机制深入理解

    Java的反射机制是一种强大的工具,它允许我们在运行时查看和修改对象的行为。以下是对反射机制深入理解的一些关键点: 1. **类加载**:在Java中,对象是通过类来创建的。

    相关 深入理解Java反射机制

    反射是Java语言提供的一种能力,允许程序在运行时动态地检查类的信息(如字段、方法等)并调用它们。 以下是反射机制的一些关键点: 1. 类的加载:反射首先需要一个类对象。这

    相关 反射 - 深入理解Java反射机制

    Java的反射机制是指在运行时动态地获取类的信息以及操作类的属性和方法。Java的反射机制允许程序在运行时检查和操作类、接口、字段和方法,而无需提前在编译时知道这些类的具体信息