什么是反射?
可以想想参数的概念,当我们不能确定值为多少时可以引入一个参数来将参数值确定的时间延迟到运行的时候,数据类型无法确定时则使用泛型,那么当我们无法确定使用那个类、哪个对象或者哪个方法时,可以使用反射。
类型信息
每个类都会产生一个对应的class对象保存在.class文件中,第一次使用该类时动态加载到jvm,当程序创建对类的静态成员的引用时就会加载这个类,类加载时会生成类的class对象,里面记录着类的相关信息,可以将它看作是类实例的模板,这个class对象就是类型信息
RTTI --RunTime Type Information
Java提供了两种让我们运行时识别对象和类的信息的方式,RTTI就是传统的一种:
A a =new A(); a.method()
是假设我们在编译时就知道A类的类型信息(这里即知道它有这个method方法),编译器在编译时打开和检查.class文件
另一种则是反射,它是在运行时打开和检查.class文件,就是把java类中的各个成分映射成一个个Java对象,对于任意一个类,都能够知道它的所有属性和方法,对任意一个对象,都能够调用它的任意对象和方法,这种动态获取信息以及动态调用对象方法的功能成为java的反射机制。本质就是在得到类型信息(class对象)后反向获取类对象的基本信息
利用反射动态获取class对象
//方法一
Class cls1 = A.class;
//方法二
A a = new A()
Class cls2 = a.getClass();
//方法三 动态加载 常用
Class cls3 = Class.forName("包名.A");
//这三个class对象是同一个(唯一性)
利用反射动态创建类实例对象
//1、获取class对象
Class cls = Class.forName("全类名");
//2.1方法一,要求A必须有一个无参构造方法,一般使用这个方法
A a = (A)cls.newInstance();
//2.2方法二,要求A必须有一个无参构造方法
/**
getConstructor:获取在本类能够访问的构造器
getDeclaredConstructor:获取所有的构造器,包括private
getConstructors:获取所有的构造器,返回数组
getDeclaredConstructors:获取所有构造器,返回数组
参数:动态参数,具体构造方法的参数类型
*/
Constructor cs = cls.getConstructor();//获取在本类能够访问的构造器
A a = (A)cs.newInstance()//若有参数则传值
使用反射调用方法
Class cls = Class.forName("全类名");
Method m = cls.getMethod(“方法名”,参数列表-形参)//获取方法对象
m.invoke(参数列表-实参)//执行方法
使用反射操作属性
//获取属性对象
Field f = cls.getDeclaredField("")
//调用私有属性前需设置访问权限
f.setAccessible(true);
//设置值
f.set(属性名,值);
//获取值
f.get(属性名);
一般属性都是私有的,这有点暴力,可以通过调用属性对应的get、set方法来操作属性
//获取属性对象
Field f = cls.getDeclaredField("")
//构建get方法
String fName = f.getName();//获取字段名称
String MethodName = "get" + fName.substring(0,1).toUpperCase() + fName.substring(1);
//根据名称获取方法对象
Method = cls.getMethod(MethodName)
//同上可进行对方法的操作
通过反射读取配置文件
propertise:
InputStream is = 任类名.class.getClassLoader().getResourceAsStream("配置文件");
Properties p = new Properties();
p.load(is);
String clsName = p.getProperty("")//获取类名
//动态加载该类、、
xml:
//使用Dom4j组件解析xml文件 需导入dom4j的jar包
SAXReader reader = new SAXReader();
InputStream is = 任类名.class.getClassLoader().getResourceAsStream("配置文件");
Document doc = reader.read(is);
//获取根节点
Element root = doc.getRootElemment();
//使用迭代器获取节点
Iterator<Element> it = root.elementIterator();
while(it.hasNext()){
Element e = it.next();
//e.elementText(“name”)
//e.elementText(“value”)
/**
xml中的节点例子:
<oper>
<name> </name>
<value> </value>
</oper>
*/
}