疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java之旅—Class类详解


 

   

  看到Class的时候,我们是不是会一下子想到我们写程序中的class呢?此Class非彼class,这里讲的Class类实际上就是Java类的统称,我们可以将其称之为抽象的类不是具体的一个类的名字。

  1. 概念

  Java程序中的各个java类属于同一个事物,描述这类事物的java类名就是Class。也许这个解释还是不够清晰,再细点说:

  Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值,java程序中的各个java类,他们是否属于同一类事物,是不是可以用一个类来描述这个类事物呢?那么这个类的名字就是Class。

  值得注意:不同于小写的class.Class类描述了类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等等,这是反射的基础。

  2. 本质解析

  举个简单的例子来解释:人的名字是person,那么java类的名字就是Class。

  我们如果将人进行实例化,那么其实例化对象则是张三或者李四等等,Class类代表一个个的java类,那么它的各个实例对象又是什么呢?

  Class类的实例对象对应的是各个类在内存中的字节码,例如,person类的字节码,Date类的字节码等等。一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不用的类的字节码是不同的,所有它们在内存中的内容是不同的。那么具体什么是字节码吗?

  3. 字节码

  Ø 定义

  当我们在源程序中用到了person类的时候,首先需要在硬盘上将这个类的二进制代码编译成Class放在硬盘上,就是一群二进制代码,需要将这群二进制代码加载到内存中来,才可以使用它创建一个个的对象,首先要将类的字节码加载到内存中来,再用这个字节码去读取一个个的对象来,当程序中用到了好多个类的时候,那么内存中就应该存在几个字节码,每一份字节码就是一个Class的实例对象。

  我们知道对于之前我们见过的类比如person,当我们用其对象时,可以使用:

  Person p1=newPerson();但是Class是不能直接用new Class直接获取到的,比如

  Class cs1=字节码;cs1代表内存中的一个字节码,比如说我们将其对应相应的对象,则是

  Classcs1=Date.class;//字节码1

  Classcs2=Person.class;//字节码2

  Ø 如何得到字节码

  通常情况下我们可以采用三种方式获取到字节码:

  第一种类名.class 比如:System.class

  举个例子:Classcls1=Date.class;//字节码;这里采用的Date就是一个类,我们经常使用的String等等并不是原始的基本数据类型,而是类,通常情况下存在八种基本数据类型,分别是boolean、byte、char、short、int、long、float anddouble。

  第二种对象.getClass() 比如:new Date().getClass()

  以上面的例子为例,比如 Person p1=new Person();那么P1就是一个实例化的对象也是P1字节码得到的具体的对象,这样我们就去拿到它的字节码,也就是p1.getClass();

  第三种Class.forName(“类名”) 比如:Class. forName(“java.util.Date”);

  此外Class这个类还存在一个静态的方法那就是forName();括号中的类名必须指定的是完整的类名,比如Class. forName(“java.util.String”);这也是相当于将抽象类找到具体的类,也就是String类的字节码;如果这个类本身已经加载到内存中来了,那么就不需要再次进行加载了.

  forName的作用是返回字节码,返回方式存在两种:

  1、 这份字节码曾经被加载过,已经呆在加载器里面了,那么直接返回即可。

  2、 Java虚拟机中还没有这个字节码,则用内加载器去加载,把加载进来的字节码缓存在虚拟机中,以后要得到这份字节码就不用再加载了。

  三种方式最优的是Class.forName();

  第三种的好处是动态编译的而不是静态的,前两者都是在编译的时候已经确定了类型,但是第三种可以在运行的时候进行配置,因为是字符串,那么我们可以定义一个变量进行存储,也就是说在配置文件中运行的时候动态给其赋值。

  值得注意:以上三种方式均是可以得到字节码,并且三种获取字节码的方式在内存中实际上是同一份字节码。

  [java]

  String str1 = "abc";

  Class cls1 = str1.getClass();

  Class cls2 = String.class;

  Class cls3 = Class.forName("java.lang.String");

  System.out.println(cls1 == cls2);

  System.out.println(cls1 == cls3);

  打印的结果均为true,说明三种获取字节码的方式在内存中实际上是同一份字节码。

  Ps:判断一种类型是不是基本数据类型,通常情况下我们可以这样的代码进行判断;int.class.isPrimitive();此外我们还可以使用:int.class==Integer.TYPE来查看是否是基本数据类型。

  Type属性同样适用于其他的类比如Boolean.TYPE,Character.TYPE,Byte.TYPE,Short.TYPE,Integer.TYPE,Long.TYPE,Float.TYPE,Double.TYPE,Void.TYPE。

  4. 小结

  了解Class类为我们了解反射机制奠定了基础,这是学习反射的前提。