偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Java開發(fā)中類的加載及反射機制

開發(fā) 后端
JAVA中類文件加載是動態(tài)的。JVM指令是被封裝在了.class文件里面,而.class文件的加載過程是動態(tài)的,也就是說當(dāng)我們用到的時候才會去加載,如果不用的話,就不會去加載我們的類。

JAVA中類文件加載是動態(tài)的。JVM指令是被封裝在了.class文件里面,而.class文件的加載過程是動態(tài)的,也就是說當(dāng)我們用到的時候才會去加載,如果不用的話,就不會去加載我們的類。這里所說的用到包括兩種方式,***種就是new一個對象的時候(這個時候要特別注意,當(dāng)設(shè)計到多態(tài)的時候,就會有一點點變化,這時候編譯器會做一些優(yōu)化,這樣以來當(dāng)加載的時候會提前加載設(shè)計到多態(tài)的類,關(guān)于這一點下面有個例子(example 1)來說明。另一種就是當(dāng)一個類的靜態(tài)代碼被調(diào)用的時候。

java 代碼
//example 1
//Zoo.java
abstract class Animal {
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
private Animal am; //Example 1.1
//private Dog am; Example 1.2
private Tiger tiger;
Zoo(){
tiger = new Tiger();
am = new Dog();
}
public static void main(String [] args){
System.out.println("new Zoo before");
Zoo z = new Zoo();
System.out.println("new Zoo after ");
}
}

我們可以看出:當(dāng)我們將子類對象賦值給父類時,編譯器會做一點優(yōu)化,于是加載器在還沒有new子類對象的時候已經(jīng)加載了父類以及子類(example1.1結(jié)果),當(dāng)不存在多態(tài)的時候,我們可以看到是當(dāng)要new Dog()的時候才會加載Dog以及父類。無論何種方式,在new之前,類確實已經(jīng)加載到了內(nèi)存中。

JAVA為我們提供了兩種動態(tài)機制。***種是隱式機制。其實new一個對象和調(diào)用類的靜態(tài)方法時,就是隱式機制在工作。第二種是顯示機制。顯示的機制又有兩種策略(***種是用java.lang.Class的forName(String str)方法,第二種是用java.lang.ClassLoader的loadClass())。#p#

***種:利用forName方法

當(dāng)我們查API文檔就會發(fā)現(xiàn)forName方法有兩種形式。分別如下:

public static Class<?> forName(String className)
throws ClassNotFoundException
public static Class<?> forName(String name,
boolean initialize,
ClassLoader loader)
throws ClassNotFoundException

先來說說第二種方法:第二個方法值得注意的就是第二個參數(shù)boolean initialize,如果我們把這個參數(shù)設(shè)置為false,那么當(dāng)我們加載完類后就不會執(zhí)行靜態(tài)代碼和靜態(tài)的初始化動作。只有當(dāng)我們new一個對象的時候才會初始化。而第三個參數(shù)是用來指明類的加載器的。

如果查看java.lang.Class類的源代碼,上述兩種方法最終都會調(diào)用Class類中的私有的native方法forName0(),此方法的聲明如下:

private static native Class forName0(String name, boolean init,ClassLoader loader)
throws ClassNotFoundException;

所以當(dāng)我們調(diào)用Class.forName(name )時,其實是在方法內(nèi)部調(diào)用了:

forName0(name, true, ClassLoader.getCallerClassLoader());

當(dāng)我們調(diào)用Class.forName(name, initialize, loader )的時候,實際上此方法內(nèi)部調(diào)用了:

forName0(name, initialize, loader);

下面看一個例子,如果方法中第二個參數(shù)為false的情況:

java 代碼
//example 2.1
//Zoo.java
abstract class Animal {
static {
System.out.println("Animal static code block ");
}
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
public static void main(String [] args)throws Exception {
System.out.println("new Zoo before");
Zoo z = new Zoo();
Class c = Class.forName("Dog",false,z.getClass().getClassLoader());
System.out.println("initilize before ");
Animal dog = (Animal)c.newInstance();
System.out.println("new Zoo after ");
}
}

類加載完成后并沒有立即執(zhí)行靜態(tài)初始化代碼,而是到了實例化的時候才進行了靜態(tài)初始化。有時候我們會說靜態(tài)代碼是在類***次被加載時執(zhí)行的,并且只執(zhí)行一次。其實這是對與new一個對象,***次訪問類的靜態(tài)代碼以及第二個參數(shù)為true時而言的,對于動態(tài)的加載來說,如果forName方法的第二個參數(shù)設(shè)置為false,那么就是在實例化的時候才會執(zhí)行靜態(tài)初始化。當(dāng)然默認情況下第二個參數(shù)是true。#p#

第二種方法:利用Class對象獲取的ClassLoader裝載

下面是一個簡單的例子:

java 代碼
//Example 2.2
//Zoo.java
abstract class Animal {
static {
System.out.println("Animal static code block ");
}
Animal(){
System.out.println("Animal constructor");
}
}
class Tiger extends Animal {
Tiger(){
System.out.println("Tig constructor ");
}
}
class Dog extends Animal {
Dog(){
System.out.println("Dog Constructor ");
}
}
public class Zoo {
public static void main(String [] args)throws Exception {
Class c = Zoo.class;
ClassLoader loader = c.getClassLoader();
System.out.println("loader before");
Class dog = loader.loadClass("Dog");
System.out.println("instance before ");
Animal an = (Animal)dog.newInstance();
}
}

loader完成以后并沒有立即進行靜態(tài)代碼的執(zhí)行。只有當(dāng)newInstance()的時候才執(zhí)行靜態(tài)初始化,這和把public static Class forName(String name, boolean initialize, ClassLoader loader)的第二個參數(shù)指定為false的情況完全一樣。其實每當(dāng)我們寫完一個編譯單元以后就會得到一個.calss文件,這個文件中就包含了該類的Class對象。JVM就是利用這個class對象來進行動態(tài)裝載類的。

【編輯推薦】

  1. 深入Java布局管理器
  2. Java軟件架構(gòu)設(shè)計簡介
  3. Java和PHP在Web開發(fā)方面的比較
責(zé)任編輯:田超 來源: JAVA8
相關(guān)推薦

2021-07-05 06:51:43

Java機制類加載器

2023-10-17 09:26:44

Java工具

2011-06-08 10:06:32

C#

2011-09-27 10:23:24

Java反射機制

2017-03-08 10:30:43

JVMJava加載機制

2017-09-20 08:07:32

java加載機制

2012-07-09 14:25:04

程序集加載

2024-09-06 09:37:45

WebApp類加載器Web 應(yīng)用

2021-01-06 09:01:05

javaclass

2025-06-26 03:33:00

2025-07-01 07:41:37

Java類加載器雙親委派

2011-07-12 10:24:17

類加載反射

2012-04-05 13:50:38

Java

2023-10-31 16:00:51

類加載機制Java

2011-04-01 14:50:56

Java的反射機制

2023-05-10 11:07:18

2020-05-20 22:13:26

JVM加載機制虛擬機

2024-03-12 07:44:53

JVM雙親委托機制類加載器

2017-03-24 09:44:33

Java反射機制

2017-05-17 15:28:15

Java反射機制
點贊
收藏

51CTO技術(shù)棧公眾號