Java基础与提高干货系列——Java反射机制

 前言

今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来。那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现。

正文

Java反射机制定义

Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
用一句话总结就是反射可以实现在运行时可以知道任意一个类的属性和方法。

反射机制的优点与缺点

为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念

  • 静态编译:在编译时确定类型,绑定对象,即通过。

  • 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。

  • 优点
    可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。

  • 缺点
    对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

理解Class类和类类型

想要了解反射首先理解一下Class类,它是反射实现的基础。
类是java.lang.Class类的实例对象,而Class是所有类的类(There is a class named Class)
对于普通的对象,我们一般都会这样创建和表示:

Code code1 = new Code();

上面说了,所有的类都是Class的对象,那么如何表示呢,可不可以通过如下方式呢:

Class c = new Class();

但是我们查看Class的源码时,是这样写的:

privateClass(ClassLoader loader){     classLoader = loader; }

可以看到构造器是私有的,只有JVM可以创建Class的对象,因此不可以像普通类一样new一个Class对象,虽然我们不能new一个Class对象,但是却可以通过已有的类得到一个Class对象,共有三种方式,如下:

Class c1 = Code.class;这说明任何一个类都有一个隐含的静态成员变量class,这种方式是通过获取类的静态成员变量class得到的Classc2= code1.getClass();code1是Code的一个对象,这种方式是通过一个类的对象的getClass()方法获得的Class c3 = Class.forName("com.trigl.reflect.Code");这种方法是Class类调用forName方法,通过一个类的全量限定名获得

这里,c1、c2、c3都是Class的对象,他们是完全一样的,而且有个学名,叫做Code的类类型(class type)。
这里就让人奇怪了,前面不是说Code是Class的对象吗,而c1、c2、c3也是Class的对象,那么Code和c1、c2、c3不就一样了吗?为什么还叫Code什么类类型?这里不要纠结于它们是否相同,只要理解类类型是干什么的就好了,顾名思义,类类型就是类的类型,也就是描述一个类是什么,都有哪些东西,所以我们可以通过类类型知道一个类的属性和方法,并且可以调用一个类的属性和方法,这就是反射的基础。

举个简单例子代码:

publicclassReflectDemo{    publicstaticvoidmain(String[] args)throws ClassNotFoundException {        //第一种:Class c1 = Code.class;        Class class1=ReflectDemo.class;        System.out.println(class1.getName());        //第二种:Class c2 = code1.getClass();        ReflectDemo demo2= new ReflectDemo();        Class c2 = demo2.getClass();        System.out.println(c2.getName());        //第三种:Class c3 = Class.forName("com.trigl.reflect.Code");        Class class3 = Class.forName("com.tengj.reflect.ReflectDemo");        System.out.println(class3.getName());    }}

执行结果:

com.tengj.reflect.ReflectDemocom.tengj.reflect.ReflectDemocom.tengj.reflect.ReflectDemo

Java反射相关操作

前面我们知道了怎么获取Class,那么我们可以通过这个Class干什么呢?
总结如下:

  • 获取成员方法Method

  • 获取成员变量Field

  • 获取构造函数Constructor

下面来具体介绍

获取成员方法信息

单独获取某一个方法是通过Class类的以下方法获得的:

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)// 得到该类所有的方法,不包括父类的public Method getMethod(String name, Class<?>... parameterTypes)// 得到该类所有的public方法,包括父类的

两个参数分别是方法名和方法参数类的类类型列表。
例如类A有如下一个方法:

publicvoidfun(String name,int age){        System.out.println("我叫"+name+",今年"+age+"岁");    }

现在知道A有一个对象a,那么就可以通过:

Class c = Class.forName("com.tengj.reflect.Person");  //先生成classObject o = c.newInstance();                           //newInstance可以初始化一个实例Method method = c.getMethod("fun", String.class, int.class);//获取方法method.invoke(o, "tengj"

                    
                
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信