即使有一个类并对它一无所知,但其实它本身就包含了许多信息,Java 在需要使用到某个类时才会将类加载,并在 JVM 中以一个 java.lang.Class 的实例存在。从 Calss 实例开始,可以获得类的许多信息。

Java 在真正需要使用一个类时才会加以加载,而不是在程序启动时就加载所有的类。因为大多数的使用者都只使用到应用程序的部分资源,在需要某些功能时才加载某些资源,可以让系统的资源运用更有效率(Java 本来就是为了资源有限的小型设备而设计的,这样的考虑是必然的)。

一个 java.lang.Class 对象代表了 Java 应用程序在运行时所加载的类或接口实例,也用来表达 enum(属于类的一种)、annotation(属于接口的一种)、数组、初始类型、void。Class 类没有公开的 构造函数。Class 对象由 JVM 自动产生,每当一个类被加载时,JVM 就自动为其产生一个 Class 对象。

可以通过 Object 的 getClass() 方法来获得每一个对象对应的 Class 对象,或者是通过 class 常量(Class Literal),在获得 Class 对象之后,就可以操作 Class 对象上的一些公开方法来取得类的基本信息。下面的例子使用 getClass() 方法取得 String 类的 Class 实例,并从中得到 String 的一些基本信息。

package cn.sunzn.demo;

public class ClassDemo {

    @SuppressWarnings("rawtypes")
public static void main(String[] args) {
String name = "sunzn";
Class stringClass = name.getClass();
System.out.println("类名称:" + stringClass.getName());
System.out.println("是否为接口:" + stringClass.isInterface());
System.out.println("是否为基本类型:" + stringClass.isPrimitive());
System.out.println("是否为数组对象:" + stringClass.isArray());
System.out.println("父类名称:" + stringClass.getSuperclass().getName());
} }

运行结果如下:

类名称:java.lang.String
是否为接口:false
是否为基本类型:false
是否为数组对象:false
父类名称:java.lang.Object

也可以直接使用以下的方式来取得 String 类的 Class 对象:

Class stringClass = String.class;

Java 在真正需要类时才会加载类,所谓真正需要通常指的是要使用指定的类生成对象时(或是使用者指定要加载类时,例如使用 Class.forName() 加载类,或是使用 ClassLoader 的 loadClass() 加载类)。使用类名称来声明参考名称并不会导致类的加载,可以设计一个测试类来印证这个说法。

package cn.sunzn.demo;

public class TestClass {

    static {
System.out.println("类被载入");
} }

在范例中定义了一个静态区块,默认在类第一次被加载时会运行静态区块(说默认的原因,是因为可以设定加载类时不运行静态区块,使用 Class 生成对象时才运行静态区块)。通过在命令行模式下显示信息,可以了解类何时被加载,可以使用如下的范例来测试类加载时机。

package cn.sunzn.demo;

public class ClassDemo {

    public static void main(String[] args) {
TestClass test = null;
System.out.println("声明 TestClass 参考名称");
test = new TestClass();
System.out.println("生成 TestClass 实例对象");
} }

运行结果如下:

声明 TestClass 参考名称
类被载入
生成 TestClass 实例对象

从运行结果中可以看出,声明参考名称并不导致 TestClass 类被加载,而是在使用 new 生成对象时才会加载类。

Class 的信息是在编译时期就被加入至 .class 文件中,这是 Java 支持运行时期类型识别(Run-Time Type Information 或 Run-Time Type Identification,RTTI)的一种方式:在编译时期编译器会先检查对应的 .class 文件,而运行时期 JVM 在使用某类时,会先检查对应的 Class 对象是否已经加载,如果没有加载,则会寻找对应的 .class 文件并载入。一个类在 JVM 中只会有一个 Class 实例,每个类的实例都会记得自己是由哪个 Class 实例所生成,如下图所示。可以使用 getClass() 或 .class 来取得 Class 实例。

在 Java 中,数组也是一个对象,也有其对应的 Class 实例。这个对象由具有相同元素与维度的数组所共享,而基本类型像 boolean、byte、char、short、int、long、float、double 和关键词 void,也都有对应的 Class 对象。可以用类常量来取得这些对象。

package cn.sunzn.demo;

public class ClassDemo {

    public static void main(String[] args) {
System.out.println(boolean.class);
System.out.println(void.class); int[] iarr = new int[10];
System.out.println(iarr.getClass().toString()); double[] darr = new double[10];
System.out.println(darr.getClass().toString());
} }

运行结果如下:

boolean
void
class [I
class [D

在 Java 中数组确实是以对象的形式存在,其对应的类由 JVM 生成。当使用 toString() 来显示数组对象的描述时,[ 表示为数组类型,并加上一个类型代表字,以上的代码运行结果中 I 表示是一个 int 数组,而 D 表示是一个 double 数组。

Java 编程下简介 Class 与类加载的更多相关文章

  1. Java 编程下 Eclipse 如何设置单行代码显示的最大宽度

    Eclipse 下一行代码的默认宽度是 80 , 稍长一点的一行代码就会自动换行,代码可读性较差,我们可以自己在 Eclipse 对代码宽度进行设置. 设置路径为:[Window]→[Preferen ...

  2. Java 编程下使用 Class.forName() 加载类

    在一些应用中,无法事先知道使用者将加载什么类,而必须让使用者指定类名称以加载类,可以使用 Class 的静态 forName() 方法实现动态加载类.下面的范例让你可以指定类名称来获得类的相关信息. ...

  3. Java 编程下使用 Class.forName() 加载类【转】

    在一些应用中,无法事先知道使用者将加载什么类,而必须让使用者指定类名称以加载类,可以使用 Class 的静态 forName() 方法实现动态加载类.下面的范例让你可以指定类名称来获得类的相关信息. ...

  4. Java 编程下字符串的 16 位、32位 MD5 加密

    package cn.sunzn.md5; import java.security.MessageDigest; import java.security.NoSuchAlgorithmExcept ...

  5. Java 编程下正则表达式判断字符串是否包含中文

    package cn.sunzn.demo; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ...

  6. Java 编程下 Eclipse/myeclipse 如何设置单行代码显示的最大宽度

    http://www.cnblogs.com/sunzn/archive/2013/03/30/2990191.html 或 http://zhidao.baidu.com/link?url=67uy ...

  7. 《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端

    1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...

  8. Java编程的逻辑 (87) - 类加载机制

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  9. java 编程基础 类加载器

    什么是类加载器 类加载器负责将class文件(可能在磁盘上,也可能在网络上)加载到内存中,并为之生成对应的java.lang.Class对象.Java开发中无须过分关心类加载机制,但所有的编程人员都应 ...

随机推荐

  1. Javascript + Dom知识点总结

    Javascript + Dom知识点总结 1.用Javascript声明数组和字典的方式 // 数组声明 var arr = new Array(); arr["0"] = &q ...

  2. Easyui入门视频教程 第05集---Easyui复杂布局

    目录 ----------------------- Easyui入门视频教程 第09集---登录完善 图标自定义   Easyui入门视频教程 第08集---登录实现 ajax button的使用  ...

  3. 【mysql】一条慢查询sql的的分析

    这个是我在jobbole.com 上看到的 先给出数据表table结构 mysql> show create table tt \G *************************** 1. ...

  4. memcached全面剖析--3.memcached的删除机制和发展方向

    下面是<memcached全面剖析>的第三部分. 发表日:2008/7/16 作者:前坂徹(Toru Maesaka) 原文链接:http://gihyo.jp/dev/feature/0 ...

  5. apache安装mod_ssl.so 出现 undefined symbol: ssl_cmd_SSLPassPhraseDialog错误解决

    很久很久以前,安装Apache的时候,根本没想过将来的某一天会使用到ssl,所以也就没有安装那个模块,结果今天需要用到的时候,却无从下手了. 由于在安装Apache的时候,mod_ssl.so这个文件 ...

  6. 【MySQL】乐观锁和悲观锁

    最近学习了一下数据库的悲观锁和乐观锁,根据自己的理解和网上参考资料总结如下: 悲观锁介绍(百科): 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持 ...

  7. android 点击通知栏返回应用 ,非启动一个新Activity

    再使用如下的 Intent 设置: Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ ...

  8. Spring JavaConfig

    以前,Spring推荐使用XML的方式来定义Bean及Bean之间的装配规则,但是在Spring3.0之后,Spring提出的强大的JavaConfig这种类型安全的Bean装配方式,它基于Java代 ...

  9. 使用layui 和 jquery 问题小结

    问题 1 在使用 layui 2.2.5 之前,可以引入最新版的 jquery ,使用更好的性能.也可以使用layui 的jquery内部版本.如果引入要在引入layui.js 之前引入 2 使用 s ...

  10. linux环境下matlab连接mysql

    因为matlab是基于java的,但是原生的matlab是没有jdbc的,这是一个java的mysql connection. 只有matlab有这个包,才能正确的连接mysql. 1.在http:/ ...