正文
Java提升篇之反射的原理
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
Java提升篇之反射的原理
1、构造方法的反射
import java.lang.reflect.Constructor;
public class ReflectConstructor {
public static void main(String[] args) throws Exception {
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
Object str = constructor.newInstance(new StringBuffer("你好"));//实例化一个对象
System.out.println(str);
}
}
2、成员变量的反射
import java.lang.reflect.*;
public class ReflectField {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("反射.ReflectPoint");
Constructor constructor = clazz.getConstructor(int.class,int.class);
Object obj = constructor.newInstance(3,5);//用字节码对象实例化一个Object对象,然后通过该对象来操作成员变量
Field fieldy=obj.getClass().getField("y");//fieldy不是对象(pt)身上的变量,而是类(Field)上的,要用它去取某个对象上对应的值
System.out.println(fieldy.get(obj));
Field fieldx=obj.getClass().getDeclaredField("x");//对于一个类里面的私有字段,要用getDeclaredField()方法获取
fieldx.setAccessible(true);//要取得一个私有字段上的值,必须设置为true
fieldx.set(obj,2);//修改某个对象上对应私有字段的值
System.out.println(fieldx.get(obj));
System.out.println(obj.toString());
}
}
class ReflectPoint {
private int x;
public int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
public ReflectPoint() {
super();
}
@Override
public String toString() {
return "ReflectPoint [x=" + x + ", y=" + y + "]";
}
}
}
【注:在应用反射时,最好都用getDeclared****()方法获取相应的Constructor、Field、Method,因为你不知道它们对应的权限是什么,通过这个方法可以越过权限检查,全部获取到,在获取成员变量时也都设置这个fieldx.setAccessible(true),设置为true,即可以访问,越过权限检查】
3、成员方法的反射
import java.lang.reflect.Method;
public class ReflectMethod {
public static void main(String[] args) throws Exception {
//Method[] method = String.class.getMethods();//获取自己包括父亲的公共方法
//Method[] method2 = String.class.getDeclaredMethods();//获取自己的所有方法
Method method = String.class.getMethod("charAt", int.class); //getMethod(String,Class<...>)第一个参数为方法名,第二个为该方法的参数类型字节码
char str = (char) method.invoke( new String("abcd"), 2); //invoke()意为调用
/*
* invoke(Object,args)第一个参数表示对象是谁(如果被调用的method不是静态方法则传入一个调用chaAt()方法的对象,
* 如果被调用的是静态方法,比如main()方法等,则invoke(null,args)第一个参数传入null),
* 第二个表示调用该方法所传入的实际参数(注意:当第二个参数为String[]类型时,必须用Object[]对象把String[]对象包在里面,即new Object{new String[]{"a","b",....}},因为如果传入String[]类型对象java会把这个对象自动拆包,这就导致传入了多个参数,即报参数数目不匹配异常。如果传入的是int[]对象的话,这个可以用new int[]{}来传入,见下面例子)
* */
System.out.println(str);
Test test = new Test();
Method method2 = test.getClass().getMethod("main", String[].class);
method2.invoke(null,new Object[]{new String[]{"1","2","3"}});//调用的是静态方法,则invoke(null,args)第一个参数传入null
}
}
class Test{
public static void sum(int[] a){
for(int arg : a){
System.out.println(arg);
}
}
public static void main(String[] args) {
for(String arg : args){
System.out.println(arg);
}
}
}
4、数组的反射
import java.lang.reflect.Array;
public class ReflectArray {
public static void main(String[] args) {
printObject(new String[]{"aaa","bbb"});
printObject(111);
}
private static void printObject(Object obj) {
Class cla = obj.getClass();
if(cla.isArray()){//判断传入过来的对象是否为数组,是数组对象则遍历输出值
int len = Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj, i));
}
}else{//如果不是数组对象,则直接输出值
System.out.println(obj);
}
}
}
————转载请注明出处
import java.lang.reflect.Constructor; public class ReflectConstructor { public static void main(String[] args) throws Exception { Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class); Object str = constructor.newInstance(new StringBuffer("你好"));//实例化一个对象 System.out.println(str); } }
2、成员变量的反射
import java.lang.reflect.*; public class ReflectField { public static void main(String[] args) throws Exception { Class clazz = Class.forName("反射.ReflectPoint"); Constructor constructor = clazz.getConstructor(int.class,int.class); Object obj = constructor.newInstance(3,5);//用字节码对象实例化一个Object对象,然后通过该对象来操作成员变量 Field fieldy=obj.getClass().getField("y");//fieldy不是对象(pt)身上的变量,而是类(Field)上的,要用它去取某个对象上对应的值 System.out.println(fieldy.get(obj)); Field fieldx=obj.getClass().getDeclaredField("x");//对于一个类里面的私有字段,要用getDeclaredField()方法获取 fieldx.setAccessible(true);//要取得一个私有字段上的值,必须设置为true fieldx.set(obj,2);//修改某个对象上对应私有字段的值 System.out.println(fieldx.get(obj)); System.out.println(obj.toString()); } } class ReflectPoint { private int x; public int y; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } public ReflectPoint() { super(); } @Override public String toString() { return "ReflectPoint [x=" + x + ", y=" + y + "]"; } } }
【注:在应用反射时,最好都用getDeclared****()方法获取相应的Constructor、Field、Method,因为你不知道它们对应的权限是什么,通过这个方法可以越过权限检查,全部获取到,在获取成员变量时也都设置这个fieldx.setAccessible(true),设置为true,即可以访问,越过权限检查】
3、成员方法的反射
import java.lang.reflect.Method; public class ReflectMethod { public static void main(String[] args) throws Exception { //Method[] method = String.class.getMethods();//获取自己包括父亲的公共方法 //Method[] method2 = String.class.getDeclaredMethods();//获取自己的所有方法 Method method = String.class.getMethod("charAt", int.class); //getMethod(String,Class<...>)第一个参数为方法名,第二个为该方法的参数类型字节码 char str = (char) method.invoke( new String("abcd"), 2); //invoke()意为调用 /* * invoke(Object,args)第一个参数表示对象是谁(如果被调用的method不是静态方法则传入一个调用chaAt()方法的对象, * 如果被调用的是静态方法,比如main()方法等,则invoke(null,args)第一个参数传入null), * 第二个表示调用该方法所传入的实际参数(注意:当第二个参数为String[]类型时,必须用Object[]对象把String[]对象包在里面,即new Object{new String[]{"a","b",....}},因为如果传入String[]类型对象java会把这个对象自动拆包,这就导致传入了多个参数,即报参数数目不匹配异常。如果传入的是int[]对象的话,这个可以用new int[]{}来传入,见下面例子) * */ System.out.println(str); Test test = new Test(); Method method2 = test.getClass().getMethod("main", String[].class); method2.invoke(null,new Object[]{new String[]{"1","2","3"}});//调用的是静态方法,则invoke(null,args)第一个参数传入null } } class Test{ public static void sum(int[] a){ for(int arg : a){ System.out.println(arg); } } public static void main(String[] args) { for(String arg : args){ System.out.println(arg); } } }
4、数组的反射
import java.lang.reflect.Array; public class ReflectArray { public static void main(String[] args) { printObject(new String[]{"aaa","bbb"}); printObject(111); } private static void printObject(Object obj) { Class cla = obj.getClass(); if(cla.isArray()){//判断传入过来的对象是否为数组,是数组对象则遍历输出值 int len = Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj, i)); } }else{//如果不是数组对象,则直接输出值 System.out.println(obj); } } }
————转载请注明出处