一、什么是反射(Reflect)?
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。
对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
java中一切操作都是在类中,万事万物都是对象,类也是对象,是Class的对象(类是对象,类是java.lang.Class类的实例对象)
假设一个class Demo{}
Demo的实例对象是Demo d1 = new Demo();
而Demo类也是Class的实例对象,3种表达方式:
1、Class c1 = Demo.class;
2、Class c2 = Demo.getClass();
c1 c2 表示Demo的类类型(Class type)
c1 c2 都代表了Demo类的类类型,一个类只可能是Class类的一个实例对象
c1 == c2 是 true
3、 Class c3 = null;
c3 = Class.forName("包名.类名"); //类的全路径名获取
获取到类后可以进行如下操作:可以通过类的类类型创建该类的对象实例
Demo d2 = (Demo)c1.newInstance(); //前提是Demo要有无参构造函数
Class.forName(“包名.类名”);
表示类的类类型,还代表了动态加载类
编译时刻加载类是静态加载类,运行时刻加载类是动态加载类
new创建对象是静态加载类,在编译时刻就需要加载所有可能的使用的类
动态加载类在实际的开发中使用更为灵活,因为开发者不能每次都获取到用户想要使用的功能,而动态加载类能根据使用者自己的需求动态的提供给使用者不同的类。
通过放射机制获取方法信息:
getMethods()//获取所有的public的函数,包括父类继承而来
getDeclaredMethods()获取所有该类自己声明的方法,不问访问权限是一个Method[]数组
.getReturnType()//得到方法的返回值类型的类类型Class
m.getParameterTypes()//得到参数列表的类型的类类型 Class[]
public static void printClassMessage(Object obj) {
Class class1 = obj.getClass();
System.out.println("类的名称:"+class1.getName());
Method[] ms = class1.getMethods();
//class1.getDeclaredMethods();
for(int i=0;i<ms.length;i++) {
function(){ //外汇返佣:http://www.fx61.com
Class returnType = ms.getReturnType();
System.out.print(returnType.getName()+" ");//方法返回类型
System.out.print(ms.getName()+"("); //方法名
Class[] parameters = ms.getParameterTypes();
for(Class c:parameters) {
System.out.print(c.getName()+",");
}
System.out.println(")");
}
}
获取成员变量信息:
Reflect.Field封装了关于成员变量的操作
getFields()//获取的是所有的public成员变量的信息
getDeclaredFields()//获取该类自己声明成员变量信息
public static void printClassFields(Object obj) {
System.out.println("--------------打印类的成员变量-----------");
Class class1 = obj.getClass();
System.out.println("类的名称:"+class1.getName());
Field[] fields = class1.getDeclaredFields();
for(Field fs : fields) {
Class fieldType = fs.getType();
String TypeName = fieldType.getName();
String fieldName = fs.getName();
System.out.println(TypeName+" "+fieldName);
}
}
获取构造函数信息:
public static void printClassConstruct(Object obj) {
Class class1 = obj.getClass();
//Constructor[] cs = class1.getConstructors();
Constructor[] constructors = class1.getDeclaredConstructors();
for(Constructor cs:constructors) {
System.out.print(cs.getName()+"(");
Class[] typePara = cs.getParameterTypes();
for(Class ty:typePara) {
System.out.print(ty.getName()+",");
}
System.out.println(")");
}
}
反射能够让我们:
在运行时检测对象的类型;
动态构造某个类的对象;
检测类的属性和方法;
任意调用对象的方法;
修改构造函数、方法、属性的可见性;
以及其他。
反射示例:Class.forName()方法可以通过类或接口的名称(一个字符串或完全限定名)来获取对应的Class对象。forName方法会触发类的初始化。
// 使用反射
Class<?> c = Class.forName("classpath.and.classname");
Object dog = c.newInstance();
Method m = c.getDeclaredMethod("bark", new Class<?>[0]);
m.invoke(dog);
Class c = "foo".getClass();
这返回的是String类型的class
enum E { A, B }
Class c = A.getClass();
A是枚举类型E的实例,所以返回的是E的Class
byte[] bytes = new byte[1024];
Class c = bytes.getClass();
(官方解释数组类型的getClass())Since arrays are Objects, it is also possible to invoke getClass() on an instance of an array. The returned Class corresponds to an array with component type byte.
Set<String> s = new HashSet<String>();
Class c = s.getClass();
这里Set是一个接口,getClass()返回的是HashSet的class
The .class Syntax
boolean b;
Class c = b.getClass(); // compile-time error
Class c = boolean.class; // correct
TYPE Field for Primitive Type Wrappers
Class c = Double.TYPE;
Methods that Return Classes
Class.getSuperclass()
返回指定类的super class
Class c = javax.swing.JButton.class.getSuperclass();
The super class of javax.swing.JButton is javax.swing.AbstractButton.
Class.getClasses()
返回当前类的所有public classes, interfaces, and enums
Class.getDeclaredClasses()
Returns all of the classes interfaces, and enums that are explicitly declared in this class.
Class.getEnclosingClass()
Returns the immediately enclosing class of the class.
Class c = Thread.State.class().getEnclosingClass();
The enclosing class of the enum Thread.State is Thread.
public class MyClass {
static Object o = new Object() {
public void m() {}
};
static Class<c> = o.getClass().getEnclosingClass();
}
The anonymous class defined by o is enclosed by MyClass.
方法的反射:
操作:method.invoke(对象,参数列表)
获取方法 名称和参数列表来决定
getMethod是获取public的方法
getDeclaredMethod获取自己申明的方法
public class MethodDemo1 {
|
|