欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Class.forName()用法及說明

 更新時間:2022年11月24日 15:38:56   作者:mocas_wang  
這篇文章主要介紹了基于Class.forName()用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

1 什么是class對象

類是程序的一部分,每個類都有一個class對象。

換言之,每當(dāng)編寫并且編譯了一個新類,就會產(chǎn)生一個class對象(更恰當(dāng)?shù)恼f,是被保存在一個同名的class文件中)。

為了生成這個類的對象,運(yùn)行這個程序的Java虛擬機(jī)(jvm)將使用被稱為“類加載器”的子系統(tǒng)。

所有的類都是在對其第一次使用的時候被加載到JVM中。如當(dāng)程序創(chuàng)建對第一個靜態(tài)成員的引用時,就會加載這個類?;蛘呤褂胣ew關(guān)鍵字創(chuàng)建新的對象的時候。

因此java程序在它運(yùn)行之前并非完全加載,其各個部分是在必須的時候才加載的。類加載器首先檢查這個類的class對象是否已經(jīng)加載。如果尚未加載,默認(rèn)的類加載器就會根據(jù)類名查找.class文件。

實際上在Java中每個類都有且只有一個Class對象。

Class 沒有公共構(gòu)造方法,因此不能顯式地聲明一個Class對象,Class 對象是在載入類時由Java 虛擬機(jī)以及通過調(diào)用類載入器中的 defineClass 方法自己主動構(gòu)造的。

Class類被創(chuàng)建后的對象就是Class對象,注意,Class對象表示的是自己手動編寫類的類型信息,比如創(chuàng)建一個Shapes類,那么,JVM就會創(chuàng)建一個Shapes對應(yīng)Class類的Class對象,該Class對象保存了Shapes類相關(guān)的類型信息。

實際上在Java中每個類都有一個Class對象,每當(dāng)我們編寫并且編譯一個新創(chuàng)建的類就會產(chǎn)生一個對應(yīng)Class對象并且這個Class對象會被保存在同名.class文件里(編譯后的字節(jié)碼文件保存的就是Class對象),那為什么需要這樣一個Class對象呢?

是這樣的,當(dāng)我們new一個新對象或者引用靜態(tài)成員變量時,Java虛擬機(jī)(JVM)中的類加載器子系統(tǒng)會將對應(yīng)Class對象加載到JVM中,然后JVM再根據(jù)這個類型信息相關(guān)的Class對象創(chuàng)建我們需要實例對象或者提供靜態(tài)變量的引用值。

需要特別注意的是,手動編寫的每個class類,無論創(chuàng)建多少個實例對象,在JVM中都只有一個Class對象,即在內(nèi)存中每個類有且只有一個相對應(yīng)的Class對象,挺拗口,通過下圖理解(內(nèi)存中的簡易現(xiàn)象圖):

到這我們也就可以得出以下幾點信息:

  • Class類也是類的一種,與class關(guān)鍵字是不一樣的。
  • 手動編寫的類被編譯后會產(chǎn)生一個Class對象,其表示的是創(chuàng)建的類的類型信息,而且這個Class對象保存在同名.class的文件中(字節(jié)碼文件),比如創(chuàng)建一個Shapes類,編譯Shapes類后就會創(chuàng)建其包含Shapes類相關(guān)類型信息的Class對象,并保存在Shapes.class字節(jié)碼文件中。
  • 每個通過關(guān)鍵字class標(biāo)識的類,在內(nèi)存中有且只有一個與之對應(yīng)的Class對象來描述其類型信息,無論創(chuàng)建多少個實例對象,其依據(jù)的都是用一個Class對象。
  • Class類只存私有構(gòu)造函數(shù),因此對應(yīng)Class對象只能有JVM創(chuàng)建和加載
  • Class類的對象作用是運(yùn)行時提供或獲得某個對象的類型信息,這點對于反射技術(shù)很重要(關(guān)于反射稍后分析)。

2 獲得class對象的三種方法

1、調(diào)用Object類的getClass()方法來得到Class對象,這也是最常見的產(chǎn)生Class對象的方法。

比如:

MyObject x;
Class c1 = x.getClass();
  • .Object.getClass(); Object中自帶的方法,getclass(),返回一個class對象。

2、使用Class類的中靜態(tài)forName()方法獲得與字符串相應(yīng)的Class對象。

比如: 

Class c2=Class.forName("MyObject")

MyObject必須是接口或者類的名字。

  • class.forname()
Class c=Class.forName("類的全限定名")

傳入string類型參數(shù),要求jvm查找并加載指定的類,返回的是一個class對象的引用。

3、獲取Class類型對象的第三個方法很easy。假設(shè)T是一個Java類型。那么T.class就代表了匹配的類對象。

比如

Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;

注意:Class對象實際上描寫敘述的僅僅是類型。而這類型未必是類或者接口。

比如上面的int.class是一個Class類型的對象。

因為歷史原因。數(shù)組類型的getName方法會返回奇怪的名字。

3 class的作用和方法

  • getname():以string類型返回class對象表示的實體(類,接口,數(shù)組,基本類型,void等)名稱
  • newInstance():創(chuàng)建一個實例,只能調(diào)用默認(rèn)構(gòu)造器。
  • getsuperclass():返回class表示的實體超類的名稱
  • getSimpleName():不辦含包名的類名。
  • isInterfence:告訴你這個class對象是否表示某個接口。

1、getName() 

一個Class對象描寫敘述了一個特定類的屬性,Class類中最經(jīng)常使用的方法getName以 String 的形式返回此 Class 對象所表示的實體(類、接口、數(shù)組類、基本類型或 void)名稱。

2、newInstance()

Class另一個實用的方法能夠為類創(chuàng)建一個實例,這種方法叫做newInstance()。

比如:

x.getClass.newInstance()

創(chuàng)建了一個同x一樣類型的新實例。newInstance()方法調(diào)用默認(rèn)構(gòu)造器(無參數(shù)構(gòu)造器)初始化新建對象。

3、getClassLoader() 

返回該類的類載入器。

4、getComponentType() 

返回表示數(shù)組組件類型的 Class。

5、getSuperclass() 

返回表示此 Class 所表示的實體(類、接口、基本類型或 void)的超類的 Class。

6、isArray() 

判定此 Class 對象是否表示一個數(shù)組類。

1、forName和newInstance結(jié)合起來使用,能夠依據(jù)存儲在字符串中的類名創(chuàng)建對象。比如

Object obj = Class.forName(s).newInstance();

2、虛擬機(jī)為每種類型管理一個獨一無二的Class對象。因此能夠使用==操作符來比較類對象。比如:

if(e.getClass() == Employee.class)...

4 Class.forName()用法

主要功能

  • Class.forName(xxx.xx.xx)返回的是一個類。
  • Class.forName(xxx.xx.xx)的作用是要求JVM查找并加載指定的類,也就是說JVM會執(zhí)行該類的靜態(tài)代碼段。

Class.forName是一個靜態(tài)方法,相同能夠用來載入類。

該方法有兩種形式:Class.forName(String name, boolean initialize, ClassLoader loader)和 Class.forName(String className)。

第一種形式的參數(shù) name表示的是類的全名;initialize表示是否初始化類。loader表示載入時使用的類載入器。

另外一種形式則相當(dāng)于設(shè)置了參數(shù) initialize的值為 true。loader的值為當(dāng)前類的類載入器

4.1 什么時候用Class.forName()?

先來個熱身,給你一個字符串變量,它代表一個類的包名和類名,你怎么實例化它?你第一想到的肯定是new,但是注意一點:

A a = (A)Class.forName(“pacage.A”).newInstance();

這和你 A a = new A(); 是一樣的效果。

現(xiàn)在言歸正傳。

動態(tài)加載和創(chuàng)建Class 對象,比如想根據(jù)用戶輸入的字符串來創(chuàng)建對象時需要用到:

String str = “用戶輸入的字符串” ;
Class t = Class.forName(str);
t.newInstance();

在初始化一個類,生成一個實例的時候,newInstance()方法和new關(guān)鍵字除了一個是方法,一個是關(guān)鍵字外,最主要有什么區(qū)別?

它們的區(qū)別在于創(chuàng)建對象的方式不一樣,前者是使用類加載機(jī)制,后者是創(chuàng)建一個新類。

4.2 newInstance和new關(guān)鍵字的區(qū)別

Java中工廠模式經(jīng)常使用newInstance()方法來創(chuàng)建對象,因此從為什么要使用工廠模式上可以找到具體答案。 例如:

class c = Class.forName(“Example”);
factory = (ExampleInterface)c.newInstance();

其中ExampleInterface是Example的接口,可以寫成如下形式:

String className = “Example”;
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();

進(jìn)一步可以寫成如下形式:

String className = readfromXMlConfig;//從xml 配置文件中獲得字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();

上面代碼已經(jīng)不存在Example的類名稱,它的優(yōu)點是,無論Example類怎么變化,上述代碼不變,甚至可以更換Example的兄弟類Example2 , Example3 , Example4……,只要他們繼承ExampleInterface就可以。

從JVM的角度看,我們使用關(guān)鍵字new創(chuàng)建一個類的時候,這個類可以沒有被加載。但是使用newInstance()方法的時候,就必須保證:

1、這個類已經(jīng)加載;

2、這個類已經(jīng)連接了。

而完成上面兩個步驟的正是Class的靜態(tài)方法forName()所完成的,這個靜態(tài)方法調(diào)用了啟動類加載器,即加載 java API的那個加載器。

現(xiàn)在可以看出,newInstance()實際上是把new這個方式分解為兩步,即首先調(diào)用Class加載方法加載某個類,然后實例化。

這樣分步的好處是顯而易見的。我們可以在調(diào)用class的靜態(tài)加載方法forName時獲得更好的靈活性,提供給了一種降耦的手段。

最后用最簡單的描述來區(qū)分new關(guān)鍵字和newInstance()方法的區(qū)別: 

  • newInstance: 弱類型。低效率。只能調(diào)用無參構(gòu)造。 
  • new: 強(qiáng)類型。相對高效。能調(diào)用任何public構(gòu)造。
  • Class.forName(“”)返回的是類。
  • Class.forName(“”).newInstance()返回的是object

5 應(yīng)用問題解析

情景一:載入數(shù)據(jù)庫驅(qū)動的時候

Class.forName的一個非經(jīng)常見的使用方法是在載入數(shù)據(jù)庫驅(qū)動的時候

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName==JSP","jph","jph");  

為什么在我們載入數(shù)據(jù)庫驅(qū)動包的時候有的卻沒有調(diào)用newInstance( )方法呢?

即有的jdbc連接數(shù)據(jù)庫的寫法里是Class.forName(xxx.xx.xx);而有一些:Class.forName(xxx.xx.xx).newInstance()。為什么會有這兩種寫法呢? 

 通過查詢Java Documentation我們會發(fā)現(xiàn)使用Class.forName( )靜態(tài)方法的目的是為了動態(tài)加載類。通常編碼過程中,在加載完成后,一般還要調(diào)用Class下的newInstance( )靜態(tài)方法來實例化對象以便操作。因此,單使用Class.forName( )是動態(tài)加載類是沒有用的,其最終目的是為了實例化對象。

剛才提到,Class.forName("");的作用是要求JVM查找并加載指定的類,如果在類中有靜態(tài)初始化器的話,JVM必然會執(zhí)行該類的靜態(tài)代碼 段。而在JDBC規(guī)范中明確要求這個Driver類必須向DriverManager注冊自己,即任何一個JDBC Driver的 Driver類的代碼都必須類似如下:

public class MyJDBCDriver implements Driver {
   static {
     DriverManager.registerDriver(new MyJDBCDriver());
  }
  }

既然在靜態(tài)初始化器的中已經(jīng)進(jìn)行了注冊,所以我們在使用JDBC時只需要Class.forName(XXX.XXX);就可以了。

既然在靜態(tài)初始化器的中已經(jīng)進(jìn)行了注冊,所以我們在使用JDBC時只需要Class.forName(XXX.XXX);就可以了。

public class ProxoolDriver implements Driver {
 
    private static final Log LOG = LogFactory.getLog(ProxoolDriver.class);
 
    static {
        try {
            DriverManager.registerDriver(new ProxoolDriver());
        } catch (SQLException e) {
            System.out.println(e.toString());
        }
    }
 
}

情景二:使用AIDL與電話管理Servic進(jìn)行通信

Method method =Class.forName("android.os.ServiceManager")
 
         .getMethod("getService",String.class);
 
// 獲取遠(yuǎn)程TELEPHONY_SERVICE的IBinder對象的代理
 
IBinder binder =(IBinder) method.invoke(null, new Object[] { TELEPHONY_SERVICE});
 
// 將IBinder對象的代理轉(zhuǎn)換為ITelephony對象
 
ITelephonytelephony = ITelephony.Stub.asInterface(binder);
 
// 掛斷電話
 
telephony.endCall();

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強(qiáng)大)

    IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強(qiáng)大

    這篇文章主要介紹了IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強(qiáng)大),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Spring WebFlux實現(xiàn)參數(shù)校驗的示例代碼

    Spring WebFlux實現(xiàn)參數(shù)校驗的示例代碼

    請求參數(shù)校驗,在實際的應(yīng)用中很常見,網(wǎng)上的文章大部分提供的使用注解的方式做參數(shù)校驗。本文主要介紹 Spring Webflux Function Endpoint 使用 Spring Validation 來校驗請求的參數(shù)。感興趣的可以了解一下
    2021-08-08
  • Java實現(xiàn)的日期處理類完整實例

    Java實現(xiàn)的日期處理類完整實例

    這篇文章主要介紹了Java實現(xiàn)的日期處理類,結(jié)合完整實例形式分析了Java針對日期的獲取、運(yùn)算、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • Spring Security實現(xiàn)身份認(rèn)證和授權(quán)的示例代碼

    Spring Security實現(xiàn)身份認(rèn)證和授權(quán)的示例代碼

    在 Spring Boot 應(yīng)用中使用 Spring Security 可以非常方便地實現(xiàn)用戶身份認(rèn)證和授權(quán),本文主要介紹了Spring Security實現(xiàn)身份認(rèn)證和授權(quán)的示例代碼,感興趣的可以了解一下
    2023-06-06
  • Spring Cloud Gateway網(wǎng)關(guān)XSS過濾方式

    Spring Cloud Gateway網(wǎng)關(guān)XSS過濾方式

    這篇文章主要介紹了Spring Cloud Gateway網(wǎng)關(guān)XSS過濾方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java非官方常用類MessageInfo消息接口示例

    java非官方常用類MessageInfo消息接口示例

    這篇文章主要為大家介紹了java非官方常用類MessageInfo消息接口使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • 基于springboot實現(xiàn)redis分布式鎖的方法

    基于springboot實現(xiàn)redis分布式鎖的方法

    這篇文章主要介紹了基于springboot實現(xiàn)redis分布式鎖的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java web中 HttpClient模擬瀏覽器登錄后發(fā)起請求

    java web中 HttpClient模擬瀏覽器登錄后發(fā)起請求

    這篇文章主要介紹了java web中 HttpClient模擬瀏覽器登錄后發(fā)起請求的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Spring Boot 集成 ElasticSearch應(yīng)用小結(jié)

    Spring Boot 集成 ElasticSearch應(yīng)用小結(jié)

    這篇文章主要介紹了Spring Boot 集成 ElasticSearch應(yīng)用小結(jié),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-11-11
  • Spring?Boot?配置?Hikari?數(shù)據(jù)庫連接池的操作代碼

    Spring?Boot?配置?Hikari?數(shù)據(jù)庫連接池的操作代碼

    數(shù)據(jù)庫連接池是一個提高程序與數(shù)據(jù)庫的連接的優(yōu)化,連接池它主要作用是提高性能、節(jié)省資源、控制連接數(shù)、連接管理等操作,這篇文章主要介紹了SpringBoot配置Hikari數(shù)據(jù)庫連接池,需要的朋友可以參考下
    2023-09-09

最新評論