反射,类加载

来源:互联网 发布:seo外包北京华网 编辑:程序博客网 时间:2024/05/16 11:02

一.反射是什么

所谓反射,本来是JAVA虚拟机自己使用的一个机制,在类加载时期产生一个Class对象,这个对象记录了这个类的所有信息,除了注释。现在是指在Java中,可以再运行期载入、探知和使用编译期完全未知的类的一种机制。

二.反射做什么

Java程序可以装在一个运行期才得到名称的类,并创建对象、或者对类的成员变量设定值、或调用其方法。

三.反射与动态多态的关系

四.类加载的机制

1.类加载

由类加载器完成,类的class文件读入内存后,就会创建一个java.lang.Class对象(类模板对象)。一旦某个类被载入JVM中,同一个类就不会再次被载入。
一个类的类模板对象只有一个,但是实例对象可以有无数个。

2.连接

把类的二进制文件合并到JRE中。

3.初始化

JVM负责对类进行初始化,也就是对静态属性进行初始化。在Java类中,对静态属性指定初始值的方式有两种:(1)声明静态属性时指定初始值(2)使用静态初始化块为静态属性指定初始值。

五.反射使用步骤

1.获得你想操作的类的java.lang.Class对象。

  1. 调用来自实例对象继承自Object的getClass()方法获取实例对象
DogBean dog = new Dog();Class DogClass = dog.getClass();  

利用这个方法可以得到所有类和数组的Class对象,但是没有编译时未知,运行时探究的动态效果。
2.利用语法类型名.class的方式获得Class对象

Class DogClass2 = DogBean.class;System.out.println(DogClass1 == DogClass2);//返回的是true,证明一个类只有一个Class对象。

同时还能得到基本数据类型的Class,但只能在JDK1.5以后使用。JDK 1.5之前使用Integer.TYPE获取Class对象。数据返回类型void也有Class对象。
但是,仍然没有编译时未知,运行时探究的动态效果。这种效果称为动态加载。
3.使用Class.forName(“全限定类名”)

Class DogClass3 = Class.forName("com.lovo.bean.DogBean");//全限定即要包含包名。

有编译时未知,运行时探究的动态效果。因为传入的类名只是一个字符串,是可以变化的。但是,不支持void,基本数据类型,数组。

2.调用诸如getDeclaredMethods等方法,特别是构造器和方法。(探究类的信息)

dogClass.getPackage().getName();//得到所在包的名字dogClass.getName();//得到类全名、类的限定名int intMod = dogClass.getModifiers();//得到访问修饰符+可选修饰符dogClass.getSuperClass();//得到父类//探究属性dogClass.getFields();//只能得到public的属性,包括从父类继承而来的public的属性。dogClass.getDeclaredFields();//得到所有的属性,但是不包括从父类得到的属性。

属性,构造,方法:1.所有公共的2.所有声明的3.公共指定的4.指定声明的。
Field,Constructor,Method,Declared。前三个通过加上‘s’后缀获得所有的。找指定的传参。

3.使用reflection API创建对象。

Constructor con = dogClass.getDeclaredConstructor(arguments[]);DogBean dog = (DogBean)con.newInstance(arguments[]);//通过newInstance方法新建一个对象。

好处:可以探究任意构造方法。坏处:太麻烦。

DogBean dog = null;dog = dogClass.newInstance();//但是调用的是只能是公共无参构造

好处:代码简洁。坏处:只能调用公共无参构造。

4.通过反射API设置访问权限

con.setAccessible(true);

设置con的访问权限为可访问—但是不到万不得已不准使用,破坏封装性。

5.操作属性

DogBean dog = new DogBean();Field theFileld = dogClass.getDeclaredField("name");theField.setAccessible(true);//万不得已,不准使用。theField.set(dog,"大黄");第一个参数代表到底是哪个对象,第二个参数代表要赋的值。theField.get(dog);

无论是赋值还是取值,都需要和对象绑定。如果属性的访问修饰符不让访问,同样访问不了。

6.调用探究到的方法。

DogBean snoopy = new DogBean();Method theM = dogClass.getMethod("bark");theM.invoke(snoopy,arguments[]);//调用使用invoke,同样要传入参数,到底是哪只狗的方法。

使用invoke调用方法。

7.数组的语法糖

当数组作为形式参数时尽量用三个点的方式,传入实参的时候不必传入一个数组。

public void test(int... array);//

这个时候array代表一个数组,可以传入任意多个参数。

六.反射的应用

0 0