Java修改Integer變量值遇到的問題及解決
Java 修改Integer變量值
對(duì)于Integer變量來說,比較變量值常見情形如下:
Integer a = 1000; Integer b = 1000; Integer c = 100; Integer d = 100; System.out.println(a == b); System.out.println(c == d);
“==”比較的是地址的值,所以正確答案是false,true;
當(dāng)我們對(duì)一個(gè)Interger變量直接用“=”號(hào)賦值時(shí),相當(dāng)于自動(dòng)裝箱,即把右邊的int型變量(整數(shù)時(shí)默認(rèn)是int) 轉(zhuǎn)換成Integer變量,另外我們看看源碼
/** * Returns an {@code Integer} instance representing the specified * {@code int} value. If a new {@code Integer} instance is not * required, this method should generally be used in preference to * the constructor {@link #Integer(int)}, as this method is likely * to yield significantly better space and time performance by * caching frequently requested values. * * This method will always cache values in the range -128 to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) //當(dāng)為-128和127之間時(shí),并沒有new一個(gè)Integer,而是從緩存中取 return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
所以說如果int的值為-128到127時(shí),是從常量池里取的Integer變量,所以“c==d”是對(duì)的,因?yàn)閏、d是100
而“a==b”為false,因?yàn)樗麄兊闹禐?000,所以是在堆里new出兩個(gè)不同的變量。
這些都很好理解,但是怎么改變Integer的整型值呢?
我嘗試了兩種方法去改變Integer的整型值
(1)
有這么一個(gè)方法
public void ceshi(Integer integer){ integer=4444; }
main方法
Integer shuzi=new Integer(100); new Test55().ceshi(shuzi); System.out.println(shuzi);
輸出的結(jié)果卻還是100而不是444
再來看看
(2)
main方法
Integer shuzi=new Integer(100); shuzi=5000; System.out.println(shuzi);
這回輸出的結(jié)果卻又是5000,為什么(1)和(2)都用了“=”號(hào)賦值,一個(gè)成功,一個(gè)卻失敗了?
看看源碼
Integer的源碼:
/** * The value of the {@code Integer}. * * @serial */ private final int value;
Integer變量里的value明明就是final變量,照理說是不能夠修改的,那為什么(2)卻成功了?
因?yàn)椋涸冢?)的這個(gè)情況里,我對(duì)它賦值5000,相當(dāng)于new了一個(gè)新的Integer變量,它的value值是5000,然后把這個(gè)新的變量賦給“shuzi”這個(gè)變量,原來那個(gè)value值為100的Integer變量就被覆蓋了,除非我用一個(gè)副本保存,不然他就會(huì)被GC清除了。
還有一個(gè)問題:那為什么(1)改變不了?
因?yàn)椋何覀兿纫?,Java 只有值傳遞,只不過值傳遞分為:內(nèi)存中數(shù)值的值傳遞以及內(nèi)存地址數(shù)值的值傳遞,傳遞一個(gè)Integer變量參數(shù)進(jìn)去,實(shí)際上是構(gòu)建了一個(gè)副本,通過這個(gè)副本我們只能去修改原來Integer變量的非final成員變量(假如有的話,也可以是其他類型),上面也說了,如果去修改Integer類型的final變量,那么是會(huì)新new一個(gè)Integer變量,去覆蓋這個(gè)變量副本,所以原來的Integer變量還是原來的,僅僅是“ceshi”這個(gè)方法里的副本變量變了,這么理解就清楚了。
Integer值比較需要注意的問題
package com.com.test; /** * Created by ***** 2018/6/29 9:18 * java中Integer類型對(duì)于-128-127之間的數(shù)是緩沖區(qū)取的, * 所以用等號(hào)比較是一致的。但對(duì)于不在這區(qū)間的數(shù)字是在堆中new出來的。所以地址空間不一樣,也就不相等。 */ public class IntegerTest { public static void main(String[] args) { Integer a1 = Integer.valueOf(60); //danielinbiti Integer b1 = 60; System.out.println("1:="+(a1 == b1)); //true Integer a2 = 60; Integer b2 = 60; System.out.println("2:="+(a2 == b2)); //true Integer a3 = new Integer(60); Integer b3 = 60; // 裝箱過程也就是Integer b3=Integer.valueOf(60) System.out.println("3:="+(a3 == b3)); //false // System.out.println("3:="+(a3.equals(b3))); //true Integer a4 = 129;//大于127時(shí),在堆中新建 Integer b4 = 129; System.out.println("4:="+(a4 == b4)); //false // System.out.println("4:="+(a4.equals(b4))); //true } }
代碼如上所示,運(yùn)行結(jié)果在注釋后。
原因
java中Integer類型對(duì)于-128-127之間的數(shù)是緩沖區(qū)取的,所以用等號(hào)比較是一致的。但對(duì)于不在這區(qū)間的數(shù)字是在堆中new出來的。所以地址空間不一樣,也就不相等。
Integer b3=60,這是一個(gè)裝箱過程也就是Integer b3=Integer.valueOf(60)
解決辦法
使用 equals 代替 “==“,即是前者可能在性能上稍遜于后者,但是用后者的話存在bug的可能性。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 淺談Java中Int、Integer、Integer.valueOf()、new Integer()之間的區(qū)別
- Java 如何判斷Integer類型的值是否相等
- Java Integer對(duì)象的比較方式
- JAVA基本類型包裝類 BigDecimal BigInteger 的使用
- Java 處理超大數(shù)類型之BigInteger案例詳解
- 詳談java中int和Integer的區(qū)別及自動(dòng)裝箱和自動(dòng)拆箱
- 聊聊Java BigInteger里面的mod和remainder的區(qū)別
- 你知道在Java中Integer和int的這些區(qū)別嗎?
- 詳解Java中包裝類Integer的使用
- Java中int和Integer的區(qū)別
相關(guān)文章
springboot2.5.2與 flowable6.6.0整合流程引擎應(yīng)用分析
這篇文章主要介紹了springboot2.5.2與 flowable6.6.0整合流程引擎應(yīng)用分析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07java:程序包javax.servlet.http不存在問題解決
這篇文章主要給大家介紹了關(guān)于java:程序包javax.servlet.http不存在問題解決的相關(guān)資料,如果引用的包依賴的庫文件缺失或版本不匹配,就會(huì)導(dǎo)致"Java 程序包不存在"的錯(cuò)誤,需要的朋友可以參考下2023-10-10springboot openfeign從JSON文件讀取數(shù)據(jù)問題
今天主要說一下在openfeign里讀取JSON文件的問題,我們將測(cè)試所需要的數(shù)據(jù)存儲(chǔ)到文件里,在修改時(shí)關(guān)注點(diǎn)比較單純2018-06-06詳解Mybatis極其(最)簡(jiǎn)(好)單(用)的一個(gè)分頁插件
這篇文章主要介紹了詳解Mybatis極其(最)簡(jiǎn)(好)單(用)的一個(gè)分頁插件,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12Java中的FileInputStream 和 FileOutputStream 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
FileInputStream 是文件輸入流,它繼承于InputStream。FileOutputStream 是文件輸出流,它繼承于OutputStream。接下來通過本文給大家介紹Java中的FileInputStream 和 FileOutputStream,需要的朋友可以參考下2017-05-05java之lombok的構(gòu)建者模式Builder中的泛型寫法說明
這篇文章主要介紹了java之lombok的構(gòu)建者模式Builder中的泛型寫法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01SpringBoot集成tika實(shí)現(xiàn)word轉(zhuǎn)html的操作代碼
Tika是一個(gè)內(nèi)容分析工具,自帶全面的parser工具類,能解析基本所有常見格式的文件,得到文件的metadata,content等內(nèi)容,返回格式化信息,本文給大家介紹了SpringBoot集成tika實(shí)現(xiàn)word轉(zhuǎn)html的操作,需要的朋友可以參考下2024-06-06Java實(shí)現(xiàn)十進(jìn)制與二進(jìn)制互轉(zhuǎn)的示例詳解
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)十進(jìn)制與二進(jìn)制的互轉(zhuǎn),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下2022-11-11如何使用IDEA創(chuàng)建MAPPER模板過程圖解
這篇文章主要介紹了如何使用IDEA創(chuàng)建MAPPER模板,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05