07.java的反射机制

Java的反射机制

1.反射的相关概念

Java语言的反射机制:在java 运行时环境中,对于任意一个类,能否知道这个类有哪些

属性和方法,对于任意一个对象,能否调用它的任意一个方法,答案是肯定的,这种动态获

取类的信息以及动态调用对象的方法的功能来自于java 语言的反射(Reflection)机制。

Java反射机制主要提供了以下的功能:

1.在运行时判断任意一个对象所属的类。

2.在运行时构造任意一个类的对象。

3.在运行时判断任意一个类所具有的成员变量和方法。

4.在运行时调用任意一个对象的方法。

反射(Reflection):是java 被视为动态(或准动态)语言的一个关键性质。这个机制

允许程序在运行时通过Reflecttion APIs 取得任意一个已知名称的class 的内部信

息,包括其修饰符(诸如public static 等等)父类(例如Object) 实现之接口(例

如serializable),也包括成员变量和方法的所有信息,并可于运行时改变成员变量的内

容或者调用方法(包括私有方法,我们知道被private 修饰的封装的机制,是不能被外部

所使用的,但是通过反射,我们可以改变私有变量和方法)。

动态语言和非动态语言:一般而言,开发者社群说到的动态语言,大致认同的一个定义是:

“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言。”从这个观点看,

Perl Python Ruby javascript 是动态语言,C++,java,C#不是动态语言。

Java语言的动态性:尽管我们刚才说道,在这样的定义与分类下java 不是动态语言,它

却有着一个非常突出的动态相关机制:反射(Reflection)。这个词的意思是“反射,影

响,倒影”,用在java 身上指的是我们可以于运行时加载,探知,使用编译期间完全位置

的classes。换句话说,java 程序可以加载一个运行时才得知名称的class 获悉其完整

结构(但不包括方法定义),并生成其对象的实体,或对其成员变量设置,或者唤起其方法,

这种“看透class”的能力被称为introspection(内省,内观)反射和内观是经常并提

的两个术语。

2、具体Api

以上是对java 的反射机制的一个大体的了解,但是还是有一种朦胧的感觉,摸不着头脑,

下面我们从jdk 中,从具体的API 中,认识java 的反射机制:

在JDK 中,主要由以下类来实现java 的反射机制,这些类都位于java.lang.reflect

包中:

--Class类:代表一个类

--Field类:代表类的成员变量(成员变量也称为类的属性)

--Method类,代表类的方法

--Constructor类:代表类的构造方法

--Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

以上类,是在使用反射机制时一定会用到的

2.反射的基石------Class

Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值,java程序中的各个java类,他们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?这个类的名字就是Class,要注意与小写的class关键字的区别,Class类描述了哪些方面的信息呢,类的名字,类的访问属性,类所在的包,字段名称的列表,方法名称的列表等等,学习反射,首先要明白Class这个类。

一句话,java程序中的各个类属于同一类事物,描述这类事物的java类名就是Class

1.对比提问:众多的人用一个什么来表示?众多的java类用一个什么类来表示?

(1)人---person

(2)Java---Class

2.对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表java类,它的各个实例对象又分别对应什么呢?

(1)对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类额字节码等、

(2)一个类被类加载器加载到内存中,占用了一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?

3.如何得到各个字节码对应的实例对象(Class类型)?

(1)类名.class 例如System.class

(2)对象.getClass 例如new Date().getClass();

(3)Class.forName("类型")  例如Class.forName("java.util.Date");

Class.forName("类型")的含义:获取该类的内存字节码(两个含义,一个是该类已经被加载到内存中,然后获取,另外一个是该类第一次被加载到内存中)

4.九个预定义Class实例对象:八个基本数据类型+void

(1)查看Class.isPrimitive方法的帮助

(2)Int.class == Integer.TYPE 返回true

5.数组类型的Class实例对象

class.isArray()返回是否是一个数组类

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如int[]  void

3.构造方法的反射应用

--Constructor类:代表类的构造方法

--得到某个类的所有构造方法:

Constructor[] constructor = Class.forName("java.lang.String").getConstructor();

--创建实例对象

通用方式:String str = new String(new StringBuffer("abc"));

反射方式:

Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

String str2 = constructor1.newInstance(new StringBuffer("abc")); 

--实例使用两种创建String的方式创建对象

除此之外,在我们获得构造方法对象以后,这个对象还有其它很多的方法,可以参考帮助文档,最重要的一个方法就是newInstance创建该类型的实例的方法。另外,除了这样一种创建实例的方法外,Class类还为我们提供了另外一种无参的创建实例的方法。

当然,我们可以不使用A方法,完全使用B方法,不会影响反射机制,A方法的使用也有好处,但我们需要创建无参实例的时候,就可以省略一步:

AClass.newInstance()

B:  Class.getConstructor().newInstance();

4.成员变量的反射

--Field类:代表类的成员变量(成员变量也称为类的属性)

--得到某个类的特定成员变量:

Field field = 类.class.getField("属性名");

--得到某个类的所有成员变量(非private修饰):

Field[] field = 类.class.getFields();

--通过反射,获取该类的所有属性(一个是private修饰一个是public修饰)

这种方式可以获得其属性值,但是只适用于public修饰的,公共的,如果我们按照同样的方法访问private修饰的属性的时候,会出现什么状况呢?会出现很多异常,为此我们需要解决两个问题:

(1)如何得到被private修饰的属性的Field对象(字节码)  --getDeclaredField

(2)如何访问使用被private修饰的属性  --privateField.setAccessible(true)

5.成员变量的使用--实例

做一个实例,在ReflectTest类中新增三个String成员变量,通过反射机制访问这个类的所有属性,如果发现属性的类型是String类型的,则将其属性的值中b的字符全部变成a,然后输出。

6.成员方法的反射

--Method类,代表类的方法

--获取类中指定方法的字节码方法:

Method method = 类.class.getMethod('方法名字',方法参数[]);方法参数为type非具体值

--如何执行方法

Method.invoke("执行类的对象","具体参数");

1.41.5invoke方法的区别:

Jdk1.5:public Object invoke(Object obj,Object args)

Jdk1.4:public Object invoke(Object obj,Object[]{ args1,args2});即按照1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中每个元素分别对应被调用的方法中的一个参数,所以调用charAt方法的代码也可以用jdk1.4改写为method.invoke(str,new Object[]{1})的形式

--用反射方式执行某个类中的main方法

通用方式:类.mainnew String[]{args1,args2...};

反射方式:

7.数组的反射应用

每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。比如:

1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的class实例对象

2.代表数组的Class实例对象的getSuper()方法返回父类为Oject类对应的Class

3.基本类型的一纬数组可以被当作Object类型使用,不能当作Object[]数组使用,非基本类型的一维数组既可以当作Object类型使用,又可以当作Object[]类型使用

4.Array.asList()方法处理int[]String[]时的差异

5.Array工具类用于完成对数组的反射操作

下面一个例子,使用反射接受一个Object对象,如果这个对象是一个数组,则打印这个数组的所有元素,反之,则直接打印这个object的值

思考,如果得到数组中的元素类型?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值