0
点赞
收藏
分享

微信扫一扫

Java 反射机制


反射机制可以帮助我们在动态运行时,获得任意一个类的所有的构造器、方法、变量。很多主流框架都使用了反射技术.像SSH框架就采用了xml做配置文件+反射技术。
为了更好说明反射技术,我们将利用TestObject类来演示:

import java.util.HashMap;

public class TestObject {

private String myName;
private int myArg;
public String hobby;
public String schoolName;
protected String age;
public String[] arr = new String[]{"hello","world"};

public TestObject(){
System.out.println("调用TestObject的无参构造方法");
this.myName = "wongkyunban";
this.myArg = 23;
}
public TestObject(String name){
System.out.printf("调用TestObject的有一个String型参数的构造方法:%s\n",name);
this.myName = name;
this.myArg = 21;
}
private TestObject(int arg){
System.out.printf("调用TestObject的有一个int型参数的构造方法:%d\n",arg);
this.myName = "Jack";
this.myArg = arg;
}
public TestObject(int arg,String name){
System.out.printf("调用TestObject的有两个参数的构造方法");
this.myName = name;
this.myArg = arg;
}
public String getMyName() {
return myName;
}
public void setMyName(String myName) {
this.myName = myName;
}
public int getMyArg() {
return myArg;
}
public void setMyArg(int myArg) {
this.myArg = myArg;
}
private void con(){
System.out.printf("hello,%s\n","您调用了一个私有方法");

}
public void printHobby(){
System.out.printf("Hobby:%s\n",hobby);
}
protected void byebye(){
System.out.printf("Bye bye!\n");
}
public void handleData(String arg1 ,HashMap<Integer,String> map){
System.out.printf("%s--->%s\n",arg1,map.get("name"));
}
private void say(String name){
System.out.printf("hello,%s\n",name);
}
}

使用反射技术获得所有构造方法(包括私有的,非私有的)

默认权限的指的是没有修饰符修饰的。

方法

描述

public Constructor getConstructor(Class… parameterTypes)

获得指定的具有public访问权限的构造方法

public Constructor[] getConstructors()

获得所有的具有public访问权限的构造方法

public Constructor getDeclaredConstructor(Class… parameterTypes)

获得指定的构造方法,不管它的访问权限是什么。

public Constructor[] getDeclaredConstructors()

获得所有的构造方法,包括public, private,protected和默认权限的


示例代码:

//获取构造函数
private void getConstructor(){
try {
Class<?> clazz = Class.forName("TestObject");
//获得所有的具有public访问权限的构造方法
Constructor<?>[] constructors = clazz.getConstructors();
System.out.printf("所有的具有public访问权限的构造方法:\n");
for(Constructor o:constructors){
System.out.printf("%s\n",o.toString());
}

//获得指定的具有public访问权限的构造方法
Constructor<?> constructor = clazz.getConstructor(String.class);
System.out.printf("获得指定的具有public访问权限的构造方法:\n");
System.out.printf("%s\n",constructor.toString());


//获得所有的构造方法,包括public, private,protected和默认权限的
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
System.out.printf("获得所有的构造方法,包括public, private,protected和默认权限的:\n");
for(Object o:declaredConstructors){
System.out.printf("%s\n",o.toString());
}

//获得指定的构造方法,不管它的访问权限是什么
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(int.class);
System.out.printf("获得指定的构造方法,不管它的访问权限是什么:\n");
System.out.printf("%s\n",declaredConstructor.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}

使用获得的构造方法(包括私有的,非私有的)实例化对象。

注意事项: 如果该方法,或者该变量不是 public 访问权限的,我们应该调用相应的 setAccessible(true) 方法,才能访问得到。

//使用获得的构造函数,构造对象
public void useConstructor(){
try {
Class<?> clazz = Class.forName("TestObject");
Constructor constructor = clazz.getConstructor(String.class);
Object o = constructor.newInstance("Hello");
TestObject testObject = (TestObject) o;
testObject.byebye();


Constructor privateConstructor = clazz.getDeclaredConstructor(int.class);
//privateConstructor的访问权限不是public所以一定要执行下面这条语句
privateConstructor.setAccessible(true);
Object o1 = privateConstructor.newInstance(88);
TestObject testObject1 = (TestObject)o1;
testObject1.byebye();

}catch (Exception e){
e.printStackTrace();
}

}

使用反射获得所有的 Filed 变量

方法

描述

public Field[] getFields()

获得所有的具有public访问权限的字段

public Field getField(String name)

获得指定的具有public访问权限的字段

public Field[] getDeclaredFields()

获得所有字段,包括public, private,protected和默认权限的字段

public Field getDeclaredField(String name)

获得指定的字段,字段的访问权限包括public, private,protected和默认权限的

示例代码:

//获取所有字段
public void getMyField(){

try {
Class<?> clazz = Class.forName("TestObject");

//获得所有的具有public访问权限的字段
Field[] fields = clazz.getFields();
System.out.printf("获得所有的具有public访问权限的字段:\n");
for(Field o:fields){
System.out.printf("%s\n",o.toString());
}

//获得指定的具有public访问权限的字段
System.out.printf("获得指定的具有public访问权限的字段:\n");
Field field = clazz.getField("hobby");
System.out.printf("%s\n",field.toString());

//获得所有字段,包括public, private,protected和默认权限的字段
Field[] declaredfields = clazz.getDeclaredFields();
System.out.printf("获得所有的字段,包括public, private,protected和默认权限的字段:\n");
for(Field o:declaredfields){
System.out.printf("%s\n",o.toString());
}

//获得指定的字段,字段的访问权限包括public, private,protected和默认权限的
System.out.printf("获得指定的字段,字段的访问权限包括public, private,protected和默认权限的:\n");
Field declaredField = clazz.getDeclaredField("myName");
System.out.printf("%s\n",declaredField.toString());

} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}


}

使用获得的字段

注意:如果该方法,或者该变量不是 public 访问权限的,我们应该调用相应的 setAccessible(true) 方法,才能访问得到

//使用获得的字段
public void useMyfield(){
try {
Class<?> clazz = Class.forName("TestObject");

Field field = clazz.getField("hobby");//有public权限的
TestObject object = new TestObject();
System.out.printf("%s\n",(String)field.get(object));
field.set(object,"PingPong");
System.out.printf("%s\n",(String)field.get(object));


Field privateField = clazz.getDeclaredField("myName");
privateField.setAccessible(true);//对于访问权限不是public的字段,要想访问,必须调用setAccessible。
System.out.printf("%s\n",(String)privateField.get(object));
privateField.set(object,"Wong");
System.out.printf("%s\n",(String)privateField.get(object));



}catch (Exception e){
e.printStackTrace();
}
}

使用反射获取所有的 Method

方法

描述

public Method[] getMethods()

获得所有的具有public访问权限的方法

public Method getMethod(String name, Class<?>… parameterTypes)

获得指定的具有public访问权限的方法

public Method[] getDeclaredMethods()

获得所有方法,包括public, private,protected和默认权限的方法

public Method getDeclaredMethod(String name, Class<?>… parameterTypes)

获得指定的方法,方法的访问权限包括public, private,protected和默认权限的

示例代码:

//获取所有方法
public void getAllMethod(){
try {
Class<?> clazz = Class.forName("TestObject");
//获得所有的具有public访问权限的方法
Method[] methods = clazz.getMethods();
System.out.printf("获得所有的具有public访问权限的方法:\n ");
for(Object o:methods){
System.out.printf("%s\n",o.toString());
}

//获得指定的具有public访问权限的方法
Method method = clazz.getMethod("setMyArg", int.class);
System.out.printf("获得指定的具有public访问权限的方法:\n ");
System.out.printf("%s\n",method.toString());

//获得所有方法,包括public, private,protected和默认权限的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
System.out.printf("获得所有方法,包括public, private,protected和默认权限的方法:\n");
for(Object o:declaredMethods){
System.out.printf("%s\n",o.toString());
}

//获得指定的方法,方法的访问权限包括public, private,protected和默认权限的

Method declaredMethod = clazz.getDeclaredMethod("say", String.class);
System.out.printf("获得指定的方法,方法的访问权限包括public, private,protected和默认权限的:\n");
System.out.printf("%s\n",declaredMethod.toString());




} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

}

使用已获得的方法

注意事项: 如果该方法,或者该变量不是 public 访问权限的,我们应该调用相应的 setAccessible(true) 方法,才能访问得到。如果不用就会报如下错:

java.lang.IllegalAccessException: Class Main can not access a member of class TestObject with modifiers "private"

//使用已获得的方法
public void useMethod(){

try {
Class<?> clazz = Class.forName("TestObject");

Method method = clazz.getMethod("handleData", String.class, HashMap.class);//有public权限的
TestObject testObject = new TestObject();
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("name", "Kingkong");
method.invoke(testObject, "Tom", hashMap);

Method privateMethod = clazz.getDeclaredMethod("con");
privateMethod.setAccessible(true);//对于访问权限不是public的方法,要想访问,必须调用setAccessible。
privateMethod.invoke(testObject);
}catch (Exception e){
e.printStackTrace();
}


}

使用反射操作数组

//利用反射技术处理数组
public void handlArray() {
String[] nameArr = new String[]{"Tom", "John", "Lucy", "Barkerly"};
Array.set(nameArr, 0, "Wongkyunban"); //修改数组的值
Class clazz = nameArr.getClass();
if (clazz.isArray()) {
int len = Array.getLength(nameArr);
for (int i = 0; i < len; i++) {
Object object = Array.get(nameArr, i);
String className = object.getClass().getName();
System.out.println("--> object=" + object + ",className=" + className);
}
}


}

使用反射获得泛型类型

//使用反射获得泛型类型
public void getGenericType(){
try {
//Class<?> clazz = TestObject.class;与下面等价
Class<?> clazz = Class.forName("TestObject");
Method genericTypeMethod = clazz.getDeclaredMethod("handleData", String.class,HashMap.class);
//获得所有的参数类型
Type[] genericParameterTypes = genericTypeMethod.getGenericParameterTypes();
//检验是否为空
if (null == genericParameterTypes || genericParameterTypes.length < 1) {
return;
}

//取方法第2个参数,获得泛型参数的类型
ParameterizedType parameterizedType = (ParameterizedType)genericParameterTypes[1];
Type rawType = parameterizedType.getRawType();
System.out.printf("--->raw type:%s\n",rawType);

//取得第二个泛型参数类型
Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
if(actualTypeArgs == genericParameterTypes || actualTypeArgs.length < 1){
return;
}
//打印出每一个类型
for (int i = 0; i < actualTypeArgs.length; i++){
Type type = actualTypeArgs[i];
System.out.printf("--->Type:%s\n",type);
}

}catch (Exception e){
e.printStackTrace();
}

}

获得 Metho,Field,Constructor 的访问权限 ( public,private,ptotected 等)

//获得Metho,Field,Constructor 的访问权限
public void showPermmit(){
try {
Class<?> clazz = Class.forName("TestObject");

Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor:constructors){
int modifier = constructor.getModifiers();

System.out.printf("构造器%s,权限是%s\n",constructor.toString(), Modifier.toString(modifier));
}
System.out.printf("\n\n");

Field[] fields = clazz.getDeclaredFields();
for (Field field:fields){
int modifier = field.getModifiers();

System.out.printf("字段%s,权限是%s\n",field.toString(), Modifier.toString(modifier));
}
System.out.printf("\n\n");

Method[] methods = clazz.getDeclaredMethods();

for (Method method:methods){
int modifier = method.getModifiers();

System.out.printf("方法%s,权限是%s\n",method.toString(), Modifier.toString(modifier));
}
}catch (Exception e){
e.printStackTrace();
}

}

​​演示demo​​


举报

相关推荐

0 条评论