一、Class对象
Class对象是一种特殊的对象,它包含了与类有关的信息。事实上,Class对象就是用来创建类的所有“常规”对象的。每个类都有一个Class对象,换言之,每当编写并编译了一个新类,就会产生一个Class对象(保存在一个同名的.class文件中)。为了生成这个类的对象,运行这个程序的Java虚拟机将使用“类加载器”。
所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员引用时,就会加载这个类。这证明了构造器也是类的静态方法,即使在构造器之前并没有使用static关键字。因此,使用new创建类的新对象也会被当作对类的静态成员的引用。
类加载器首先检查这个类的Class对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名查找.class文件。在这个类的字节码被加载时,它们就会接收验证,以确保其没有被破坏,并且不包含不良的Java代码。
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。
Class对象中,forName()是取得Class对象引用的一种方法。它是用一个包含目标类的文本名(区分大小写)的String作为输入参数,返回的是该类的Class对象的引用,使用该方法会显式的要求JVM加载该类的.class文件并初始化该类。
class A
{
static
{
System.out.println("From A!");
}
}
class B extends A
{
static
{
System.out.println("From B!");
}
}
public class Test
{
public static void main(String[] args)
{
System.out.println("---------Using 'new'---------");
//创建对象之前,根据继承关系,需要首先加载A.class,然后加载B.class
B b = new B();
System.out.println("-----------------------------");
System.out.println("---Using 'Class.forname()'---");
try
{
//显式要求加载B.class,但是B.class已经加载,所以不会重新加载
Class.forName("B");
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("-----------------------------");
}
}
输出
---------Using 'new'---------
From A!
From B!
-----------------------------
---Using 'Class.forname()'---
-----------------------------
class A
{
static
{
System.out.println("From A!");
}
}
class B extends A
{
static
{
System.out.println("From B!");
}
}
public class Test
{
public static void main(String[] args)
{
System.out.println("---Using 'Class.forname()'---");
try
{
//显式要求加载B.class,发现B.class和A.class都没加载
//所以根据继承关系会先加载A.class然后加载B.class
Class.forName("B");
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println("-----------------------------");
System.out.println("---------Using 'new'---------");
//B.class已经加载,可以创建对象
B b = new B();
System.out.println("-----------------------------");
}
}
输出
---Using 'Class.forname()'---
From A!
From B!
-----------------------------
---------Using 'new'---------
-----------------------------
二、类字面常量
Java提供了另一种方法来生成对Class对象的引用,即使用“类字面常量”:例如B.class。
这样做不仅更简单,而且更安全,因为它在编译时就会受到检查(因此不需try&catch),并且它根除了对forName()方法的调用,所以更高效。
需要注意的是,当使用该方式创建对Class对象的引用时,不会自动初始化该Class对象。为了使用类而做的准备工作实际上包含三个步骤:
1.加载,这是由类加载器执行的。该步骤将查找字节码,并从这些字节码中创建一个Class对象。
2.连接。在连接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建的对其他类的所有引用。
3.初始化。如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块。
使用类字面常量时初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行。
class A
{
static
{
System.out.println("From A!");
}
}
class B extends A
{
static
{
System.out.println("From B!");
}
}
public class Test
{
public static void main(String[] args)
{
System.out.println("-----using '.class'------");
//只加载.class而不初始化,所以无输出
Class c = B.class;
System.out.println("-------------------------");
System.out.println("--using Class.forName()--");
try
{
//虽然已经加载,但是还未初始化,因此会初始化
Class.forName("B");
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("-------------------------");
}
}
输出
-----using '.class'-----
-------------------------
--using Class.forName()--
From A!
From B!
-------------------------
三、instanceof
instanceof的语法:[某个对象] instanceof [某个类或接口]
它返回一个布尔值,用来告诉我们某个对象是否是某个类的实例,或者是某个类的子类的实例;当第二个参数是接口时,表示某个对象是否是该接口的某个实现的实例。它考虑了类的继承体系。
class A
{}
class B extends A
{}
interface C
{}
class D implements C
{}
public class Test
{
public static void main(String[] args)
{
B b = new B();
System.out.println("b instance of B: " + (b instanceof B));
System.out.println("b instance of A: " + (b instanceof A));
D d = new D();
System.out.println("d instance of D: " + (d instanceof D));
System.out.println("d instance of C: " + (d instanceof C));
}
}
输出
b instance of B: true
b instance of A: true
d instance of D: true
d instance of C: true
分享到:
相关推荐
计算机的应用领域 过程控制 计算机应用基础--第一章--项目1-认识和使用计算机全文共142页,当前为第14页。 2.计算机的应用领域 计算机辅助技术 (CAD、CAM、CAI、CIMS) 计算机应用基础--第一章--项目1-认识和使用...
数据管理与分析 第13章 人工智能导论 第14章 初识机器学习 第15章 自然语言处理 第16章 语音识别技术 第17章 计算机视觉 第18 章 人工神经网络 Pyhton实用教程-第1章-初识Python全文共34页,当前为第3页。 第1章 ...
NULL 博文链接:https://listen-raining.iteye.com/blog/1897209
3 Windows 7的窗口与对话框 循环切换窗口 Alt+Tab 三维堆栈排列窗口:Windows 徽标键+Tab 关闭窗口 14 计算机应用基础第02章--Windows7应用全文共37页,当前为第14页。 3 Windows 7的窗口与对话 对话框:对话框是...
Java高级程序设计(第二版)--第2章-异常处理全文共19页,当前为第14页。 知识点:throws关键字为方法声明异常 方法声明 <throws> <异常类1>,<异常类2>,…<异常类n> { //方法体,抛出异常 } Java高级程序设计(第二版)...
4.2.2 数据输入和编辑 一、工作表中单元格和区域的选定 二、数据输入 三、数据删除 四、数据修改 五、单元格、行、列的插入与删除 2023/5/31 14 计算机应用基础第4章-中文Excel-全文共74页,当前为第14页。...
第一章 PL-SQL一览 第二章 PL-SQL基础 第三章 PL-SQL数据类型 第四章 PL-SQL的控制结构 第五章 PL-SQL集合与记录(1) ...第十一章 PL-SQL对象类型 第十二章 本地动态SQL 第十三章 PL-SQL应用程序性能调优
计算机应用基础 第1章 计算机基础知识 大学计算机应用基础教程(Windows10-MSOffice2016)-第1章-计算机基础全文共104页,当前为第1页。 主要知识点: 计算机的发展、类型及其应用领域。 计算机软硬件系统的组成及主要...
Java编程思想第十四章类型信息之反射与代理.pptx
第1章 SQL Server 概述 ...第14章 创建和维护索引 第15章 实现视图 第16章 实现存储过程 第17章 实现用户定义函数 第18章 实现触发器 第19章 多服务器编程 第20章 优化查询性能 第21章 分析查询 第22章 管理事务和锁
第十四章1-3.mp4 第十五章1-7.mp4 第十六章1-2.mp4 第十六章3-5.mp4 第十七章1-5.mp4 第十八章1-3.mp4 第十九章1-12.mp4 作业 01_05_10_MySQL之触发器.docx 01_05_011_MySQL存储过程和函数.docx 01_05_01_数据库理论...
⽤C语⾔设计程序算出1-1/2+1/3-14+1/5...+1/99-1/100的值 #include int main() { ; double a=1.0,b=2.0,sum; ) { i=-i; sum=i/b; a=a+sum; b=b+; } printf("%f ",a); ; } 2.⽤C语⾔设计程序算出1x2x3x4x5的值 #...
【C++程序设计教程 第二版】完整课程列表如下: C++程序设计教程 第1_2_3_4章 C++基础 数据类型 表达式 过程化语句(共23页) ...C++程序设计教程 第14章 模板(共32页) C++程序设计教程 第15章 异常(共5页)
1.1 简介--------------------------------------------------------------1 1.2 什么是计算机------------------------------------------------------3 1.3 计算机组成-------------------------------------...
第1章 欢迎 机构-----------------------------------------------------------------------------------------------8 怎样使用VTK-----------------------------------------------------------------------------...
计算机后端-Java-Java核心基础-第14章 面向对象06 22. 基本数据类型转换为包装类.avi
计算机后端-Java-Java核心基础-第14章 面向对象06 23. 包装类转换为基本数据类型.avi
c语言程序设计王勇第14章结构体共用体和用户定义类型-海贝.ppt
第14章-常用工具介绍 什么是SQL*Plus 使用SQL*Plus 使用PL/SQL Developer 第15章-控制文件和日志文件 控制文件与日志文件 初识控制文件 控制文件的多路复用 创建控制文件 日志文件的管理 第16章-表空间的管理...
计算机后端-Java-Java核心基础-第14章 面向对象06 25. 基本数据类型包装类与String的相互