Java常量池理解與總結

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

一.相關概念


  1. 什么是常量
  2. 用final修飾的成員變量表示常量,值一旦給定就無法改變!
  3. final修飾的變量有三種:靜態變量、實例變量和局部變量,分別表示三種類型的常量。
  4. Class文件中的常量池
  5. 在Class文件結構中,最頭的4個字節用于存儲魔數Magic Number,用于確定一個文件是否能被JVM接受,再接著4個字節用于存儲版本號,前2個字節存儲次版本號,后2個存儲主版本號,再接著是用于存放常量的常量池,由于常量的數量是不固定的,所以常量池的入口放置一個U2類型的數據(constant_pool_count)存儲常量池容量計數值。
  6. 常量池主要用于存放兩大類常量:字面量(Literal)和符號引用量(Symbolic References),字面量相當于Java語言層面常量的概念,如文本字符串,聲明為final的常量值等,符號引用則屬于編譯原理方面的概念,包括了如下三種類型的常量:
  • 類和接口的全限定名
  • 字段名稱和描述符
  • 方法名稱和描述符
  1. 方法區中的運行時常量池
  2. 運行時常量池是方法區的一部分。
  3. CLass文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池,用于存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載后進入方法區的運行時常量池中存放。
  4. 運行時常量池相對于CLass文件常量池的另外一個重要特征是具備動態性,Java語言并不要求常量一定只有編譯期才能產生,也就是并非預置入CLass文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用比較多的就是String類的intern()方法。
  5. 常量池的好處
  6. 如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:787707172,群里有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。
  7. 常量池是為了避免頻繁的創建和銷毀對象而影響系統性能,其實現了對象的共享。
  8. 例如字符串常量池,在編譯階段就把所有的字符串文字放到一個常量池中。
  9. (1)節省內存空間:常量池中所有相同的字符串常量被合并,只占用一個空間。
  10. (2)節省運行時間:比較字符串時,==比equals()快。對于兩個引用變量,只用==判斷引用是否相等,也就可以判斷實際值是否相等。
  11. 雙等號==的含義
  12. 基本數據類型之間應用雙等號,比較的是他們的數值。
  13. 復合數據類型(類)之間應用雙等號,比較的是他們在內存中的存放地址。

二.8種基本類型的包裝類和常量池


  1. java中基本類型的包裝類的大部分都實現了常量池技術,
  2. 即Byte,Short,Integer,Long,Character,Boolean;
Integer i1 = 40;Integer i2 = 40;System.out.println(i1==i2);//輸出TRUE

這5種包裝類默認創建了數值[-128,127]的相應類型的緩存數據,但是超出此范圍仍然會去創建新的對象。

//Integer 緩存代碼 :
public static Integer valueOf(int i) {assert IntegerCache.high >= 127;if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}Integer i1 = 400;Integer i2 = 400;System.out.println(i1==i2);//輸出false
  1. 兩種浮點數類型的包裝類Float,Double并沒有實現常量池技術。
Double i1=1.2;Double i2=1.2;System.out.println(i1==i2);//輸出false
  1. 應用常量池的場景
  2. (1)Integer i1=40;Java在編譯的時候會直接將代碼封裝成Integer i1=Integer.valueOf(40);,從而使用常量池中的對象。
  3. (2)Integer i1 = new Integer(40);這種情況下會創建新的對象。
Integer i1 = 40;Integer i2 = new Integer(40);System.out.println(i1==i2);//輸出false
  1. Integer比較更豐富的一個例子
Integer i1 = 40;Integer i2 = 40;Integer i3 = 0;Integer i4 = new Integer(40);Integer i5 = new Integer(40);Integer i6 = new Integer(0);System.out.println("i1=i2 " + (i1 == i2));System.out.println("i1=i2+i3 " + (i1 == i2 + i3));System.out.println("i1=i4 " + (i1 == i4));System.out.println("i4=i5 " + (i4 == i5));System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); System.out.println("40=i5+i6 " + (40 == i5 + i6)); 
i1=i2 true
i1=i2+i3 true
i1=i4 false
i4=i5 false
i4=i5+i6 true
40=i5+i6 true

解釋:語句i4 == i5 + i6,因為+這個操作符不適用于Integer對象,首先i5和i6進行自動拆箱操作,進行數值相加,即i4 == 40。然后Integer對象無法與數值進行直接比較,所以i4自動拆箱轉為int值40,最終這條語句轉為40 == 40進行數值比較。

Java中的自動裝箱與拆箱

三.String類和常量池


  1. String對象創建方式
String str1 = "abcd";String str2 = new String("abcd");System.out.println(str1==str2);//false

這兩種不同的創建方法是有差別的,第一種方式是在常量池中拿對象,第二種方式是直接在堆內存空間創建一個新的對象。

只要使用new方法,便需要創建新的對象。

  1. 連接表達式 +
  2. 如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:787707172,群里有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。
  3. (1)只有使用引號包含文本的方式創建的String對象之間使用“+”連接產生的新對象才會被加入字符串池中。
  4. (2)對于所有包含new方式新建對象(包括null)的“+”連接表達式,它所產生的新對象都不會被加入字符串池中。
String str1 = "str";String str2 = "ing";String str3 = "str" + "ing";String str4 = str1 + str2;System.out.println(str3 == str4);//falseString str5 = "string";System.out.println(str3 == str5);//true

java基礎:字符串的拼接

  • 特例1
public static final String A = "ab"; // 常量A
public static final String B = "cd"; // 常量B
public static void main(String[] args) {String s = A + B; // 將兩個常量用+連接對s進行初始化 String t = "abcd"; if (s == t) { System.out.println("s等于t,它們是同一個對象"); } else { System.out.println("s不等于t,它們不是同一個對象"); } } 
s等于t,它們是同一個對象

A和B都是常量,值是固定的,因此s的值也是固定的,它在類被編譯時就已經確定了。也就是說:String s=A+B; 等同于:String s="ab"+"cd";

  • 特例2
public static final String A; // 常量A
public static final String B; // 常量B
static { A = "ab"; B = "cd"; } public static void main(String[] args) { // 將兩個常量用+連接對s進行初始化 String s = A + B; String t = "abcd"; if (s == t) { System.out.println("s等于t,它們是同一個對象"); } else { System.out.println("s不等于t,它們不是同一個對象"); } } 
s不等于t,它們不是同一個對象

A和B雖然被定義為常量,但是它們都沒有馬上被賦值。在運算出s的值之前,他們何時被賦值,以及被賦予什么樣的值,都是個變數。因此A和B在被賦值之前,性質類似于一個變量。那么s就不能在編譯期被確定,而只能在運行時被創建了。

  1. String s1 = new String("xyz"); **創建了幾個對象? **
  2. 考慮類加載階段和實際執行時。
  3. (1)類加載對一個類只會進行一次。"xyz"在類加載時就已經創建并駐留了(如果該類被加載之前已經有"xyz"字符串被駐留過則不需要重復創建用于駐留的"xyz"實例)。駐留的字符串是放在全局共享的字符串常量池中的。
  4. (2)在這段代碼后續被運行的時候,"xyz"字面量對應的String實例已經固定了,不會再被重復創建。所以這段代碼將常量池中的對象復制一份放到heap中,并且把heap中的這個對象的引用交給s1 持有。
  5. 這條語句創建了2個對象。
  6. java.lang.String.intern()
  7. 運行時常量池相對于CLass文件常量池的另外一個重要特征是具備動態性,Java語言并不要求常量一定只有編譯期才能產生,也就是并非預置入CLass文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用比較多的就是String類的intern()方法。
  8. String的intern()方法會查找在常量池中是否存在一份equal相等的字符串,如果有則返回該字符串的引用,如果沒有則添加自己的字符串進入常量池。
public static void main(String[] args) { String s1 = new String("計算機");String s2 = s1.intern();String s3 = "計算機";System.out.println("s1 == s2? " + (s1 == s2));System.out.println("s3 == s2? " + (s3 == s2));}
s1 == s2? false
s3 == s2? true
  1. 字符串比較更豐富的一個例子
public class Test {public static void main(String[] args) { String hello = "Hello", lo = "lo";System.out.println((hello == "Hello") + " ");System.out.println((Other.hello == hello) + " ");System.out.println((other.Other.hello == hello) + " ");System.out.println((hello == ("Hel"+"lo")) + " ");System.out.println((hello == ("Hel"+lo)) + " ");System.out.println(hello == ("Hel"+lo).intern());} 
}
class Other { static String hello = "Hello"; }
package other;
public class Other { public static String hello = "Hello"; }
true true true true false true```
在同包同類下,引用自同一String對象.
在同包不同類下,引用自同一String對象.
在不同包不同類下,依然引用自同一String對象.
在編譯成.class時能夠識別為同一字符串的,自動優化成常量,引用自同一String對象.
在運行時創建的字符串具有獨立的內存地址,所以不引用自同一String對象.

如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:787707172,群里有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

?

轉載于:https://my.oschina.net/u/3990817/blog/3029815

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252023.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252023.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252023.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

轉載:https://blog.csdn.net/dcrmg/article/details/52939318

張正友相機標定Opencv實現以及標定流程&&標定結果評價&&圖像矯正流程解析&#xff08;附標定程序和棋盤圖&#xff09;使用Opencv實現張正友法相機標定之前&#xff0c;有幾個問題事先要確認一下&#xff0c;那就是相機為什么需要標定&#xff0c;標定需要的輸…

Redis學習筆記--Redis數據過期策略詳解==轉

本文對Redis的過期機制簡單的講解一下  講解之前我們先拋出一個問題&#xff0c;我們知道很多時候服務器經常會用到redis作為緩存&#xff0c;有很多數據都是臨時緩存一下&#xff0c;可能用過之后很久都不會再用到了&#xff08;比如暫存session&#xff0c;又或者只存放日行…

會員連鎖配置以及金額走向

PS&#xff1a;所有電子支付方式的資金走向都是同樣的&#xff0c;配置的是什么支付方式就走什么支付方式;下面以支付寶為例說明 一、連鎖非總機模式 資金走向&#xff1a; 支付寶&#xff1a;收到的錢在主賬號配置的支付寶&#xff0c;會員卡的金額在主賬號 微信&#xff1a;收…

Python標準模塊--logging

Python標準模塊--logging參考http://www.cnblogs.com/zhbzz2007/p/5943685.html1 logging模塊簡介logging模塊是Python內置的標準模塊&#xff0c;主要用于輸出運行日志&#xff0c;可以設置輸出日志的等級、日志保存路徑、日志文件回滾等&#xff1b;相比print&#xff0c;具備…

Podfile grammar

參考&#xff1a;http://www.jianshu.com/p/8af475c4f717 Podfile Podfile文件詳細描述了一個或多個工程中targets的依賴關系。Podfile會默認創建一個隱式的目標鏈接到工程中用戶的第一個target&#xff0c;名稱為“default”。 一個Podfile可以非常簡單: *pod AFNetworking, ~…

并發編程 - 協程 - 1.協程概念/2.greenlet模塊/3.gevent模塊/4.gevent實現并發的套接字通信...

1.協程并發&#xff1a;切保存狀態單線程下實現并發&#xff1a;協程 切 保存狀態 yield 遇到io切&#xff0c;提高效率 遇到計算切&#xff0c;并沒有提高效率 檢測單線程下 IO行為 io阻塞 切 相當于騙操作系統 一直處于計算協程&#xff1a;。。。單線程下實現…

pymysql

連接數據庫 連接時需要額外指定參數dbcursor.execute( ) 操作SQL語句SELECT VERSION() 獲得當前版本CREATE DATABASE spiders DEFAULT CHARACTER SET utf8 創建數據庫import pymysql db pymysql.connect(hostlocalhost,user ,password ,port3306)#IP&#xff0c;用戶名&#x…

C# 多線程及同步簡介示例

60年代&#xff0c;在OS中能擁有資源和獨立運行的基本單位是進程&#xff0c;然而隨著計算機技術的發展&#xff0c;進程出現了很多弊端&#xff0c;一是由于進程是資源擁有者&#xff0c;創建、撤消與切換存在較大的時空開銷&#xff0c;因此需要引入輕型進程&#xff1b;二是…

opencv-python單目視覺標定,簡單易用。

import cv2 import numpy as np import glob# 設置尋找亞像素角點的參數&#xff0c;采用的停止準則是最大循環次數30和最大誤差容限0.001 criteria (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)# 獲取標定板角點的位置 objp np.zeros((6 * 7, 3), np.f…

python多線程多進程

一、線程&進程 對于操作系統來說&#xff0c;一個任務就是一個進程&#xff08;Process&#xff09;&#xff0c;比如打開一個瀏覽器就是啟動一個瀏覽器進程&#xff0c;打開一個記事本就啟動了一個記事本進程&#xff0c;打開兩個記事本就啟動了兩個記事本進程&#xff0c…

Spring Framework 5.1.6、5.0.13 與?4.3.23 發布

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; Spring Framework 5.1.6、5.0.13 與 4.3.23 發布了。 v5.1.6 包含 49 個 bug 修復和功能改進&#xff1b;v5.0.13 是 5.0.x 系列的最后一個版本&#xff0c;包含了 25 個 bug 修復和功能改進&am…

curl命令

Curl是一種支持多種協議&#xff08;http、https&#xff0c;ftp&#xff09;等&#xff0c;利用url規則在命令行下工作的文件傳輸工具&#xff0c;還支持POST、cookies、認證、從指定偏移處下載部分文件、用戶代理字符串、限速、文件大小、進度條等特征 1.語法&#xff1a; cu…

單目視覺標定:世界坐標系、相機坐標系、圖像坐標系、像素坐標系——簡單粗暴,粗暴

轉&#xff1a;https://blog.csdn.net/chentravelling/article/details/53558096 1.正文 圖像處理、立體視覺等等方向常常涉及到四個坐標系&#xff1a;世界坐標系、相機坐標系、圖像坐標系、像素坐標系。例如下圖&#xff1a; 構建世界坐標系只是為了更好的描述相機的位置在哪…

Python基礎知識-05-數據類型總結字典

python其他知識目錄 1、一道題&#xff0c;選擇商品的序號。程序員和用戶各自面對的序號起始值 如有變量 googs [汽車,飛機,火箭] 提示用戶可供選擇的商品&#xff1a; 0,汽車1,飛機2,火箭用戶輸入索引后&#xff0c;將指定商品的內容拼接打印&#xff0c;如&#xff1a;用戶輸…

Python學習筆記之異常

Python用異常對象來表示異常情況&#xff0c;如果異常對象未被處理或捕捉&#xff0c;程序就會回溯&#xff08;traceback&#xff09;中止執行。 異常可以在出錯時自動引發&#xff0c;也可以主動引發。 異常被引發后如果不被處理就會傳播至程序調用的地方&#xff0c;直到主程…

VSFTP的使用

一、基本安裝 1.安裝服務 yum -y install vsftpd //centos Redhat apt-get install vsftpd //debian ubuntu 2.開啟服務 service vsftpd status //查看狀態&#xff0c;默認是關閉的 service vsftpd start 3.開機隨操作系統啟動 chkconfig vsftpd on4.添加賬號 useradd -d /…

OC Swift混編-Swift.h File not found

https://www.jianshu.com/p/f860fe1718ca 2016.09.13 11:53* 字數 266 閱讀 1935評論 1喜歡 1今天碰到個神坑,本人項目是OC項目,最近開始使用Swift開始替代.但是,在替代的已開始就出現問題了:新建swift文件,然后提示創建bridging-Hearder文件,然后swift可以使用OC代碼了.這些都…

視覺標定,再來一波!!更簡單粗暴!!!!!!

繼續&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 一、四個坐標系簡介和轉換 相機模型為以后一切標定算法的關鍵&#xff0c;只有這邊有相當透徹的理解&#xff0c;對以后的標定算法才能有更好的理解。本人研究了好長時間&#xff0c;幾乎每天…

深入淺出NIO之Selector實現原理

2019獨角獸企業重金招聘Python工程師標準>>> 前言 Java NIO 由以下幾個核心部分組成&#xff1a; 1、Buffer 2、Channel 3、Selector Buffer和Channel在深入淺出NIO之Channel、Buffer一文中已經介紹過&#xff0c;本文主要講解NIO的Selector實現原理。 之前進行sock…

介紹一下畫圖小能手matplotlib。

我們在做完數據分析的時候需要把分析出來的結果&#xff0c;做一個圖形化的形象表達&#xff0c;這里我們就需要用到畫圖小能手matplotlib&#xff0c;下面就演示一下常用的條形圖和折線圖 散點圖 散點圖的做大的作用是研究兩個變量的相關性&#xff08;正相關&#xff0c;負相…