其实 Class 并不在 java.lang.reflect 中,它的全限定名为: java.lang.Class 。
Class 是什么?
它和我们平时写的代码中的类一样,对它么的它就是一个类。它有属性有方法,别想得它有什么特别的地方,我就告诉你它不特别,它就是一个类。
这个类是干什么用的呢?它是用来表示其他类的信息的类。是不是有点绕,我来说慢点:Class 这个类的实例,就是表示其他类(包括它自己)信息的。类信息的意思就是,这个类有什么属性,属性的权限是什么,属性的类型是什么,有什么方法,方法的权限是什么,入参是什么,返回值是什么。烦是你在*.java这个文件中看得到的信息就叫类的信息。反向来讲就是,从Class 的实例中可以知道*.java长什么样子。
如何得到类的Class 对象实例?
首先,它的构造方法只有一个,而且还是私有的。
private
Class(ClassLoader
paramClassLoader
)
{
this
.
classLoader
=
paramClassLoader
;
}
所以它是没法new 出来的。据我所有,它可以有两种方式得到。
1.
Class<?>
clzz
= Class.
forName
(
"java.lang.Class"
);
这是在知道类的全限定名(包.名)的情况获得的。
2.
TestClass
tt
=
new
TestClass();
Class<?>
ttclzz
=
tt
.getClass();
这是在得到类的实例的情况,也可以获得。其实得到Class 对象后也可以得到该对象代表的类的实例。
TestClass
instance
= (TestClass)
clzz
.newInstance();
Class --> 实例;实例-->Class 。
所谓的反射,就像是:
Class --> 实例,这种情况,但这不是反射的定义 。
3.Class<?> clzz = TestClass.class;
这种是最容易但也是最容易被人忘却的方式。
上面这三种方式得到Class 实例都要做同一件事,也是想要获取其他所有实例都要做的一件事。它是什么呢?
得到Class 实例所要做的事
其实这件事在说JVM 的时候已经有说过了,那就是从 类的 二进制字节码中 将 类信息 加载、验证等一系列操作放到JVM内存中来。
得到Class 实例后我们可以做什么?
前面说过了,
Class 实例 就是某类 代号A 的信息。这些信息 我们当然可以一个个列出来啊,所以Class类中有相应的方法帮我们做这些事。
ClassLoader
cd
=
clzz
.getClassLoader();
得到加载这个类 A 的 类加载器
Field[]
fd
=
clzz
.getFields();
得到这个
类 A的所有公共的属性
Field
[]
fd
=
clzz
.getDeclaredFields();
得到这个类 A的所有属性
Method[]
fm
=
clzz
.getMethods();
得到这个类 A的所有公共的方法
等等。烦是你能从 *.java 中得到的信息这个 Class 对象都能得到。
Class 这个类什么用?
我们学Java 之初就有人告诉我们 Java 类 就是对某种事物的抽象,万物皆对象。这句话是非常正解的,只是大家可能都是知道这句话的意思,但并不知道如何运用这个道理(知道的道理很多,却依然看不清事情的本质)。这个 Class 类抽象的 就是这世界所有的 Java 类(包括它自己)。
它有什么秒用呢,我还是习惯形象地举个例子。
一般我们获取对象的方式:
ClassA a = new ClassA();
ClassB b = new ClassB();
ClassC c = new ClassC();
ClassD d = new ClassD();
...(后续还有几百行)
依次类推,发挥你的想象这里new 了几百个对象。
有了Class 之后 :
for (String classFullName : classFullNameList) {
Class<?> clzz = Class.forName(
classFullName );
}
后续再无代码。
这就是反射机制。它可以动态地生成实例对象,还不需要使用它的构造函数来生成 。仔细分析的话,道理是非常简单的。区别就是前一种方式它把 类 的名写死在代码了;而后一种则是通过传参的方式,从其他地方得到 类 的名字。其实这是所谓的解耦思想,增加更多的灵活性。这种获取实例的方式是很多框架用到的,因为框架并不知道你会写什么类。