一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - 詳解JAVA 常量池

詳解JAVA 常量池

2020-07-14 18:05團隊buff工具人 JAVA教程

這篇文章主要介紹了JAVA 常量池的相關資料,文中講解非常詳細,示例代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下

前言

常量池的理解之前,需要熟悉的是一些術語:

字面量

在計算機科學中,字面量(literal)是用于表達源代碼中一個固定值的表示法(notation)。
幾乎所有計算機編程語言都具有對基本值的字面量表示,諸如:整數、浮點數以及字符串;而有很多也對布爾類型和字符類型的值也支持字面量表示;
還有一些甚至對枚舉類型的元素以及像數組、記錄和對象等復合類型的值也支持字面量表示法。C語言關于復合字面量的介紹可參考: [1]  。

百度也給了一個例子:

這個object-c 的例子,容易理解。

?
1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(void)
{
 int a = 10; // 10為int類型字面量
 char a[] = {"Hello world!"} // Hello world 為字符串形式字面量
  .............
 // 以此類推,不再贅述
 return 0;
}

正文

JVM常量池主要分為Class文件常量池、運行時常量池,全局字符串常量池,以及基本類型包裝類對象常量池。

我在網上找了一個例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
private int value = 1;
public String s = "abc";
public final static int f = 0x101;
public static void main(String[] args)
{
}
public void setValue(int v){
    final int temp = 3;
    this.value = temp + v;
}
public int getValue(){
    return value;
}

編譯后:

下面只截取了一部分,常量池:

?
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
44
45
46
public class test.program
 minor version: 0
 major version: 57
 flags: (0x0021) ACC_PUBLIC, ACC_SUPER
 this_class: #1       // test/program
 super_class: #3       // java/lang/Object
 interfaces: 0, fields: 3, methods: 4, attributes: 1
Constant pool:
 #1 = Class    #2    // test/program
 #2 = Utf8    test/program
 #3 = Class    #4    // java/lang/Object
 #4 = Utf8    java/lang/Object
 #5 = Utf8    value
 #6 = Utf8    I
 #7 = Utf8    s
 #8 = Utf8    Ljava/lang/String;
 #9 = Utf8    f
 #10 = Utf8    ConstantValue
 #11 = Integer   257
 #12 = Utf8    <init>
 #13 = Utf8    ()V
 #14 = Utf8    Code
 #15 = Methodref   #3.#16   // java/lang/Object."<init>":()V
 #16 = NameAndType  #12:#13  // "<init>":()V
 #17 = Fieldref   #1.#18   // test/program.value:I
 #18 = NameAndType  #5:#6   // value:I
 #19 = String    #20   // abc
 #20 = Utf8    abc
 #21 = Fieldref   #1.#22   // test/program.s:Ljava/lang/String;
 #22 = NameAndType  #7:#8   // s:Ljava/lang/String;
 #23 = Utf8    LineNumberTable
 #24 = Utf8    LocalVariableTable
 #25 = Utf8    this
 #26 = Utf8    Ltest/program;
 #27 = Utf8    main
 #28 = Utf8    ([Ljava/lang/String;)V
 #29 = Utf8    args
 #30 = Utf8    [Ljava/lang/String;
 #31 = Utf8    setValue
 #32 = Utf8    (I)V
 #33 = Utf8    v
 #34 = Utf8    temp
 #35 = Utf8    getValue
 #36 = Utf8    ()I
 #37 = Utf8    SourceFile
 #38 = Utf8    program.java

好的下面介紹class 常量池;

class 常量池

主要包括:字面量和符號引用

首先字面量不是全部的字面量,如果不明白什么是字面值請看上面;

字符字面值:

#7 = Utf8               s
#20 = Utf8               abc

用final修飾的成員變量

#9 = Utf8               f
#11 = Integer            257

大概包含的就是這兩種。

符號引用

符號引用主要設涉及編譯原理方面的概念,包括下面三類常量:

類和接口的全限定名,也就是java/lang/String;這樣,將類名中原來的"."替換為"/"得到的,主要用于在運行時解析得到類的直接引用,像上面

#5 = Class              #33            // JavaBasicKnowledge/JavaBean
#33 = Utf8               JavaBasicKnowledge/JavaBean

字段的名稱和描述符,字段也就是類或者接口中聲明的變量,包括類級別變量和實例級的變量

#4 = Fieldref           #5.#32         // JavaBasicKnowledge/JavaBean.value:I
#5 = Class              #33            // JavaBasicKnowledge/JavaBean
#32 = NameAndType       #7:#8          // value:I

#7 = Utf8               value
#8 = Utf8               I

//這兩個是局部變量,值保留字段名稱
#23 = Utf8               v
#24 = Utf8               temp

可以看到,對于方法中的局部變量名,class文件的常量池僅僅保存字段名。

方法中的名稱和描述符,也即參數類型+返回值

 #21 = Utf8               setValue
 #22 = Utf8               (I)V

 #25 = Utf8               getValue
 #26 = Utf8               ()I

其實并不需要怎么關注符號引用。

那么這些class 常量池有什么好處呢?

運行時常量池是方法區的一部分,所以也是全局貢獻的,我們知道,jvm在執行某個類的時候,必須經過加載、鏈接(驗證、準備、解析)、初始化,在第一步加載的時候需要完成:

通過一個類的全限定名來獲取此類的二進制字節流

將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構

在內存中生成一個類對象,代表加載的這個類,這個對象是java.lang.Class,它作為方法區這個類的各種數據訪問的入口。

類對象和普通對象是不同的,類對象是在類加載的時候完成的,是jvm創建的并且是單例的,作為這個類和外界交互的入口, 而普通的對象一般是在調用new之后創建。

上面的第二條,將class字節流代表的靜態存儲結構轉化為方法區的運行時數據結構,其中就包含了class文件常量池進入運行時常量池的過程,這里需要強調一下不同的類共用一個運行時常量池,同時在進入運行時常量池的過程中,多個class文件中常量池相同的字符串,多個class文件中常量池中相同的字符串只會存在一份在運行時常量池,這也是一種優化。

運行時常量池的作用是存儲java class文件常量池中的符號信息,運行時常量池中保存著一些class文件中描述的符號引用,同時在類的解析階段還會將這些符號引用翻譯出直接引用(直接指向實例對象的指針,內存地址),翻譯出來的直接引用也是存儲在運行時常量池中。

運行時常量池相對于class常量池一大特征就是具有動態性,java規范并不要求常量只能在運行時才產生,也就是說運行時常量池的內容并不全部來自class常量池,在運行時可以通過代碼生成常量并將其放入運行時常量池中,這種特性被用的最多的就是String.intern()。

那么就看下String.intern() 來理解:運行時常量池。

首先看下:

string x="x" 和 String x=new String("x");

有什么區別?

可以肯定的是他們的值是一樣的。

但是他們運行差別很大。string x="x" 會查找常量池,如果沒有x的話,那么會存入常量池,如果有的話,那么會存在于常量池并進行引用。

而 String x=new String("x") 則只會生成在堆中,而不會和常量池產生聯系。

注:

常量字符串和變量拼接時(如:String str3=baseStr + “01”;)會調用stringBuilder.append()在堆上創建新的對象。

那么String.intern() 是什么意思呢?這個是會去查找變量詞中有沒有,如果有的話那么會返回引用,如果沒有的話,這個和版本有關。

詳解JAVA 常量池

題目

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
// write your code here
    Integer i01=59;
    int i02=59;
    Integer i03=Integer.valueOf(59);
    Integer i04= new Integer(59);
}
 
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

問題如下:

i01 是否和 i02 相等?

i03 是否和 i01 相等。

i04 是否和 i01相等。

總結

寫的比較倉促,后續會完善好。

以上就是詳解JAVA 常量池的詳細內容,更多關于java 常量池的資料請關注服務器之家其它相關文章!

原文鏈接:https://www.cnblogs.com/aoximin/p/12824458.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 人妖巨茎video | 亚洲国产精品综合一区在线 | 日韩精品免费一区二区三区 | 亚洲国产AV无码综合在线 | 69日本xxxhd | 成人另类视频 | 99国产小视频 | 亚洲AV永久无码精品澳门 | 欧美一级专区免费大片 | 青草青草伊人精品视频 | 国产精品午夜剧场 | 亚洲女bbwxxxx另类 | 午夜福到在线4国产 | 亚洲va在线va天堂va偷拍 | 青丝视频免费版在线看 | 色综合九九 | 青草网在线观看 | 日韩一区二区中文字幕 | 91看片淫黄大片.在线天堂 | 羞羞影院午夜男女爽爽影院网站 | 99热影视| 精品一区二区三区中文 | 99在线免费视频 | 美女视频ww8888网网 | 亚洲久草 | 日本护士xxxx爽爽爽 | 91.prom在线观看国产 | 免费看a视频 | 99热这里只有精品在线 | 精品久久香蕉国产线看观看亚洲 | 99在线播放 | 亚洲国产精品一在线观看 | 日本在线www | 亚洲精品一二三四区 | 免费永久观看美女视频网站网址 | 陈峰姚瑶全集小说无删节 | 黄+色+性+人免费 | 成人在线免费看 | 久久er国产免费精品 | 毛片免费观看 | 久久久久久久久人体 |