JavaSE反射机制详解

1反射是什么?为什么叫反射?

1.1 JavaSE中发射的定义:

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。

1.2 计算机科学中反射的定义:

计算机科学中的反射(reflection) 指计算机程序在运行时(runtime) 可以访问、检测和修改它本身状态或行为的一种能力。通俗说,反射就是程序在运行的时候能够“观察”并且修改自己的行为,是程序对自身的反思、自检、修改。英文 reflection 本身就有反思的意思。而反思一词听起来让程序有了生命力,也说明了反射只有在程序运行时才能起作用,因为程序代码只有在CPU上“跑”起来才有“生命力”。

故:反射源于“reflection”,亦有反思之意。

2反射的作用

我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!

这么一看,反射机制就像是全局的掌控者,不管程序如何运行,都能知道类的属性和方法。

3反射机制的具体实现细节

3.1获取类的方法

我们要在程序运行中动态获取或者改变类的相关内容,那么,就必须能在程序运行中去获取类的对象。每当定义一个类,就会创建一个Class实例。一个类在 JVM 中只会有一个 Class 实例,即我们对下面获取的 c1,c2,c3进行 equals 比较,发现都是true。

//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
//  类型的对象,而我不知道你具体是什么类,用这种方法
  Person p1 = new Person();
  Class c1 = p1.getClass();

//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
//  这说明任何一个类都有一个隐含的静态成员变量 class
  Class c2 = Person.class;

//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
//   但可能抛出 ClassNotFoundException 异常
  Class c3 = Class.forName("com.ys.reflex.Person");

3.2Java反射有关的类

3.2.1Class类

  • 返回当前Class类对应的实体类的父类的Class类
public Class<? super T> getSuperclass()
  • 返回类定义的公共的内部类,以及从父类、父接口那里继承来的内部类
public Class<?>[] getClasses()
  • 返回类中定义的公共、私有、保护的内部类
public Class<?>[] getDeclaredClasses()
  • 返回一个成员内部类/属性/方法/构造器所在的类的Class,这些方法是上面那两个方法的逆操作
java.lang.reflect.Class.getDeclaringClass()    ;//返回一个成员内部类所在的类的Class
java.lang.reflect.Field.getDeclaringClass()      ;//返回一个字段所在的类的Class
java.lang.reflect.Method.getDeclaringClass()    ;//返回一个方法所在的类的Class
java.lang.reflect.Constructor.getDeclaringClass() ;//返回一个构造器所在的类的Class
  • 获取Class对应类(或者接口)的修饰符
public int getModifiers();//返回此类或接口以整数编码的 Java 语言修饰符。
//修饰符由 Java 虚拟机的 public、protected、private、final、static、abstract 和 interface 对应的常量组成;
//它们应当使用 Modifier 类的方法来解码。
- 访问权限控制符:public, protected, private
- 抽象的、需要实现的:abstract
- 限制只能有一个实例的:static
- 不允许修改的:final
- 线程同步锁:synchronized
- 原生函数:native
- 采用严格的浮点精度:strictfp
- 接口
- 注解
  • 获取Class对应的类或者接口的成员Member(成员有:属性,方法,构造方法)

a.获取构造函数

返回构造器数组

 Constructor<?>[] getDeclaredConstructors();//返回所有的构造方法的Constructor对象的数组的Constructor对象的数组
 Constructor<?>[] getConstructors();        //返回所有共有的构造方法的Constructor对象的数组

返回指定的构造器

Constructor<T> getConstructor(Class<?>... parameterTypes) 
//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
//返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 

b.获取成员变量

返回字段对象数组

Field[] getFields() 
//返回此 Class 对象所表示的类或接口的所有公有字段数组(Field 对象数组)
Field[] getDeclaredFields() 
//返回此 Class 对象所表示的类或接口中所有声明的字段数组(Field对象数组)。 

返回单个字段对象

Field getField(String name) 
//返回此 Class 对象所表示的类或接口的指定的公有成员字段对象(Field对象)。 
 Field getDeclaredField(String name) 
//返回一个此 Class 对象所表示的类或接口的指定已声明字段(Field 对象)
  • 获取成员方法

a.获取方法对象数组:第一个只能获取public修饰的方法数组,第二个可以获取除继承外的所有方法

 Method[] getMethods() 
//返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
//(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 
 Method[] getDeclaredMethods() 
//返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
//包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 

b.获取单个方法:第一个只能获取到public修饰的方法,第二个能获取除继承外的方法所有方法(公有,保护,默认,私有)

Method getMethod(String name, Class<?>... parameterTypes) 
//返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定的public成员方法。 
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
//返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
  • 创建对象的方法
 T newInstance() 
//创建此 Class 对象所表示的类的一个新实例。
  • 返回字符串的方法
 String getCanonicalName() 
//返回 Java Language Specification 中所定义的底层类的规范化名称。 
 String getName() 
//以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称(全限定名:包名.类名)。
 String getSimpleName() 
//返回源代码中给出的底层类的简称。 
 String toString() 
//将对象转换为字符串。 
  • 返回boolean的方法
boolean isLocalClass()     ;//判断是不是局部类,也就是方法里面的类 
boolean isMemberClass()    ;//判断是不是成员内部类,也就是一个类里面定义的类
boolean isAnonymousClass() ;//判断当前类是不是匿名类,匿名类一般用于实例化接口

3.2.2Field类

Field类提供类或接口中单独字段的信息,以及对单独字段的动态访问。

常用方法:

  • equals(Object obj)属性于obj相等则返回ture
  • get(Object obj)获得obj中对应的属性值
  • set(Object obj, Object value)设置obj中对应的属性值

3.2.3Method类

Method类代表某个类中的一个成员方法

常用方法为invoke(Object obj, Object… args)

传递object对象及参数调用该对象对应的方法

3.2.4ClassLoader类

类装载器是用来把类装载进JVM的。ClassLoader使用的双亲委托模型来搜索加载类的。

3.2.5Constructor类

Constructor类代表某个类中的一个构造方法

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值