Java中如何获得一个对象所对应的类及Class类的简单理解
前言
在之前的学习中,所用的编程语言主要是Python,最近开始学习Java,熟悉Python的同学应该会知道在Python中有一个函数type()
,通过这个函数可以非常方便地获得一个变量的类型。那么在Java中可不可以实现类似的功能呢?答案当然是可以的,一个比较简单的方法就是利用Java中Class类来实现。
利用Class类的方法获得一个对象所属于的类
在这里先给出一个例子:
List<Integer> listTest = new ArrayList<>();
System.out.println(listTest.getClass().getName());
运行这段代码会输出:
java.util.ArrayList
在这一段代码中,新建了一个ArrayList
类型的实例listTest
,在其后的一行代码中,用.getclass()
方法获得了listTest
变量所属于的类,并再用.getName()
将这个类的名称输出出来。
同时,也可以用.toString()
将完整的信息打印出来:
System.out.println(listTest.getClass().toString());
结果为
class java.util.ArrayList
可以看到,用.getClass()
方法可以很方便地获得我们想要知道的对象变量所对应的类的名称。
而以上是用于实例的获取其类的类型的方法,与之类似的还有.class()
方法,这个方法是针对类的,如:
System.out.println(ArrayList.class.getName());
输出为:
java.util.ArrayList
关于Class类的一些理解
在上面的例子中,我们看到Class
类有一些非常方便的应用,所以可以来简单地了解以下Class
类的内容。
java是一门比较纯粹的面向对象的语言,在这样一门语言里,一切皆为对象。当然还是有着一些例外,比如从开发者的角度看静态成员和普通数据类型就不属于对象,静态成员只属于某个类,而不属于对象,而普通数据类型是因为处于对性能的考虑,因为处理对象需要额外的系统开销,所以颗将基本数据类型当作对象,就会给语言性能带来负面影响,因此,在Java中基本数据类型是不作为对象来使用的,不过,在需要的时候可以通过方便的装箱(boxing)与开箱(unboxing)来实现基本数据类型与对象之间的转换。
当然,既然上面说了是从开发者的角度看,肯定对应着其它的角度,比如若在JVM的视角,会将所有的原始类型都当作对象处理,但是会为原始类型创建非常轻量级的对象,相比于其装箱的包装类的功能要少得多,但是会有很多优化。而对于静态成员,就可以通过Class类来进行理解。
那么,既然Java中,一切皆为对象,那么在程序里的类本身是不是对象呢?答案为是的,在Java中有这样专门的一个类java.lang.Class
,在程序中所写的每一个类都既有着自己的对象,同时它自己本身也是Class
类的对象。
在Java中,程序运行的期间,Java的运行时系统会始终为所有的对象维护一个被称为运行时的类型标识,这个信息跟踪着每个对象所属的类,虚拟机则利用女性是类型信息来选择相应的方法执行,而保存这些信息的类就是Class
类。而在之前我们的例子中的的.getClass()
方法返回的就是这样一个Class
类型的实例,获得Class类的方法主要有以下三种:
-
Object
类中的getClass()
方法 -
Class
类中的forName()
方法,例:Class cl = Class.forName(className);
输入参数为雷鸣,获得类名对应的Class对象。 -
如果T是任意的Java类型,则
T.class
返回匹配的类对象。
其中的1、3条即为本文开始时的两个例子。
在这里,需要注意的一点时,一个Class对象实际上上表示的是一个类型,而这个类型未必一定是一种类,如int不是类,但int.class是一个Class类型的对象。
Class类还有其它一些比较有用的地方,比如,虚拟机为每个类型管理一个Class对象,因此,可以利用==
运算符实现两个类对象比较的操作,如:
if (e.getClass() == Employee.class)...
还有一个很有用的方法newInstance()
,可以用来动态地创建一个类的实例。例如:
e.getClass().newInstance();
这个语句创建了一个与e
具有相同类的类型的实例。newInstance方法调用默认的构造器(没有参数的构造器)初始化新创建的对象。如果这个类没有默认的构造器,就会抛出一个异常。
将forName
与newInstance
配合使用,可以根据存储在字符串中的类名创建一个对象。
String s = "java.util.Random";
Object m = Class.forName(s).newInstance;
同时,还需要知道,Class
类的构造函数为私有函数,即我们无法像定义普通类的实例那样,用new
的方法来构造Class
的实例,若要获得Class
的实例可以通过上面介绍的三种方法。