日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

class mywnd : pubic qwidget是什么意思_学了这么久java反射,你知道class.forName和classloader的区别吗?...

發布時間:2024/9/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 class mywnd : pubic qwidget是什么意思_学了这么久java反射,你知道class.forName和classloader的区别吗?... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前兩天頭條有朋友留言說使用class.forName找不到類,可以使用classloader加載。趁此機會總結一下,正好看到面試中還經常問到。

一、類加載機制

上面兩種加載類的方式說到底還是為了加載一個java類,因此需要先對類加載的過程進行一個簡單的了解。我們寫好的程序,然后run運行,過程可以直接看下面這張圖:

往細了看大致分為5個階段:

(1)加載:java類運行時候會生成一個class字節碼文件,加載的過程就是去我們的操作系統尋找這個class文件。

(2)鏈接:這個過程就是把class文件加載到java虛擬機。

(3)初始化:在虛擬機中根據class文件進行初始化。

(4)使用:這個過程大家都明白。

(5)卸載:使用完了,java虛擬機進行清理。

對于class.forName和classloader來說針對的就是第一個過程,也就是加載過程。不過這倆雖然有一定的相似性,但是區別還是挺大的。

二、使用舉例

我們使用代碼,先看看如何使用。注意包的范圍,避免加載不了。

第一步:定義User類

public?class?User?{
????private?static?int?a?=?10;
????{
????????System.out.println("普通代碼塊");
????}
????static{
????????System.out.println("靜態變量a:"+a);
????????System.out.println("靜態代碼塊");
????}
}

第二步:測試

public?class?FDDTest?{
????public?static?void?main(String[]?args)?{
????????//注意,我在com.fdd.reflect包下建的類
????????String?user?=?"com.fdd.reflect.User";
????????test(user);
????}???
????public?static?void?test(String?user)?{
????????try?{
????????????ClassLoader?loader?=?ClassLoader.getSystemClassLoader();
????????????System.out.println("classloader?testing...");
????????????Class>?loaderUser?=?loader.loadClass(user);
????????????System.out.println("user?"?+?loaderUser.getName());
????????????System.out.println("---------------------------------------");?
????????????Class?forNameUser?=?Class.forName(user);
????????????System.out.println("Class.forName?testing...");
????????????System.out.println("user?"?+?forNameUser.getName());
????????}?catch?(ClassNotFoundException?e){
????????????e.printStackTrace();
????????}
????}
}

我們在上面的test方法中,使用了兩個加載方法。現在我們測試一下:

classloader?testing...
user?com.fdd.reflect.User
---------------------------------------
靜態變量a:10
靜態代碼塊
Class.forName?testing...
user?com.fdd.reflect.User

是不感覺有點區別。現在是先給出一個大體的使用,下面我們分析一下他們的區別。

三、區別

1、class.forName

class.forName()前者除了將類的.class文件加載到jvm中之外,還會對類進行解釋,執行類中的static塊。注意這里的靜態塊指的是在類初始化時的一些數據。但是classloader卻沒有,想要弄清楚這個原因,還是直接到源碼中看看。

@CallerSensitive
public?static?Class>?forName(String?className)?
????????????????????throws?ClassNotFoundException?{
???Class>?caller?=?Reflection.getCallerClass();
???return?forName0(className,?
???????????????????true,?
???????????????????ClassLoader.getClassLoader(caller),?
???????????????????caller);
}

在這個源碼中我們會發現,其實底層真正實現的是forName0方法,那這幾個參數又是什么意思呢?

(1)className:表示我們要加載的類名

(2)true:指Class被加載后是不是必須被初始化。不初始化就是不執行static的代碼即靜態代碼,在這里默認為true,也就是默認實現類的初始化。

(3)ClassLoader.getClassLoader(caller):表示類加載器,到這你會發現forNanme其實也是使用的ClassLoader類加載器加載的。

(4)caller:指定類加載器。

所以,在這里你可以指定是否在class加載后被初始化。而且底層還是使用的classloader加載的。

2、classloader

在上面的案例中我們發現,classloader并沒有初始化靜態塊,原因最好還是到源碼中看。

首先我們先進入到loadclass方法中的源碼。

public?Class>?loadClass(String?name)?
????????????throws?ClassNotFoundException?{
????return?loadClass(name,?false);
}

這一步看起來還看不明白,沒關系這里真正實現的是內部的loadclass,我們再跟進去看看。

protected?Class>?loadClass(String?name,?boolean?resolve)
????throws?ClassNotFoundException{
????synchronized?(getClassLoadingLock(name))?{
????????//?首先檢查這個類是否已經被加載
????????Class>?c?=?findLoadedClass(name);
????????if?(c?==?null)?{
????????????long?t0?=?System.nanoTime();
????????????try?{
???????????????//沒有被加載使用父加載器繼續加載
????????????????if?(parent?!=?null)?{
????????????????????c?=?parent.loadClass(name,?false);
????????????????}?else?{
????????????????????c?=?findBootstrapClassOrNull(name);
????????????????}
????????????}?catch?(ClassNotFoundException?e)?{}
????????????if?(c?==?null)?{
????????????????long?t1?=?System.nanoTime();
????????????????c?=?findClass(name);
??????????????? sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);???????????????? sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
????????????????sun.misc.PerfCounter.getFindClasses().increment();
????????????}
????????}
????????//如果已經加載了,那就重新加載
???????if?(resolve)?{
????????????resolveClass(c);
????????}
????????return?c;
????}
}

這個才是真正實現的方法,在這里的步驟其實很簡單,大致流程是先判斷class是否已經被加載,如果被加載了那就重新加載,如果沒有加載那就使用雙親委派原則加載。加載的時候并沒有指定是否要進行初始化。

所以現在他們的區別基本上很少,總結一下:

(1)class.forName()除了將類的.class文件加載到jvm中之外,還會對類進行解釋,執行類中的static塊。當然還可以指定是否執行靜態塊。

(2)classLoader只干一件事情,就是將.class文件加載到jvm中,不會執行static中的內容,只有在newInstance才會去執行static塊。

有一個小問題需要注意:我在網上看了幾篇文章,親測有錯誤,那就是class.forName其實是不會執行靜態方法的,但是會初始化靜態變量。錯誤的例子是使用了靜態方法為靜態變量賦值了。

ok,一個小知識點。如有問題,還請批評指正。

總結

以上是生活随笔為你收集整理的class mywnd : pubic qwidget是什么意思_学了这么久java反射,你知道class.forName和classloader的区别吗?...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。