激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java在運(yùn)行時識別類型信息的方法詳解

Java在運(yùn)行時識別類型信息的方法詳解

2021-07-12 15:11沉默王二 Java教程

這篇文章主要給大家介紹了關(guān)于Java在運(yùn)行時識別類型信息的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考借鑒,下面來一起看看吧

前言

在日常的學(xué)習(xí)工作當(dāng)中,有一些知識是我們在讀書的時候就能夠習(xí)得;但有一些知識不是的,需要在實踐的時候才能得到真知——這或許就是王陽明提倡的“知行合一”。

在java中,并不是所有的類型信息都能在編譯階段明確,有一些類型信息需要在運(yùn)行時才能確定,這種機(jī)制被稱為rtti,英文全稱為run-time type identification,即運(yùn)行時類型識別,有沒有一點“知行合一”的味道?運(yùn)行時類型識別主要由class類實現(xiàn)。

01 class類

在java中,我們常用“class”(首字母為小寫的c)關(guān)鍵字來定義一個類,說這個類是對某一類對象的抽象。你比如說王二是一個網(wǎng)絡(luò)知名作者,我們可以這樣簡單地定義作者類:

?
1
2
3
4
5
6
package com.cmower.java_demo.fifteen;
 
class author {
 private string pen_name;
 private string real_name;
}

現(xiàn)在,我們想知道writer這個類本身的一些信息(比如說類名),該怎么辦呢?這時候就需要用到“class”(首字母為大寫的c)類,該類包含了與類有關(guān)的信息。請看以下代碼:

?
1
2
3
4
5
6
7
8
public class test {
 public static void main (string [] args) {
  author wanger = new author();
  class c1 = wanger.getclass();
  system.out.println(c1.getname());
  //輸出 com.cmower.java_demo.fifteen.author
 }
}

當(dāng)我們創(chuàng)建了作者對象wanger后,就可以通過wanger.getclass()獲取wanger的class對象,通過c1.getname()可獲得wanger對象的類名。

想象一下,經(jīng)過五年的刻意練習(xí),王二從一名寫作愛好者晉升為一名作家了。我們用代碼來假裝一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.cmower.java_demo.fifteen;
 
class author {
 private string pen_name;
 private string real_name;
}
 
class writer extends author {
 private string honour;
}
 
public class test {
 public static void main (string [] args) {
  author wanger = new writer();
  class c1 = wanger.getclass();
  system.out.println(c1.getname());
  //輸出 com.cmower.java_demo.fifteen.writer
 }
}

在上例中,即使我們將writer的對象引用wanger向上轉(zhuǎn)型為author,wanger的class對象類型依然是writer(通過輸出結(jié)果可以判定)。這也就是說,java能夠在運(yùn)行時自動識別類型的信息,它不會因為wanger的引用類型是author而丟失wanger真正的類型信息(writer)。java是怎么做到這一點呢?

當(dāng)java創(chuàng)建某個類的對象,比如writer類對象時,java會檢查內(nèi)存中是否有相應(yīng)的class對象。如果內(nèi)存中沒有相應(yīng)的class對象,那么java會在.class文件中尋找writer類的定義,并加載writer類的class對象。

一旦class對象加載成功,就可以用它來創(chuàng)建這種類型的所有對象。這也就是說,每個對象在運(yùn)行時都會有對應(yīng)的class對象,這個class對象包含了這個對象的類型信息。因此,我們能夠通過class對象知道某個對象“真正”的類型,并不會因為向上轉(zhuǎn)型而丟失。

02 獲取class對象的其他方式

在使用getclass()方法獲取一個類的class對象時,我們必須要先獲取這個類的對象,比如上面提到的wanger。如果我們之前沒有獲取這個類的對象,就需要用另外兩種方式來獲取類的class對象:

?
1
2
3
4
5
6
7
8
9
class c2 = writer.class;
system.out.println(c2.getname());
 
try {
 class c3 = class.forname("com.cmower.java_demo.fifteen.writer");
 system.out.println(c3.getname());
} catch (classnotfoundexception e) {
 e.printstacktrace();
}

1)當(dāng)使用.class來獲取class對象時,不會自動地初始化該class對象,初始化被延遲到了對靜態(tài)方法或者非final靜態(tài)域進(jìn)行首次引用時才執(zhí)行。這樣做不僅更簡單,而且更安全,因為它在編譯時就會受到檢查(因此不需要置于try語句塊中)。

2)class.forname會自動地初始化該class對象,但需要指定類名,并且需要置于try語句塊中。

03 class類提供的常用方法

class類為我們提供了一些非常有用的方法,比如說getname()用來返回類名,getpackage()返回類所在的包名。

我們還可以利用class類提供的newinstance()方法來創(chuàng)建相應(yīng)類的對象,比如:

?
1
2
3
4
5
6
7
8
9
10
class c2 = writer.class;
system.out.println(c2.getname());
 
try {
 writer wangsan = (writer) c2.newinstance();
 system.out.println(wangsan);
 // 輸出:com.cmower.java_demo.fifteen.writer@7852e922
} catch (instantiationexception | illegalaccessexception e1) {
 e1.printstacktrace();
}

由于我們在創(chuàng)建class對象c2時沒有使用泛型,所以newinstance()返回的對象類型需要強(qiáng)轉(zhuǎn)為writer。我們可以在此基礎(chǔ)上進(jìn)行改進(jìn),示例如下:

?
1
2
3
4
5
6
7
8
9
10
class<writer> c4 = writer.class;
system.out.println(c4.getname());
 
try {
 writer wangsan = c4.newinstance();
 system.out.println(wangsan);
 // 輸出:com.cmower.java_demo.fifteen.writer@7852e922
} catch (instantiationexception | illegalaccessexception e1) {
 e1.printstacktrace();
}

04 反射

我們還可以通過getfields()獲取所有public修飾的字段,通過getmethods()返回所有public修飾的方法。

甚至,我們還可以通過getdeclaredfields()獲取更多字段,包括公共、受保護(hù)、默認(rèn)(包)訪問和私有字段,但不包括繼承字段。對應(yīng)的,getdeclaredmethods()用來獲取更多方法。示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.cmower.java_demo.fifteen;
 
import java.lang.reflect.field;
import java.lang.reflect.method;
 
class author {
 private string pen_name;
 private string real_name;
}
 
class writer extends author {
 private string honour;
 
 private void makemoney() {
  system.out.println("很多很多錢");
 }
}
 
public class test {
 public static void main(string[] args) {
 
  class<writer> c4 = writer.class;
  system.out.println(c4.getname());
 
  try {
   writer wangsan = c4.newinstance();
   system.out.println(wangsan);
 
   field[] fields = c4.getdeclaredfields();
   for (field field : fields) {
    system.out.println(field.getname());
   }
 
   method[] methods = c4.getdeclaredmethods();
   for (method method : methods) {
    system.out.println(method.getname());
   }
  } catch (instantiationexception | illegalaccessexception e1) {
   e1.printstacktrace();
  }
 
 }
}

上面的例子其實涉及到了反射,field、method(還有例子中未提到的constructor)都來自java.lang.reflect類庫。class類與java.lang.reflect類庫一起對反射的概念進(jìn)行了支持。

有時候,我們需要從磁盤文件或網(wǎng)絡(luò)文件中讀取一串字節(jié)碼,并把它轉(zhuǎn)換成一個類,這時候就需要用到反射。最常見的典型例子就是將一串json字符串(在網(wǎng)絡(luò)傳輸中最初的形態(tài)可能是字節(jié)數(shù)組)反射為對應(yīng)類型的對象。

阿里巴巴提供的fastjson提供了 tojsonstring() 和 parseobject() 方法來將 java 對象與 json 相互轉(zhuǎn)換。調(diào)用tojsonstring方法即可將對象轉(zhuǎn)換成 json 字符串,parseobject 方法則反過來將 json 字符串轉(zhuǎn)換成對象。fastjson的內(nèi)部其實用的就是反射機(jī)制。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.cmower.common.util;
 
import java.io.unsupportedencodingexception;
 
import org.apache.commons.logging.log;
import org.apache.commons.logging.logfactory;
 
import com.alibaba.fastjson.json;
 
@suppresswarnings("all")
public class jsonutil {
 private static log logger = logfactory.getlog("json");
 
 public static byte[] objecttobyte(object obj) throws unsupportedencodingexception {
  string jsonstr = json.tojsonstring(obj);
  logger.debug("序列化后數(shù)據(jù):" + jsonstr);
  return jsonstr.getbytes("utf-8");
 }
 
 public static <t> t bytetoobject(byte[] data, class<t> obj) throws unsupportedencodingexception {
  string objectstring = new string(data, "utf-8");
  logger.debug("反序列化后數(shù)據(jù) : " + objectstring);
  return json.parseobject(objectstring, obj);
 }
 
 public static <t> object stringtoobject(string data, class<t> obj) throws unsupportedencodingexception {
  logger.debug("反序列化后數(shù)據(jù) : " + data);
  return json.parseobject(data, obj);
 }
}

05 總結(jié)

為了完成這篇文章,我特意和青苗谷的一名技術(shù)專家聊了聊,問他了幾個很傻逼的問題:“‘運(yùn)行時'是什么意思?是站在java虛擬機(jī)的角度,還是程序員的角度?”

他給了我很好的解釋和啟發(fā),我不由覺得非常的慚愧,作為一名年紀(jì)頗長的java學(xué)習(xí)者,竟然對理論知識薄弱到令人發(fā)指的地步——不知道你是否也有這樣的困惑?

但寫作的好處就在于此,在向讀者解釋“java如何在運(yùn)行時識別類型信息”的過程中,我的思路逐漸地清晰了起來——這真是一個自我提升的好辦法!

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。

原文鏈接:https://www.cnblogs.com/qing-gee/p/10313662.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美日韩精品一区二区三区不卡 | 丰满年轻岳中文字幕一区二区 | 国产一级爱c视频 | 欧美日韩中文字幕在线视频 | 草b视频在线观看 | 精品在线视频播放 | 91短视频在线观看 | 羞羞视频免费网站 | 亚洲午夜免费 | 极色品影院 | 日韩精品中文字幕在线观看 | 亚洲影视在线观看 | 久久久久二区 | 欧美日韩成人一区二区 | 精品成人av一区二区三区 | 亚洲网站免费观看 | 国产99久久久久 | 亚洲精品tv久久久久久久久久 | 国产精品嘿咻嘿咻在线播放 | 亚洲va久久久噜噜噜久牛牛影视 | 国产片91 | av噜噜噜噜| 一级毛片a级 | 国产精品亚洲综合 | 午夜视频亚洲 | 日韩一级片毛片 | 娇喘视频在线观看 | 在线观看av国产一区二区 | 成人激情视频网站 | 调教小男生抽打尿孔嗯啊视频 | 美国av免费看 | 日韩黄色精品视频 | fc2国产成人免费视频 | 国产精品久久久久久久av | 中国女人内谢69xxxx天美 | 一本视频在线观看 | 国产精品一品二区三区四区18 | 亚洲天堂在线电影 | 国内精品久久久久久影视8 嫩草影院在线观看网站成人 | 污污网站入口 | 日本韩国欧美一级片 |