京东自营 618 + 国补 iPhone 历史最低价          领 618 红包,最高25618元

详解 Java Class

反射是我学习Java时遇到的最大障碍,因为太抽象了。

我当时是跟着网络上的培训班视频自学的,视频里的老师说:类是对现实事物的抽象,而Class是对类的抽象。这句话对于刚开始学习Java的人来说,无异于天书。我当时的理解是:根据类,可以创建对象,所以类是比对象更高一级的抽象。如果要对类进一步抽象,它应该是什么形式呢?我无法想象。在我的认知里,Java除了类还是类,类层级的抽象似乎已经到尽头了。

如何对类进行抽象?

许多年后,再次回想那段经历,我发现自己当时陷入了一个思维陷阱,误以为“用类抽象类”是一个死循环,把自己困在里面了。

其实,换个角度这个问题就迎刃而解了。Java用类对世间万物进行抽象,包括人、动物、甚至空气、键盘、鼠标,那么用Java语言编写的类文件(xxx.java)不也是世间万物的一种吗?是不是也能用类表示?老师说的那句话没错,但更准确的说法是:

对于Java而言,类是对现实事物的抽象,其中有一个名为Class的类专门用于描述Java类(文件)

Class类也是一个类,只不过它描述的事物比较特殊:Java类

按照这个思路,我们尝试写一个Class类,用来描述Java中的“类”。好,想法有了,怎么开始呢?

所谓抽象,就是抽取相像的。什么叫相像?单个事物肯定不能说相像,因为相像是相互比对后得出的结论。所以,我们至少要先编写两个类。

抽象最忌讳一上来就关注细节,这样是很难得到一个好的抽象模型的。反之,在设计之初应该观其大略,从大处着手“找共性”。

它们都是Class,它们都有Constructor、Field、Method

啊?这也太粗粒度了吧!别急,再慢慢细化就是了:

方法可以细分为:访问修饰符、返回值类型、方法名、参数列表

如果你足够耐心,还可以继续细化,比如Parameter可以进一步细分为:修饰符、参数类型、参数名、参数索引(第几个参数)。由于Java已经替我们做好抽象,这里就不再继续重复劳动了。

Class:对类的抽象

Constructor:对构造器的抽象

Method:对方法的抽象

Field:对字段的抽象

Parameter:对参数的抽象

其他的就不列举了,总之最终我们会得到很多个大小模型,这些模型相互协作共同描绘了“Java类”这一抽象。

Class对象

什么是Class对象?简单来说,就是Class类的实例。

Java有一个Class类,那么按理说我们应该可以new一个Class对象。但Class类是个狠角色,它不仅对自己进行了阉割(final class,不允许继承),还隐藏了构造器(final constructor,不允许new)。也就是说,正常途径下没有人能创建Class对象,也不会有Class的子类。

官方说得很清楚:Only the Java Virtual Machine creates Class objects.

那虚拟机创建的Class对象长啥样呢?

在Java中,每个类在首次加载时都会有一个对应的Class对象被创建。

当你执行new User()时,JVM会检查是否已经加载了User类:

  • 如果没有加载,它会先加载User类,并创建User类的Class对象,然后根据该对象创建User类的实例。
  • 否则,直接找到User类的Class对象并创建User类的实例。

也就是说,我们一直以为new User()的步骤是 User类 => User对象,但实际上是 User类 => User类的Class对象 => User对象。

注意,这里有一个反直觉的地方:

JDK中只有一个Class类,那么根据这个Class创建出来的Class实例应该都是一样的,怎么会有Student Class对象、User Class对象呢?

我可没说JVM创建了Student Class对象。上面图中所说的Class对象(Student),指的是这个Class对象包含的信息来自Student类。

这样一来,顺便也解答了为什么JVM禁止程序员手动根据Class类创建Class对象。

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java