java反射机制
概述
rtti:运行时类型信息使得你可以在程序运行时发现和使用类型信息。但是这个类型在编译时必须已知,这样才能使用rtti识别他,并利用这些信息做一些有用的事。换句话说,在编译时,编译器必须知道所有要通过rtti来处理的类。
但是,在编译时程序根本没法获知这个对象所属的类。例如,假设你从磁盘文件或者网络连接中获取一串字节,并且你被告知这些字节代表了一个类。这时候需要通过反射。这样也可以达到在跨网络的远程平台上创建和运行对象的能力。即远程方法调用(rmi).
定义
java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。只用反射的前提就是必须先得到代表的字节码的class,class类用于表示.class文件(字节码)
反射其实是获取类的字节码文件,也就是.class文件,那么我们就可以通过class这个对象进行获取。
-
getclass()方法
public static void main(string[] args) { getclass get = new getclass(); class c = get.getclass(); system.out.println(c.getname()); }
2..class方法
public static void main(string[] args) { class c = getclass.class; system.out.println(c.getname()); }
-
class.forname(string name)
public static void main(string[] args) { class c =class.forname("getclass") system.out.println(c.getname()); }
那么这3中方式我们一般选用哪种方式呢?第一种已经创建了对象,那么这个时候就不需要去进行反射了,显得有点多此一举。第二种需要导入类的包,依赖性太强。所以我们一般选中第三种方式。
反射机制的相关类
类名 | 用途 |
---|---|
class类 | 代表类的实体,在运行的java应用程序中表示类和接口 |
field类 | 代表类的成员变量(成员变量也称为类的属性) |
method类 | 代表类的方法 |
constructor类 | 代表类的构造方法 |
class类
class代表类的实体,在运行的java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
-
获得类相关的方法
方法 | 用途 |
---|---|
assubclass(class<u> clazz) | 把传递的类的对象转换成代表其子类的对象 |
cast | 把对象转换成代表类或是接口的对象 |
getclassloader() | 获得类的加载器 |
getclasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getdeclaredclasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
forname(string classname) | 根据类名返回类的对象 |
getname() | 获得类的完整路径名字 |
newinstance() | 创建类的实例 |
getpackage() | 获得类的包 |
getsimplename() | 获得类的名字 |
getsuperclass() | 获得当前类继承的父类的名字 |
getinterfaces() | 获得当前类实现的类或是接口 |
-
获得类中属性相关的方法
方法 | 用途 |
---|---|
getfield(string name) | 获得某个公有的属性对象 |
getfields() | 获得所有公有的属性对象 |
getdeclaredfield(string name) | 获得某个属性对象 |
getdeclaredfields() | 获得所有属性对象 |
-
获得类中注解相关的方法
方法 | 用途 |
---|---|
getannotation(class<a> annotationclass) | 返回该类中与参数类型匹配的公有注解对象 |
getannotations() | 返回该类所有的公有注解对象 |
getdeclaredannotation(class<a> annotationclass) | 返回该类中与参数类型匹配的所有注解对象 |
getdeclaredannotations() | 返回该类所有的注解对象 |
-
获得类中构造器相关的方法
方法 | 用途 |
---|---|
getconstructor(class...<?> parametertypes) | 获得该类中与参数类型匹配的公有构造方法 |
getconstructors() | 获得该类的所有公有构造方法 |
getdeclaredconstructor(class...<?> parametertypes) | 获得该类中与参数类型匹配的构造方法 |
getdeclaredconstructors() | 获得该类所有构造方法 |
-
获得类中方法相关的方法
方法 | 用途 |
---|---|
getmethod(string name, class...<?> parametertypes) | 获得该类某个公有的方法 |
getmethods() | 获得该类所有公有的方法 |
getdeclaredmethod(string name, class...<?> parametertypes) | 获得该类某个方法 |
getdeclaredmethods() | 获得该类所有方法 |
-
类中其他重要的方法
方法 | 用途 |
---|---|
isannotation() | 如果是注解类型则返回true |
isannotationpresent(class<? extends annotation> annotationclass) | 如果是指定类型注解类型则返回true |
isanonymousclass() | 如果是匿名类则返回true |
isarray() | 如果是一个数组类则返回true |
isenum() | 如果是枚举类则返回true |
isinstance(object obj) | 如果obj是该类的实例则返回true |
isinterface() | 如果是接口类则返回true |
islocalclass() | 如果是局部类则返回true |
ismemberclass() | 如果是内部类则返回true |
field类
field代表类的成员变量(成员变量也称为类的属性)。
方法 | 用途 |
---|---|
equals(object obj) | 属性与obj相等则返回true |
get(object obj) | 获得obj中对应的属性值 |
set(object obj, object value) | 设置obj中对应属性值 |
method类
method代表类的方法。
方法 | 用途 |
---|---|
invoke(object obj, object... args) | 传递object对象及参数调用该对象对应的方法 |
constructor类
constructor代表类的构造方法。
方法 | 用途 |
---|---|
newinstance(object... initargs) | 根据传递的参数创建类的对象 |
反射用例
被反射类book
package rtti.reflect; public class book { private static final string tag = "booktag"; private string name; private string author; public void setname(string name) { this.name = name; } public void setauthor(string author) { this.author = author; } public string getname() { return name; } public string getauthor() { return author; } @override public string tostring(){ return "book[ "+name+" "+author+" ]"; } public book(){} private book(string name,string author){ this.name = name; this.author =author; } private string declaremethod(int index){ string str = null; switch (index){ case 0: str = "declaremethod 1 !"; break; case 1: str = "declaremethod 2 !"; break; default: str = "declaremethod 3 !"; } return str; } }
反射逻辑封装类
public class reflecttest { private final static string tag = "rtti.reflect.reflectclass"; public static void main(string[] args) { reflectnewinstance(); reflectprivatecons(); reflectprivatefield(); reflectprivatemethod(); } //创建对象 public static void reflectnewinstance(){ try { class<?> bookclass = class.forname("rtti.reflect.book"); object obj = bookclass.newinstance(); book book =(book)obj; book.setname("黄金时代"); book.setauthor("王小波"); system.out.println(tag+",reflectnewinstance book="+book.tostring()); } catch (exception e) { e.printstacktrace(); } } //反射私有的构造方法 public static void reflectprivatecons(){ try { class<?> bookclass = class.forname("rtti.reflect.book"); constructor<?> cons = bookclass.getdeclaredconstructor(string.class,string.class); cons.setaccessible(true); object obj= cons.newinstance("黄金时代","王小波"); book book =(book)obj; system.out.println(tag+",reflectnewinstance book="+book.tostring()); } catch (exception e) { e.printstacktrace(); } } //反射私有属性 public static void reflectprivatefield(){ try { class<?> bookclass = class.forname("rtti.reflect.book"); object obj = bookclass.newinstance(); field fieldtag = bookclass.getdeclaredfield("tag"); fieldtag.setaccessible(true); field fieldname = bookclass.getdeclaredfield("name"); fieldname.setaccessible(true); string tag = (string)fieldtag.get(obj); string name = (string)fieldname.get(obj); system.out.println(tag+",reflectprivatefield tag,name = "+tag+","+name); }catch (exception e){ e.printstacktrace(); } } //反射私有方法 public static void reflectprivatemethod(){ try{ class<?> bookclass = class.forname("rtti.reflect.book"); object obj = bookclass.newinstance(); method method = bookclass.getdeclaredmethod("declaremethod",int.class); method.setaccessible(true); string str = (string) method.invoke(obj,1); system.out.println(tag+",reflectprivatemethod str ="+str); }catch (exception e){ e.printstacktrace(); } } }
反射应用
-
访问一些不能访问的变量或者属性:破解别人代码
-
数据库jdbc中通过class.froname(driver)来获取数据库连接驱动
-
分析类文件
-
工厂模式,factory类中用反射的话,添加一个新类,就不需要修改工厂类factory了。、
-
远程方法调用
参考文献