首页 > 编程语言 >Java编程思想9

Java编程思想9

时间:2022-12-25 15:25:03浏览次数:46  
标签:Java 思想 编程 System static println out Class 加载

第十四章:类型信息
运行时类型信息使得你可以在程序运行时发现和使用类型信息。

它使你从只能在编译期执行面向类型的操作的整锢中解脱了出来。并且可以使用某些非常强大的程序。对RTTI的需要,揭示了面向对象设计中许多有趣(并且复杂)的问题,同时也提出了如何组织程序的问题。

​ 
本章将讨论 Java 是如何让我们在运行时识别对象和类的信息的。主要有两种方式∶一种是"传统的"RTTI,它假定我们在编译时已经知道了所有的类型;另一种是"反射"机制,它允许我们在运行时发现和使用类的信息。在Java中,所有的类型转换都是在运行时进行正确检查的,这也是RTTI名字的含义:在运行时,识别一个对象的类型。

Class对象
​ 要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的。这项工作是由称为Class对象的特殊对象完成的,它包含了与类有关的信息。事实上,Class对象就是用来创建类的所有的”常规“对象的。Java使用Class对象来执行其RTTI,即使你正在执行的是类似转型这样的操作。Class类还拥有大量的使用RTTI的其他方式。
类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象(更恰当地说,是被保存在一个同名的.class文件中)。为了生成这个类的对象,运行这个程序的Java虚拟机(JVM)将使用被称为"类加载器"的子系统。

​ 
类加载器子系统实际上可以包含一条类加载器链,但是只有一个原生类加载器,它是JVM 实现的一部分。原生类加载器加载的是所谓的可信类,包括Java API类,它们通常是从本地盘加载的。在这条链中,通常不需要添加额外的类加载器,但是如果你有特殊需求(例如以某种特殊的方式加载类,以支持Web服务器应用,或者在网络中下载类),那么你有一种方式可以挂接额外的类加载器。
所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这个证明构造器也是类的静态方法,即使在构造器之前并没有使用static关键字。因此,使用new操作符创建类的新对象也会被当作对类的静态成员的引用。
因此,Java程序在它开始运行之前并非被完全加载,其各个部分是在必需时才加载的。这一点与许多传统语言都不同。动态加载使能的行为,在诸如C++这样的静态加载语言中是很难或者根本不可能复制的。

​ 
类加载器首先检查这个类的Class对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名查找.class文件(例如,某个附加类加载器可能会在数据库中查找字节码)。在这个类的字节码被加载时,它们会接受验证,以确保其没有被破坏,并且不包含不良Java代码(这是Java 中用于安全防范目的的措施之一)。

​ 
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。下面的示范程序可以证明这一点∶

class Candy {
static {
System.out.println("Loading Candy");
}
}

class Gum {
static {
System.out.println("Loading Gum");
}
}

class Cookie {
static {
System.out.println("Loading Cookie");
}
}


public class SweetShop {
public static void main(String[] args) {
System.out.println("inside main");
new Candy();
System.out.println("After creating Candy");
try {
Class.forName("typeinfo.Gum");
} catch (ClassNotFoundException e) {
System.out.println("Couldn't find Gum");
}
System.out.println("After Class.forName(\"Gum\")");
new Cookie();
System.out.println("After creating Cookie");
}
}/** output:
* inside main
* Loading Candy
* After creating Candy
* Loading Gum
* After Class.forName("Gum")
* Loading Cookie
* After creating Cookie
*/

 

这里的每个类Candy、Gum和Cookie,都有一个static子句,该子句在类第一次被加载时执行。这时会有相应的信息打印出来,告诉我们这个类什么时候被加载了。在main()中,创建对象的代码被置于打印语句之间,以帮助我们判断加载的时间点。
从输出中可以看到,Cass对象仅在需要的时候才被加载。

类字面常量

​ Java还提供了另一种方法来生成对Class对象的引用,即使用类字面常量。对上述程序来说,就像下面这样∶
Gum.class;
这样做不仅更简单,而且更安全,因为它在编译时就会受到检查(因此不需要置于try语句块中)。并且它根除了对forName()方法的调用,所以也更高效。

书中建议使用".class"的形式,以保持与普通类的一致性。

注意,有一点很有趣,当使用".class"来创建对Class对象的引用时,不会自动地初始化该Class对象。为了使用类而做的准备工作实际包含三个步骤∶

1. 加载,这是由类加载器执行的。该步骤将查找字节码(通常在classpath所指定的路径中查找,但这并非是必需的),并从这些字节码中创建一个Class对象。

2. 链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必需的话,将解析这个类创建的对其他类的所有引用。

3. 初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行∶

 

class Initable {
// 编译期常量,Initable不需要被初始化就可以读取
static final int staticFinal = 47;
static final int staticFinal2 = ClassInitialization.rand.nextInt(1000);
static {
System.out.println("Initializing Initable");
}
}

class Initable2 {
static int staticNonFinal = 147;
static {
System.out.println("Initializing Initable2");
}
}

class Initable3 {
static int staticNonFinal = 74;
static {
System.out.println("Initializing Initable3");
}
}

public class ClassInitialization {
public static Random rand = new Random(47);

public static void main(String[] args) throws Exception {
Class initable = Initable.class;
System.out.println("After creating Initable ref");

// 编译期常量,这个值不需要对Initable类初始化就可以被读取
System.out.println(Initable.staticFinal);

// 对Initable.staticFinal2的访问将强制进行类得初始化,因为他不是一个编译器常量
System.out.println(Initable.staticFinal2);

// 如果一个static域不是final的,那么在对它访问时,总是要求被读取之前,要先进行链接(为这个域分配存储空间)和初始化(初始化该存储空间)
System.out.println(Initable2.staticNonFinal);

// Class.forName()立即就进行了初始化
Class initable3 = Class.forName("typeinfo.Initable3");
System.out.println("After creating Initable3 ref");
System.out.println(Initable3.staticNonFinal);
}
}/* output:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74
*/

 

标签:Java,思想,编程,System,static,println,out,Class,加载
From: https://www.cnblogs.com/LvJinshuai/p/17004057.html

相关文章