反射
java反射是指在程序运行时获取已知名称的类或已有对象相关信息的一种机制,包括类的方法,属性,父类等信息,还包括实列的创建和实列类型的判断等
在jdk当中,主要由以下类来实现java反射机制,这些类都位于java.lang.reflect
1,Class类:代表着一个类
2,Constructor类:代表着类的构造方法
3,Field类:代表着类的成员变量(成员变量也成为类的属性)
4,Method类:代表着类的方法
下面将通过代码展示 统一形式解析类的构造方法,成员变量和成员方法。
import java.lang.reflect.*;
public class A{
int m;
public A(){}
public void fun1(){}
public int fun2(){return m;}
public static void main(String[] args) throws Exception{
/**
*测试,看看是不是用mybatis连接到了数据库
*/
bookDao bookDao=new bookDao();
System.out.println(bookDao.getBookById(1));
Class classinfo = Class.forName("A");
/**
* 以下均是获取的结果时数组,A是自定义类,首先通过静态方法Class.forName(“类名”)返回包含A类信息结果的Class对象
* 然后通过Class类中的getConstructors(),返回A的构造方法信息
* getDeclaredFields()获取相应类的成员变量信息,getDEclaredMethods()来获取类A的成员方法信息
*/
}
注意,刚刚上面的过程仅解析lA的结构,并没有产生类A的实例。以下将展示如何用反射机制产生A的实列呢?分别有两种方法
2.1统一形式构造函数调用方法示列
import java.lang.reflect.*;
public class test {
public test(){
System.out.println("test");
}
public test(Integer m){
System.out.println("this is m"+m);
}
public test(String S,Integer m){
System.out.println("this is S m"+S+m);
}
public static void main(String []args)throws Exception{
Class classinfo = Class.forName("test");
Constructor cons[] = classinfo.getConstructors();
for (Constructor i:cons){
System.out.println(i.toString());
}
cons[2].newInstance();
cons[1].newInstance(new Object[]{10});
cons[0].newInstance(new Object[]{"Hello",2019});
Constructor c = classinfo.getConstructor();
c.newInstance();
c = classinfo.getConstructor(new Class[]{Integer.class});
c.newInstance(new Object[]{10});
c = classinfo.getConstructor(new Class[]{String.class,Integer.class});
c.newInstance(new Object[]{"Hello",2019});
}
}
结果如下:
public test(java.lang.String,java.lang.Integer)
public test(java.lang.Integer)
public test()
test
this is m10
this is S mHello2019
test
this is m10
this is S mHello2019
1 通过Class类无参getConstructors()方法,获取Constructor对象数组,其长度等于反射类当中实际构造函数个数,然后对这三个对象分别调用newIntance()
2 通过Class类的有参getConstrutor()方法,来获取对应的一个构造方法信息,然后调用newInstance()方法,完成创建过程。
统一形式调用成员方法示列
import java.lang.reflect.*;
public class test {
public test(){
System.out.println("test");
}
public test(Integer m){
System.out.println("this is m"+m);
}
public test(String S,Integer m){
System.out.println("this is S m"+S+m);
}
public void fun(){System.out.println("fun");}
public void fun1(Integer m){System.out.println("this isfun "+m);}
public void fun2(String S,Integer m){System.out.println("this is S+m"+S+m);}
public static void main(String []args)throws Exception{
Class classinfo = Class.forName("test");
Object obj = classinfo.getConstructor().newInstance();
Method mt1 = classinfo.getMethod("fun");
mt1.invoke(obj);
Method mt2 = classinfo.getMethod("fun1",Integer.class);
mt2.invoke(obj,new Object[]{10});
Method mt3 = classinfo.getMethod("fun2",String.class,Integer.class);
mt3.invoke(obj,new Object[]{"invole",2019});
}
}
结果
fun
this isfun 10
this is S+minvole2019
方法反射主要利用的是Class类的getMethod方法,得到Method对象,然后利用Method类中的invoke方法完成反射方法的执行。
总结:只要知道类名字符串,方法名字符串,方法参数值,运用反射机制就能执行改方法。突出特点:可以把类名,方法名作为字符串变量,直接对这两个字符串进行规范操作,就能产生类的实列及相应的运行方法。运用反射机制,可以大大的提高框架的稳定程度。
反射固然强大,但是他是以牺牲实际为代价的。一般常用:接口+构造方法反射
动态实现与本地实现相比,其运行速度要快上20倍,这是因为动态实现无需从java到c++再到java的转换,而生成字节码的时间耗时,少次使用的化,反而是本地方法要快。许多反射只会调用一次,所以jvm设置了一个阈值(15),当该反射调用次数在15次以下时,采用本地实现。当达到15时,便开始动态的生成字节码,并将委派实现的委派对象切换至动态实现。这个过程我们称为inflation
小练习
利用反射技术解析像量类java.util.Vecor有那些属性和方法。
import java.lang.reflect.*;
public class test {
public static void main(String []args)throws Exception{
Class classinfo = Class.forName("java.util.Vector");
// 表示其构造函数
Constructor cons[] = classinfo.getConstructors();
System.out.println("Constructor");
for (Constructor i:cons){
System.out.println(i.toString());
}
Field fil[] = classinfo.getDeclaredFields();
System.out.println("Field:");
for(Field i:fil){
System.out.println(i.toString());
}
Method met[] = classinfo.getDeclaredMethods();
System.out.println("Method");
for(Method i:met){
System.out.println(i.toString());
}
}
结果:
练习结果
网友评论