`
xifangyuhui
  • 浏览: 188968 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java反射学习笔记

阅读更多

java反射作用:

1、自省:通过对象自身获得类结构,继而获取并修改字段值,调用方法,构造实例。

2、String->Object:通过类字符串构造类实例

传统创建一个对象 或者是调用对象的一个方法 ,需要在程序里将创建对象的语句,即new一个对象,都需要在程序里面写死,即在程序中硬编码。众所周知,硬编码是一种不好的编程方式,最好的方法是在程序中通过配置信息(String字符串)动态创建对象或是动态调用对象的方法。

Class对象 :类对象,它是JAVA自省机制的起点 一个对象要知道自己有什么,首先肯定需要知道自己是什么,即首先获知它是哪个类的对象,那么怎么获知这个对象呢?

这里不得不提到类加载 ,类经过编译后会生成一个Class字节码文件 当生成某个类的实例时,首先需要JVM将对应类的Class文件加载 进来,JVM会在类路径下(ClassPath)下根据包名去相应路径下搜索目标类的Class文件,找到后将其读到虚拟机中,这就是所谓的 类加载 ,这样JVM便获知了类的信息。读到JVM中后,更进一步地说,JVM需要将类存起来,即 封装 ,这样JVM便会把类信息封装在一个对象中,这个记录了类信息的对象就是 类对象 ,即Class对象,类对象是JVM加载类的一个产物,只要类对象没有消失,就不需要再加载类对象,这样JVM通过类对象就知道了类的组成结构,继而也就能创建类的实例了。当我们 首次使用某个类的时候才会发生类加载 ,什么才算使用呢?创建一个类的对象,访问一个类的静态属性或者方法,注意声明一个类的引用时不会产生类加载,JVM不需要知道这个类是什么,它只在栈空间中为这个引用分配四个字节就行了,在真正使用类的时候才会加载类。

大家都知道面向对象的一个重要特征便是 封装 ,JVM会把类对象中的每个字段封装成一个Field对象,把每个构造方法封装成一个Constructor对象,把每个方法封装成一个Method对象,这些对象再一同封装为类对象,我们可以理解为封装的封装。

程序中如何获取类对象呢?三种方法:

  • 类名.class: 八种基本数据类型也通过.class获得类对象,需要注意,int.class和Integer.class是不一样的 它们是两个不同的类对象。
  • 对象.getClass(): 来获取对象所属类的类对象,这个方法是继承于Object的,因此所有类都拥有这个方法。
  • Class.forName(类名字符串): 通过Class的静态方法forName得到类字符串代表的类对象

获 取了类对象之后,我们继而可以获得该类中的Field对象,Constructor对象,Method对象,再通过上面这些对象获得字段,构造方法,方法 的详细信息。这里需要注意的是getFileds()与getDeclaredFields()的区别,其实大家看API也能看到,这里简述一下:

  • getDeclaredFields ()    返回类中的所有字段对象,甚至包括私有的字段,但是需要注意的是它不会返回父类中的字段。
  • getFields () 返回该类及其父类的公有字段,即public修饰的字段。

获取Method[]以及Constructor[]同样的道理。

另外,获得指定的Method时, 除了传递方法的名字外,还需要传递参数类对象数组 ,以此参数类对象数组来判断调用的是哪个方法,因为方法可以重载嘛,而参数的类型,顺序,个数决定了不同的重载方法。

通过反射,我们 还可以对对象进行一些操作 。上面已经讲到我们可以通过反射获得类成员变量本身的一些信息,这里我们不仅仅是想获得类的结构信息,我们还想获取和修改字段的值,另外可能还要调用某个方法,构造一个对象实例等等。即对此类进行 动态操作 ,我们可以把获取类结构看做对类的 静态操作 。但是要注意,如果类的字段 是private的而且没有提供get和set接口 ,我们还可以操作该字段吗?答案是可以的。

那么我们 怎么获取和修改另外一个类的私有字段呢?

  • 首先通过对象获得类对象(调用对象的getClass());
  • 接着需要得到私有成员字段包装的Field对象(调用类对象的getDeclaredFields());
  • 接下来下面大家可以查看一下Field对象的API,其中有一个get方法:

public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException

 

参数object指的是针对哪个对象获取相应字段的值,如果你直接通过调用get()并传入对象去获取私有字段的值,会得到 IllegalAccessException 异常。这里我们需要用到另外一个关键的方法: setAccessible(boolean flag) ,该方法来自于Field,Constructor,Method的父类 AccessibleObject ,大致浏览该类的API大家可以发现,该类主要用来对 Field, Constructor,Method的访问控制检测进行压制( It provides the ability to flag a reflected object as suppressing default Java language access control checks when it is used ), 访问控制检测大家应该都知道是什么意思,这里调用setAccessible(true),顾名思义,表示设置可访问性,其是对当前Filed或者 Constructor或者Method对象进行访问控制检测压制,这样我们便可以通过get(Object obj)来获得私有字段的值了。

  • 我们还可以设置该字段的值,调用set方法:

public void set(Object obj, Object value) throws IllegalArgumentException, illegalAccessException

进行赋值。

调用私有方法怎么做呢?

  • 首先调用类对象的

 

   getDeclaredMethod ( String  name, Class <?>... parameterTypes) throws NoSuchMethodException , SecurityException

传递两个参数,一个是参数的名字,另外一个是方法的参数类对象数组,用来确定调用的是哪个方法。

  • 接着查看Method类的API可以看到invoke方法:

invoke ( Object  obj, Object ... args)    Invokes the underlying method represented by this Method object, on the specified object with the specified  parameters.

 

这里需要传递两个参数,第一个参数表示对哪个对象调用invoke方法,第二参数是一个Object数组,即参数值
。返回一个Object对象,即调用方法的返回值。如果调用的是一个void方法,那么调用invoke方法返回的是null。

如何通过类对象创建实例呢? 第一种方法:直接调用类对象的newInstance()来构造一个实例。不知道大家注意到没有,创建实例的时候并没有传递参数,也就是说原来的类中必须有一个无参数的构造方法,否则该方法不能调用,那么带参数的构造方法怎么调用呢?
第二种方法:通过类对象调用:

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

 

传递的参数大家应该都清楚了,和上面获取指定Method一样,传递一个参数类对象数组,用于确认到底获取那个构造方法。接下来,再调用Constructor的


public T newInstance(Object... initargs) throws InstantiationException, 

 LegalAccessException,IllegalArgumentException, InvocationTargetException

并传递参数就可以创建对象了。

 

大家 现在应该知道JAVABean中为什么要必须包含一个无参的构造方法以及包含一系列public的get,set方法了,这样 工具便可以通过反射使用类对象的newInstance直接创建对象了,同时由于方法名都是有规律的,只要知道字段名,便可以通过构造get/set+字段名(首字母大写)字符串得到对应字段的Method对象,继而调用它们来获取和设置值了 ,这一切都可以由工具自动来完成。

 

 

0
0
分享到:
评论

相关推荐

    Java基础 学习笔记 Markdownr版

    本学习笔记主要涵盖了Java的基础知识,包括面向对象、集合、IO流、多线程、反射与动态代理以及Java 8的新特性等方面,旨在帮助初学者或有经验的开发者巩固和提升Java编程技能。 1. 面向对象(OOP):Java的核心是...

    java注解和反射的个人学习笔记

    java注解和反射的个人学习笔记

    Java反射学习笔记

    Java反射是Java编程语言中的一个强大特性,允许程序在运行时动态地获取类的信息并操作类的对象。在Java中,反射主要用于以下场景:动态加载类、访问私有成员、调用私有方法以及处理泛型等。以下是关于Java反射的一些...

    java学习笔记markdown

    8. **反射机制**:探讨Java反射API的使用,包括动态获取类信息、创建对象、调用方法等功能,这对于理解和调试程序有很大的帮助。 9. **JVM内部机制**:简述Java虚拟机的工作原理,包括类加载、内存管理、垃圾回收...

    Java入门学习笔记

    "Java入门第三季学习笔记"可能涵盖了更多高级话题,如反射、注解、设计模式和Java库的使用。反射允许程序在运行时检查类、接口、字段和方法的信息,提供了更大的灵活性。注解是一种元数据,可以用来提供编译器或运行...

    java学习笔记java反射机制

    java学习笔记java反射机制

    java李兴华学习笔记之Java常用类库

    ### Java李兴华学习笔记之Java常用类库 #### 一、课程介绍及知识点概览 根据提供的资料,“Java李兴华学习笔记之Java常用类库”这份文档来源于北京MLDN软件实训中心的教学资料,主要涵盖了Java编程语言中常用类库...

    java学习——java中的反射学习笔记.rar_java 反射

    本篇笔记将深入探讨Java反射的概念、重要性以及如何使用。 一、反射基础 1. 类加载:当Java虚拟机(JVM)加载一个类时,它会创建该类的Class对象。这个对象包含了关于类的所有信息,包括方法、字段、构造器等。...

    java学习笔记(java 反射机制 流 内存管理)

    本笔记主要涵盖了四个核心知识点:Java反射机制、流(I/O流)、内存管理和Java学习的基础。以下是对这些主题的详细阐述: 一、Java反射机制 Java反射机制是Java语言的一个强大特性,允许程序在运行时检查类、接口、...

    JAVA学习笔记 林信良

    《JAVA学习笔记》是林信良先生的一部深入浅出的Java编程教程,旨在帮助初学者和有一定经验的开发者巩固和提升Java编程技能。这本书涵盖了Java语言的基础到高级概念,是一份宝贵的自学资料。 首先,从基础部分开始,...

    java反射笔记

    在“java反射笔记”这个主题中,我们将深入探讨反射的基础知识和常见用法。 首先,我们需要了解什么是反射。在Java中,反射是指在运行时获取类的信息(如类名、方法名、参数类型等)并动态调用对象的方法或访问其...

    Java学习笔记(源码)

    8. **反射机制**:Java反射API允许在运行时动态访问类的信息,包括类名、方法、字段等。学习笔记会讲解如何使用反射进行元编程,以及其在插件系统、序列化和动态代理中的应用。 9. **Java API和库**:Java标准库...

    java反射机制学习笔记

    Java反射机制是Java编程语言的一项重要特性,它允许程序在运行时动态地获取类的信息,并且能够对类的属性和方法进行操作。反射机制的核心在于Java的`java.lang.reflect`包,其中包含了`Class`、`Constructor`、`...

    Java基础尚硅谷宋红康学习笔记

    1. **反射**:Java反射机制允许在运行时检查类的信息(如类名、方法、字段等),并能动态调用方法和修改字段值,增强了代码的灵活性。 2. **泛型**:泛型提供了一种在编译时检查类型安全的方法,允许在类、接口和...

    java校招学习笔记

    "java校招学习笔记"显然是针对应届毕业生或求职者准备的,旨在帮助他们掌握Java的基础知识和校招面试中常见的技术问题。这份笔记可能包含了从基础概念到进阶主题的全面概述,以提高求职者的竞争力。 首先,Java的...

    java超强学习笔记

    "Java超强学习笔记"显然是一份全面且深入的Java学习资料,由一位极具洞察力和组织能力的作者精心编纂。这份笔记可能包含了从基础知识到高级特性的全方位讲解,旨在帮助学习者构建坚实的Java编程基础,并提升他们的...

    Java学习笔记(必看经典).doc

    这份“Java学习笔记(必看经典).doc”文档将涵盖Java的核心概念和重要知识点,对于初学者和有经验的开发者来说都是宝贵的参考资料。 首先,Java的基础部分通常包括以下几个方面: 1. **Java语法基础**:这是所有...

    基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip

    基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码....

Global site tag (gtag.js) - Google Analytics