Java 编程下简介 Class 与类加载
即使有一个类并对它一无所知,但其实它本身就包含了许多信息,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 与类加载的更多相关文章
- Java 编程下 Eclipse 如何设置单行代码显示的最大宽度
Eclipse 下一行代码的默认宽度是 80 , 稍长一点的一行代码就会自动换行,代码可读性较差,我们可以自己在 Eclipse 对代码宽度进行设置. 设置路径为:[Window]→[Preferen ...
- Java 编程下使用 Class.forName() 加载类
在一些应用中,无法事先知道使用者将加载什么类,而必须让使用者指定类名称以加载类,可以使用 Class 的静态 forName() 方法实现动态加载类.下面的范例让你可以指定类名称来获得类的相关信息. ...
- Java 编程下使用 Class.forName() 加载类【转】
在一些应用中,无法事先知道使用者将加载什么类,而必须让使用者指定类名称以加载类,可以使用 Class 的静态 forName() 方法实现动态加载类.下面的范例让你可以指定类名称来获得类的相关信息. ...
- Java 编程下字符串的 16 位、32位 MD5 加密
package cn.sunzn.md5; import java.security.MessageDigest; import java.security.NoSuchAlgorithmExcept ...
- Java 编程下正则表达式判断字符串是否包含中文
package cn.sunzn.demo; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ...
- Java 编程下 Eclipse/myeclipse 如何设置单行代码显示的最大宽度
http://www.cnblogs.com/sunzn/archive/2013/03/30/2990191.html 或 http://zhidao.baidu.com/link?url=67uy ...
- 《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端
1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...
- Java编程的逻辑 (87) - 类加载机制
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- java 编程基础 类加载器
什么是类加载器 类加载器负责将class文件(可能在磁盘上,也可能在网络上)加载到内存中,并为之生成对应的java.lang.Class对象.Java开发中无须过分关心类加载机制,但所有的编程人员都应 ...
随机推荐
- 【laravel5.*】添加ide_helper.php 助手
1.参照文档:https://github.com/barryvdh/laravel-ide-helper#automatic-phpdoc-generation-for-laravel-facade ...
- ios中ASIHTTPRequst的封装
#import <Foundation/Foundation.h> #import "ASIHTTPRequest.h" #import "ASIDownlo ...
- svn备份与还原_脚本_(dump命令)
今天备份svn, 能保证好用就行先, 回头再研究 buerguo.bat @echo off :: 关闭回显 :: 说明:如有命令不明白,请使用帮助命令:命令/? .如:for/? :: 设置标题 t ...
- numpy文件读写的三对函数
在Python很多库中,使用文件名的地方都可以使用文件对象来替代. 在下述三种方法中,都是如此. 一.a.tofile()和np.fromfile() numpy中的ndarray对象有一个函数tof ...
- memcached全面剖析--4. memcached的分布式算法
我是Mixi的长野. 第2次.第3次由前坂介绍了memcached的内部情况.本次不再介绍memcached的内部结构,开始介绍memcached的分布式. memcached的分布式 正如第1次中介 ...
- mysql/mariadb基于ssl的主从复制
当mysql/mariadb跨越互联网进行复制时别人可以窃取到mysql/mariadb的复制信息, 这些信息是明文的, 因此存在不安全性, 这里通过ssl对复制的信息进行加密 1. 创建证书中心 在 ...
- android 安卓APP获取手机设备信息和手机号码的代码示例
下面我从安卓开发的角度,简单写一下如何获取手机设备信息和手机号码 准备条件:一部安卓手机.手机SIM卡确保插入手机里.eclipse ADT和android-sdk开发环境 第一步:新建一个andro ...
- mysql单机多实例
在数据库服务器上,可以架构多个Mysql服务器,进行单机多实例的读写分离: 可以通过mysqld_multi来进行多实例的管理,mysqld_multi是用perl写的脚本,原理是通过mysql_ad ...
- MongoDB学习笔记(6)--find
MongoDB 查询文档 MongoDB 查询文档使用 find() 方法. find() 方法以非结构化的方式来显示所有文档. 语法 MongoDB 查询数据的语法格式如下: db.collecti ...
- background-size ie8不支持怎么解决
background-size这个属性是css3,新增的属性,现在很多浏览器已经支持了,但是IE系列的浏览器却没有支持,比如IE8,下面介绍下如何解决这个问题 在IE浏览器中,可以通过滤镜filter ...