你知道java反射機制中class.forName和classloader的區別嗎?

2020-12-14 愚公要移山1

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

一、類加載機制

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

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

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

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

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

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

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

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

二、使用舉例

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

第一步:定義User類

第二步:測試

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

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

三、區別

1、class.forName

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

在這個源碼中我們會發現,其實底層真正實現的是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,我們再跟進去看看。

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

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

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

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

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

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

相關焦點

  • Java基礎增強篇一,Java核心功能反射機制
    Java反射機制1. java代碼在 java 語言中最核心的就是代碼的運行, 按照面向對象的思想,在調用java代碼時往往需要先創建對象,再調用方法, 而寫在方法中的即所謂的java 代碼先分析Class對象的圖解:
  • 程式設計師:什麼是Java反射機制,有什麼作用
    什麼是Java反射機制?Java反射機制是 Java 語言的一個重要特性,它在伺服器程序和中間件程序中得到了廣泛運用。在伺服器端,往往需要根據客戶的請求,動態調用某一個對象的特定方法。此外,在 ORM 中間件的實現中,運用 Java 反射機制可以讀取任意一個 JavaBean 的所有屬性,或者給這些屬性賦值通過反射機制,可以在運行的時候訪問到對象的屬性、方法、構造方法等等哪些地方用到反射機制?其實我們都用過反射機制,只是並不知道它是反射機制而已。
  • 說說Java的反射機制
    一、什麼是反射動態獲取類的信息以及動態調用對象的方法稱為Java的反射(Reflection)機制。反射提供了封裝程序集、模塊和類型的對象。在Java運行時環境中,對於任意一個類的對象,可以通過反射獲取這個類的信息。
  • Java高級特性:反射機制
    概述JAVA反射機制:在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制。
  • get新技能,Java的Class與反射機制原理,讓你寫出更靈活的代碼
    前言最近一些朋友怎麼是說自己的代碼太複雜、太臃腫、靈活性太差,也不知道問題出在哪裡。首先表揚一下你的精神,可以時刻關注著自己代碼的問題。反射機制反射是框架設計的靈魂,java的反射機制就是增加程序的靈活性,避免將代碼寫死在程序裡反射的概述JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性
  • ClassLoader——JAVA成長之路
    ClassLoader 中與加載類相關的方法對於 java.lang.ClassLoader類介紹 中給出的方法,表示類名稱的 name 參數的值是類的二進位名稱。該方法有兩種形式:Class.forName(String name, boolean initialize, ClassLoader loader) 和 Class.forName(String className) 。
  • 阿里P8教你Java註解與反射
    Ⅰ 什麼是註解Java 註解(Annotation)又稱 Java 標註,是 JDK5.0 引入的一種注釋機制。Java 語言中的類、方法、變量、參數和包等都可以被標註。和 Javadoc 不同,Java 標註可以通過反射獲取標註內容。在編譯器生成類文件時,標註可以被嵌入到字節碼中。
  • 如何使用JAVA反射/JAVA反射實例
    JAVA反射技術,在平時我們的開發中雖然很少會用到例如讀取配製文件可能就用到這個技術,但在我們所使用的框架源碼中是經常會用到的。通過Object類中的方法實例化  c3 = X.class ; // 通過類.class實例化  System.out.println("類名稱:" + c1.getName())  ; // 得到類的名稱  System.out.println("類名稱:" + c2.getName())  ; // 得到類的名稱  System.out.println("類名稱:" + c3.getName(
  • 強烈推薦:Java的反射機制和使用你們都知道嗎?
    Java中的反射機制和使用想必大家都不是很了解,今天我就和大家一起來認識和學習這些知識點吧,發射這個詞相信大家平時學習時用的不多但聽的很多,特別是在各種開源框架中,很多框架都用到反射機制,hibernate,struts ,spring等框架都是用反射機制實現的。
  • 一起學JAVA——反射技術
    反射技術是java動態特性的基石,java之所以有很多開發框架就是因為反射技術的存在。什麼是反射JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。
  • Java面試高頻考點:反射機制使用大全
    作為一個Java開發工程師,在面試的過程中,反射機制也是經常會被問到的一個問題。例如Spring的IOC實現機制,其底層都是依賴於java的反射機制,因此,這是一個非常重要的知識點。對於初學java的同學來說,掌握其使用方法很有必要。
  • Java編程中基礎反射詳細解析
    類加載指的是將類的class文件讀入內存中,並為之創建一個 java.lang.Class對象,也就是說程序使用任何類的時候,都會為其創建一個class對象。反射Java反射就是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;並且能改變它的屬性。
  • Java中反射學習系列教程三-常用API方法
    本文是《Java中反射學習系列教程》中的第三篇文章。本文我們接著之前的講解。先來看看今天學習主要內容:4.2.2 實例化class對象的幾種方式Class對象獲取共有三種方式。> clazz3 = null;clazz3 = Person.class;log.info("clazz1 name:{}",clazz1.getName());log.info("clazz2 name:{}",clazz2.getName());log.info("clazz3 name
  • Java反射,泛型在Json中的運用
    最近項目中遇到了Json數據自動獲取的功能,不然令人想起java的反射,已經很長時間沒複習java了正好一塊連java的這一塊內容一起過一遍。java中的反射無疑就相當於java開發者的春天,在眾多的框架中也能看到它的身影,可以在運行時檢查類,接口、變量和方法等信息,可以實例化調用方法以及設置變量值等。本文主要以代碼的形式直接將反射,泛型的運用展現出來。java中的反射首先新建一個基礎類Author。
  • 反射——Java高級開發必須懂得
    一、Class類的使用任何一個類都是Class的實例對象,這個實例對象有三種表示方式1、任何一個類都有一個隱含的靜態成員變量classClass c1=Foo.class;2、已經知道該類的對象通過getClass
  • 一文帶你深扒ClassLoader內核,揭開它的神秘面紗!
    > findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name);}如果你不想重新定義加載類的規則,也沒有複雜的處理邏輯,只想在運行時能夠加載自己制定的一個類,那麼你可以用 this.getClass().getClassLoader
  • Java中的回調與事件機制
    在main方法中,我們向Caller類的對象傳入了一個MyImplement對象(在回調概念中,可以說是註冊回調方法)。在這個例子中,我們沒有使用內部類,而且廢了好大力氣就是為了得到一個簡單的結果,這看起來沒有什麼意義,實際上,我們只是通過這個例子來說明Java中回調機制的工作模式。
  • JAVA的反射,你需要了解
    JAVA的反射,是JAVA的核心技術要點。有很多我們耳熟能詳的框架、api,其底層就是使用了java反射功能來實現的。比如jdbc加載不同的資料庫驅動,spring容器加載對象,idea的提示等等。那麼,究竟什麼是JAVA 的反射呢?JAVA反射又是怎樣實現上述功能的呢?一、什麼是JAVA反射?
  • Java反射:框架設計的靈魂
    靜態語言:相對於動態語言來說,在編譯時變量的數據類型就已經確定(使用變量之前必須聲明數據類型),在編譯時就會進行類型是否匹配;比如 C 語言、Java ;03.反射的概念Java 反射機制:在運行過程中,對於任意一個類,都能知道其所有的屬性和方法;對於任意一個對象,都能調用其屬性和方法;這種動態獲取類信息和調用對象方法的功能
  • Java咖啡館(11):Java插件技術
    要知道,Java插件技術與我們上回咖啡館中介紹的運行Applet的方法有著本質上的區別。  在上回Java咖啡館中,我向大家介紹了Applet編寫過程,以及在IE中運行Applet的方法。回憶一下,我們是通過在HTML網頁中嵌入<applet>標籤實現的。