一、Java反射的使用场景
暂时只用过通过配置文件的className来创建对象。
“很多人都觉得,既然都知道类名,为什么不直接new出来,然后调用方法,搞反射太麻烦了,而且一点用都没有?”对于这个问题,我觉得有需要看框架的应该得懂,因为框架有用到,虽然我还没有学习,但在网上看到过这方面问答,所以就冒昧写出来了
二、基础知识
2.1 通过反射得到className的方式
class.forName()
类.class()方法
实例化的类.getClass()方法
2.2 通过ClassName实例化对象的方式
通过class的newInstance的方法
通过Constructor来创建
他们的区别在于,前者只能实例化无参的实例化对象,后者兼容各种参数的实例化对象,当然还包括无参的
2.3 常用类
Method跟类的方法挂钩
Field跟类的字段挂钩
Constructor跟类的构造方法挂钩
2.4 常用方法
Method.getMethod()获取public的类方法,局限性很大
Method.getDeclaredMethod()使用方法跟上面一样,但除了public方法,还可以获取private方法
如果你尝试使用getMethod()方法来获取private方法,那么将会提示你NoSuchMethodException()
其余的Field方法同上
三、具体实例
实现功能:访问类的私有方法,并将值打印出来
提供私有方法的类
public class BeiTest1 {
public int myself=12;
private int getchina(){
return myself;
}
}
操作类
public class ReflectTest1 {
public static void main(String[] args) throws Exception{
BeiTest1 test=new BeiTest1();
//在这里可以使用newInstance或者Constractor来创建实例
Class<?> classType=test.getClass();
//使用getMethod将不能访问private方法,如果访问了将会抛出java.lang.NoSuchMethodException异常,后续也就得不到运行
Method method=classType.getDeclareMethod("getchina",new Class[]{});
//设置是否启用访问检测,如果为true则表示不检测,也就表示可以访问
method.setAccessible(true);
Integer aaa=(Integer)method.invoke(test, new Object[]{});
System.out.println("结果是"+aaa);
}
}
实现功能:将某个对象中的字段提取出来,保存到另外一个新建对象中,然后打印出来
class BeiTestCopy{
int age;
String name;
public BeiTestCopy(int a,String n) {
this.age=a;
name=n;
}
}
public class ReflectCopyTest {
public static void main(String[] args) throws Exception{
//模拟初始化对象
BeiTestCopy testcopy=new BeiTestCopy(35,"张三");
//调用函数,将通用的Object强转
BeiTestCopy mycopy=(BeiTestCopy) copyObject(testcopy);
//打印copy回来的数据
System.out.println(mycopy.name+"今年"+mycopy.age);
}
public static Object copyObject(Object o) throws Exception{
//获取对象中的各个字段的值
Class<?> classType=o.getClass();
//注,千万要使用declaredFields而非getfields方法,否则无返回
Field[] fields=classType.getDeclaredFields();
//用来存读取到的内容
Object[] obj=new Object[2];
int i=0;
for(Field field:fields){
//获取到对应字段的名称
//System.out.println(field.getName());
//field.get接的参数是要提取数据的实例,而非字段名称
//System.out.println("找到的值"+field.get(o));
obj[i]=field.get(o);
i++;
}
//创建对象
Class<?> classType2=o.getClass();
Constructor<?> constructor=classType2.getConstructor(new Class[]{int.class,String.class});
//直接使用先前存放的obj数组即可,以形成通用模式
//Object newobj=constructor.newInstance(new Object[]{});
Object newobj=constructor.newInstance(obj);
//将新创建的对象返回出去
return newobj;
}
}