Java反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
Java如何能够做出上述的动态特性呢?这是一个深远话题,本文对此只简单介绍一些概念。整个篇幅最主要还是介绍Reflection APIs,也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其methods。本文将谈到java.lang.Class,以及java.lang.reflect中的Method、Field、Constructor等等classes。
Class
众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。
Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的!因为Class并没有public constructor。
反射示例
示例代码展示了Java反射常见的使用场景,代码和运行结果都有,比较明了,不做详细介绍。这里需要注意的一点是:通过反射可以调用某个类定义的私有方法(Methods)、私有变量(Fields)和私有构造方法,只是在使用之前需要设定setAccessible(true)
,否则将会抛出IllegalAccessException
异常。
public class ReflectDemos {
public static void main(String[] args) {
Person person = new Person("Yue", 2, 21.3);
System.out.println("person:-> " + person);
Class clazz1 = null;
Class clazz2 = null;
Class clazz3 = Person.class;
try {
System.out.println("------------Get Class Object for class Person------------");
clazz1 = person.getClass();
clazz2 = Class.forName("com.qqmaster.com.reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("Classes of Person are equal ? -> " + clazz1.equals(clazz2));
System.out.println("Classes of Person are equal ? -> " + clazz2.equals(clazz3));
System.out.println("\n\n------------Get Fields for class Person------------");
/**
* Get all fields of class Person.
*/
Field[] declaredFields = clazz1.getDeclaredFields();
System.out.println("------------all declared Fields:------------");
for(Field field: declaredFields){
System.out.println(field);
}
System.out.println("\n------------all Fields:------------");
Field[] Fields = clazz1.getFields();
for(Field field: Fields){
System.out.println(field);
}
System.out.println("\n\n------------Get Methods for class Person------------");
System.out.println("------------all declared declaredMethods:------------");
Method[] declaredMethods = clazz1.getDeclaredMethods();
for(Method method : declaredMethods){
System.out.println(method);
}
System.out.println("\n------------all methods:");
Method[] methods = clazz1.getMethods();
for(Method method : methods){
System.out.println(method);
}
System.out.println("\n\n------------Invoke Fields for class Person----");
try {
clazz1.getDeclaredField("name").set(person, "YueYue");
Field field_age = clazz1.getDeclaredField("age");
field_age.setAccessible(true);
field_age.set(person, 3);
field_age.setAccessible(false);
clazz1.getDeclaredField("weight").set(person, 22.3);
System.out.println("person:-> " + person);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("\n\n------------Invoke Methods for class Person----");
try {
Method method1 = clazz1.getDeclaredMethod("getRealAge");
method1.setAccessible(true);
System.out.println("invoke1->" + method1.invoke(person));
Method method2 = clazz1.getDeclaredMethod("getAge");
System.out.println("invoke2->" + method2.invoke(person));
Method method3 = clazz1.getDeclaredMethod("setAge", int.class);
method3.invoke(person, 6);
System.out.println("invoke2->" + person);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("\n\n------------constructors----");
Constructor[] constructors = clazz1.getConstructors();
for(Constructor constructor:constructors){
System.out.println(constructor);
}
System.out.println("\n\n------------Build new Instance----");
try {
Person p1 = (Person)clazz1.newInstance();
System.out.println("p1->" + p1);
Person p2 = (Person)clazz1.getConstructor().newInstance();
System.out.println("p2->" + p2);
Person p3 = (Person)clazz1.
getConstructor(String.class, int.class, double.class)
.newInstance("MinYue", 3, 22.3);
System.out.println("p3->" + p3);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
/**
* int is primitive type, But Integer is a class.
*/
System.out.println("\n\n------------Other Reflect Demos----");
Class clazz_int = int.class;
Class clazz_Integer = Integer.class;
Class clazz_void = void.class;
System.out.println("int.class equals Integer.class? " + clazz_int.equals(clazz_Integer));
System.out.println("\n\n------------Class of Class------------");
Class clazz_Class = Class.class;
Constructor[] cs = clazz_Class.getDeclaredConstructors();
System.out.println();
for(Constructor c:cs){
System.out.println(c.getName());
}
}
}
public class Person {
public String name;
private int age;
protected double weight;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age, double weight){
this.name = name;
this.age = age;
this.weight = weight;
}
@SuppressWarnings("unused")
private Person(){
this.name = "MasterQuan";
this.age = 28;
this.weight = 55.5;
}
protected String getFullName(){
return "full : " + name;
}
private int getRealAge(){
return age + 3;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", weight=" + weight + "]";
}
}
运行结果:
person:-> Person [name=Yue, age=2, weight=21.3]
------------Get Class Object for class Person------------
Classes of Person are equal ? -> true
Classes of Person are equal ? -> true
------------Get Fields for class Person------------
------------all declared Fields:------------
public java.lang.String com.qqmaster.com.reflect.Person.name
private int com.qqmaster.com.reflect.Person.age
protected double com.qqmaster.com.reflect.Person.weight
------------all Fields:------------
public java.lang.String com.qqmaster.com.reflect.Person.name
------------Get Methods for class Person------------
------------all declared declaredMethods:------------
public java.lang.String com.qqmaster.com.reflect.Person.toString()
public void com.qqmaster.com.reflect.Person.setAge(int)
public int com.qqmaster.com.reflect.Person.getAge()
private int com.qqmaster.com.reflect.Person.getRealAge()
protected java.lang.String com.qqmaster.com.reflect.Person.getFullName()
------------all methods:
public java.lang.String com.qqmaster.com.reflect.Person.toString()
public void com.qqmaster.com.reflect.Person.setAge(int)
public int com.qqmaster.com.reflect.Person.getAge()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
------------Invoke Fields for class Person----
person:-> Person [name=YueYue, age=3, weight=22.3]
------------Invoke Methods for class Person----
invoke1->6
invoke2->3
invoke2->Person [name=YueYue, age=6, weight=22.3]
------------constructors----
public com.qqmaster.com.reflect.Person()
public com.qqmaster.com.reflect.Person(java.lang.String,int,double)
------------Build new Instance----
p1->Person [name=MasterQuan, age=28, weight=55.5]
p2->Person [name=MasterQuan, age=28, weight=55.5]
p3->Person [name=MinYue, age=3, weight=22.3]
------------Other Reflect Demos----
int.class equals Integer.class? false
------------Class of Class------------
java.lang.Class
网友评论