反射(reflect),本来是动态语言中的特性。Java中的反射相对于Python来看就有点难看了。
为了体现反射。首先定义一个接口和一个实现类。
public interface TestInterFace {
public void TestInterFace();
}
public class TestClass extends Object implements TestInterFace {
// 字段
private String testClassName = "";
protected double[] doubleTestArray;
public int testClassNum = 0;
// 属性(get/set)
public String getTestClassName() {
return testClassName;
}
public void setTestClassName(String testClassName) {
this.testClassName = testClassName;
}
public int getTestClassNum() {
return testClassNum;
}
public void setTestClassNum(int testClassNum) {
this.testClassNum = testClassNum;
}
// 构造器
public TestClass() {
System.out.println("调用构造器TestClass()");
}
public TestClass(String testClassName, int testClassNum) {
this.testClassName = testClassName;
this.testClassNum = testClassNum;
System.out
.println("调用构造器TestClass(String testClassName,int testClassNum)");
}
// 方法
// 私有方法
private void privateMethod() {
}
// 保护方法
protected void protectedMethod() {
}
// 公有方法
public void TestClassMethod() {
System.out.println("调用了TestClass类的void TestClassMethod()方法");
}
public String TestClassMethod(String i) {
System.out
.println("调用了TestClass类的String TestClassMethod(String i)方法,传入的参数为"+ i);
return i;
}
public void TestInterFace() {
System.out.println("这是TestInterFace接口的实现");
}
}
上面的类基本是照顾到了类的各个方面,除了内部类等。
说明:
(1)java.lang.reflect包中包含了反射的中使用的各种类。使用反射前需要导入。
(2) 若Class对象的方法名称中有Declared。则说明这个方法可以访问Class对象对应类的任意成员,无视访问权限(private,friendly,protected,public)。若没有则只能访问public的类成员。
(3)带Declared的方法破坏了oop的封装机制。
(4)若用反射调用类的方法,则无视多态的限制。可以没有限制的调用对象的运行时类型的方法。无视对象的编译时类型。这个在下篇文章中用代码阐述。
接下来看Java的反射。
首先,
通过反射获得类的相关信息。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Reflect_to_get_ClassInformation {
public static void main(String[] args) throws Exception {
// 获得Class对象
System.out.println("获得Class对象");
// 方法1
Class c1 = Class.forName("TestClass");
System.out
.println("方法1:使用Class.forName。如Class c=Class.forName(\"TestClass\");\t得到的Class对象为"
+ c1);
// 方法2
Class c2 = TestClass.class;
System.out
.println("方法2:使用*(类).Class。如Class c2=TestClass.class;\t得到的Class对象为"
+ c2);
// 方法3
TestClass testClassInstance = new TestClass();
Class c3 = testClassInstance.getClass();
System.out
.println("方法3:使用*(实例).getClass()。如Class c3=testClassInstance.getClass();;\t得到的Class对象为"
+ c3);
// 从Class对象中获取信息。
// 获取Class对象对应类的构造器Constructor对象
System.out.println();
System.out.println("获取Class对象对应类的构造器Constructor对象");
// 方法1
Constructor constructor1 = c1.getConstructor();
Constructor constructor2 = c1.getConstructor(String.class, int.class);
System.out.println("方法1:Constructor constructor1=c1.getConstructor();\t获得有参数构造器:"+ constructor1);
System.out.println(" :Constructor constructor2=c1.getConstructor(String.class,int.class);\t获得有参数构造器:"+ constructor2);
// 方法2
Constructor[] constructor_array = c1.getConstructors();
System.out.println("方法2:Constructor[] constructor_array=c1.getConstructors();以数组的形式返回所有构造器\t得到构造器数组");
for (Constructor constructor : constructor_array) {
System.out.println("\t\t\t构造器[]:" + constructor);
}
// 方法3
// 方法4
// 获取Class对象获取类的方法Method对象。
System.out.println();
System.out.println("获取Class对象获取类的方法Method对象。");
// 方法1
Method method1 = c1.getMethod("TestClassMethod");
Method method2 = c1.getMethod("TestClassMethod", String.class);
System.out.println("方法1:返回TestClassMethod无参数method对象" + method1);
System.out.println("\t ;返回TestClassMethod有参数method对象" + method2);
// Method method3 = c1.getMethod("privateMethod");
// System.out.println("方法1:返回私有方法Method对象" + method3);
System.out.println("该方法只能返回public方法Method对象,对private,protected则会报错。");
// 方法2
Method[] method_array = c1.getMethods();
System.out.println("方法2:以数组方式返回类的所有的方法method对象");
for (Method method : method_array) {
System.out.println("\t\t\t方法:" + method);
}
//方法3
Method method3 = c1.getDeclaredMethod("privateMethod");
System.out.println("方法3:使用getDeclaredMethod().无视private,protected。返回私有方法Method对象" + method3);
//方法4
Method[] method_all_array = c1.getDeclaredMethods();
System.out.println("方法4:getDeclaredMethods(),以数组方式返回类的所有的方法method对象,无视private,protected");
for (Method method4 : method_all_array) {
System.out.println("\t\t\t方法[]:" + method4);
}
System.out.println();
// 获取Class对象对应类的字段Field对象。
System.out.println();
System.out.println("获取Class对象对应类的字段Field对象。");
// 方法1
Field field1 = c1.getField("testClassNum");
System.out.println("方法1 ;返回TestClassMethod中的Field对象" + field1);
// Field field2 = c1.getField("testClassName");
// System.out.println("\t:返回TestClassMethod中的Field对象" + field2);
System.out.println("该方法只能返回public字段Field对象,对private,protected则会报错。");
// 方法2
Field[] field_array = c1.getFields();
System.out.println("方法2:以数组方式返回类的所有的public字段Field对象");
for (Field field : field_array) {
System.out.println("\t\t\t字段[]:" + field);
}
// 方法3
Field field3 = c1.getDeclaredField("testClassNum");
System.out.println("方法3:使用getDeclaredField()。该方法可以返回任意访问权限的字段。无视private,protected。返回TestClassMethod中的Field对象" + field3);
// 方法4
Field[] field_all_array = c1.getDeclaredFields();
System.out.println("方法4:以数组方式返回类的所有的字段Field对象,无视private,protected。");
for(Field field4:field_all_array){
System.out.println("\t\t\t字段[]"+field4);
}
System.out.println();
// 获取Class对象对应类的 注释 对象。
System.out.println();
// 获取Class对象对应类的 内部类Class对象。
System.out.println();
// 获取Class对象对应类的 外部类Class对象。
System.out.println();
// 获取Class对象对应类所实现的接口。
System.out.println();
System.out.println("获取Class对象对应类所实现的接口Class对象。");
Class[] interface_array = c1.getInterfaces();
System.out.println("方法2:以数组方式返回类的所有的public字段Field对象");
for (Class inter : interface_array) {
System.out.println("\t\t\t接口:" + inter);
}
System.out.println();
// 获取Class对象对应类的父类Class对象。
System.out.println();
System.out.println("获取Class对象对应类的父类Class对象。");
Class super_c = c1.getSuperclass();
System.out.println("方法1:Class super_c = c1.getSuperclass();所得到的父类Class对象的super_c为"+super_c);
}
}
通过反射实例化Class对象所对应类与方法调用。
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Reflect_Operate_Class {
public static void main(String[] args) throws Exception {
//通过反射用Class对象实例化该对象对应类的实例。
System.out.println("通过反射用Class对象实例化该对象对应类的实例。");
Class c=Class.forName("TestClass");
//方法1
Object tc1=c.newInstance();
System.out.println("方法1:Class c=Class.forName(\"TestClass\");该方法只能调用默认无参数构造");
//方法2
Constructor constructor1=c.getConstructor();
Object tc2=constructor1.newInstance();
System.out.println("方法2.1:Constructor constructor1=c.getConstructor();TestClass tc2=(TestClass)constructor1.newInstance();");
Constructor constructor2=c.getConstructor(String.class,int.class);//注意到得到对应的构造器
TestClass tc3=(TestClass)constructor2.newInstance("构造器",100);
System.out.println("方法2.2:Constructor constructor2=c.getConstructor();TestClass tc3=(TestClass)constructor1.newInstance(\"构造器\",100);构造器有参数实例化");
//调用Class所对应的类方法。
Object obj=c.newInstance();
Method method1=c.getMethod("TestClassMethod");
method1.invoke(obj);
Method method2=c.getMethod("setTestClassNum",int.class);
method2.invoke(obj,100);
//访问属性
}
}
以上的代码均通过运行。基本可以体现反射的一些基本用法了。等有什么新的东西,再更新吧。