java裝箱,java裝箱問題 遺傳演算法

本文目錄一覽:

java 為什麼要有裝箱和拆箱?

把一個基本類型包裝成一個類,一個是可以使這個類型具有很多可以調用的方法。二個是Java向面像對象語言的靠近。其實Java還不算是很純的面向對象的語言。真正的面向對象,是沒有基本數據類型的。它只有一種類型,就是對象。三個是在泛型中,基本類型是不可以做泛型參數的。如:List int list = new ArrayListint ();這是不合法的。你只能這個樣寫ListInteger list = new ArrayListInteger ();也就是要用int型的包裝類類型來解決基本類型不可以做泛型參數的問題 。

一名話,包裝類有更多的方法和用途, 而這是基本類型沒有的!!!

java 什麼是拆箱和裝箱,拆箱和裝箱 嘛用啊???

詳解Java的自動裝箱與拆箱(Autoboxing and unboxing)

一、什麼是自動裝箱拆箱 

很簡單,下面兩句代碼就可以看到裝箱和拆箱過程

//自動裝箱

Integer total = 99;

//自定拆箱

int totalprim = total;

簡單一點說,裝箱就是自動將基本數據類型轉換為包裝器類型;拆箱就是自動將包裝器類型轉換為基本數據類型。

下面我們來看看需要裝箱拆箱的類型有哪些:

這個過程是自動執行的,那麼我們需要看看它的執行過程:

public class Main {

    public static void main(String[] args) {

    //自動裝箱

    Integer total = 99;

    //自定拆箱

    int totalprim = total;

    }

}

反編譯class文件之後得到如下內容:

javap -c StringTest

Integer total = 99; 

執行上面那句代碼的時候,系統為我們執行了: 

Integer total = Integer.valueOf(99);

int totalprim = total; 

執行上面那句代碼的時候,系統為我們執行了: 

int totalprim = total.intValue();

我們現在就以Integer為例,來分析一下它的源碼: 

1、首先來看看Integer.valueOf函數

public static Integer valueOf(int i) {

    return  i = 128 || i  -128 ? new Integer(i) : SMALL_VALUES[i + 128];

}

它會首先判斷i的大小:如果i小於-128或者大於等於128,就創建一個Integer對象,否則執行SMALL_VALUES[i + 128]。

首先我們來看看Integer的構造函數:

private final int value;

public Integer(int value) {

    this.value = value;

}

public Integer(String string) throws NumberFormatException {

    this(parseInt(string));

}

它裡面定義了一個value變數,創建一個Integer對象,就會給這個變數初始化。第二個傳入的是一個String變數,它會先把它轉換成一個int值,然後進行初始化。

下面看看SMALL_VALUES[i + 128]是什麼東西:

private static final Integer[] SMALL_VALUES = new Integer[256];

它是一個靜態的Integer數組對象,也就是說最終valueOf返回的都是一個Integer對象。

所以我們這裡可以總結一點:裝箱的過程會創建對應的對象,這個會消耗內存,所以裝箱的過程會增加內存的消耗,影響性能。

2、接著看看intValue函數

@Override

public int intValue() {

    return value;

}

這個很簡單,直接返回value值即可。

二、相關問題 

上面我們看到在Integer的構造函數中,它分兩種情況: 

1、i = 128 || i -128 ===== new Integer(i) 

2、i 128 i = -128 ===== SMALL_VALUES[i + 128]

private static final Integer[] SMALL_VALUES = new Integer[256];

SMALL_VALUES本來已經被創建好,也就是說在i = 128 || i -128是會創建不同的對象,在i 128 i = -128會根據i的值返回已經創建好的指定的對象。

說這些可能還不是很明白,下面我們來舉個例子吧:

public class Main {    public static void main(String[] args) {

        Integer i1 = 100;

        Integer i2 = 100;

        Integer i3 = 200;

        Integer i4 = 200;

        System.out.println(i1==i2);  //true

        System.out.println(i3==i4);  //false

    }

}

代碼的後面,我們可以看到它們的執行結果是不一樣的,為什麼,在看看我們上面的說明。 

1、i1和i2會進行自動裝箱,執行了valueOf函數,它們的值在(-128,128]這個範圍內,它們會拿到SMALL_VALUES數組裡面的同一個對象SMALL_VALUES[228],它們引用到了同一個Integer對象,所以它們肯定是相等的。

2、i3和i4也會進行自動裝箱,執行了valueOf函數,它們的值大於128,所以會執行new Integer(200),也就是說它們會分別創建兩個不同的對象,所以它們肯定不等。

下面我們來看看另外一個例子:

public class Main {    public static void main(String[] args) {

        Double i1 = 100.0;

        Double i2 = 100.0;

        Double i3 = 200.0;

        Double i4 = 200.0;

        System.out.println(i1==i2); //false

        System.out.println(i3==i4); //false

    }

}

看看上面的執行結果,跟Integer不一樣,這樣也不必奇怪,因為它們的valueOf實現不一樣,結果肯定不一樣,那為什麼它們不統一一下呢? 

這個很好理解,因為對於Integer,在(-128,128]之間只有固定的256個值,所以為了避免多次創建對象,我們事先就創建好一個大小為256的Integer數組SMALL_VALUES,所以如果值在這個範圍內,就可以直接返回我們事先創建好的對象就可以了。

但是對於Double類型來說,我們就不能這樣做,因為它在這個範圍內個數是無限的。 

總結一句就是:在某個範圍內的整型數值的個數是有限的,而浮點數卻不是。

所以在Double裡面的做法很直接,就是直接創建一個對象,所以每次創建的對象都不一樣。

public static Double valueOf(double d) {

    return new Double(d);

}

下面我們進行一個歸類: 

Integer派別:Integer、Short、Byte、Character、Long這幾個類的valueOf方法的實現是類似的。 

Double派別:Double、Float的valueOf方法的實現是類似的。每次都返回不同的對象。

下面對Integer派別進行一個總結,如下圖:

下面我們來看看另外一種情況:

public class Main {    public static void main(String[] args) {

        Boolean i1 = false;

        Boolean i2 = false;

        Boolean i3 = true;

        Boolean i4 = true;

        System.out.println(i1==i2);//true

        System.out.println(i3==i4);//true

    }

}

可以看到返回的都是true,也就是它們執行valueOf返回的都是相同的對象。

public static Boolean valueOf(boolean b) {

    return b ? Boolean.TRUE : Boolean.FALSE;

}

可以看到它並沒有創建對象,因為在內部已經提前創建好兩個對象,因為它只有兩種情況,這樣也是為了避免重複創建太多的對象。

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

上面把幾種情況都介紹到了,下面來進一步討論其他情況。

Integer num1 = 400;  

int num2 = 400;  

System.out.println(num1 == num2); //true

說明num1 == num2進行了拆箱操作

Integer num1 = 100;  

int num2 = 100;  

System.out.println(num1.equals(num2));  //true

我們先來看看equals源碼:

@Override

public boolean equals(Object o) {

    return (o instanceof Integer)  (((Integer) o).value == value);

}

我們指定equal比較的是內容本身,並且我們也可以看到equal的參數是一個Object對象,我們傳入的是一個int類型,所以首先會進行裝箱,然後比較,之所以返回true,是由於它比較的是對象裡面的value值。

Integer num1 = 100;  

int num2 = 100;  

Long num3 = 200l;  

System.out.println(num1 + num2);  //200

System.out.println(num3 == (num1 + num2));  //true

System.out.println(num3.equals(num1 + num2));  //false

1、當一個基礎數據類型與封裝類進行==、+、-、*、/運算時,會將封裝類進行拆箱,對基礎數據類型進行運算。 

2、對於num3.equals(num1 + num2)為false的原因很簡單,我們還是根據代碼實現來說明:

@Override

public boolean equals(Object o) {

    return (o instanceof Long)  (((Long) o).value == value);

}

它必須滿足兩個條件才為true: 

1、類型相同 

2、內容相同 

上面返回false的原因就是類型不同。

Integer num1 = 100;

Ingeger num2 = 200;

Long num3 = 300l;

System.out.println(num3 == (num1 + num2)); //true

我們來反編譯一些這個class文件:javap -c StringTest 

可以看到運算的時候首先對num3進行拆箱(執行num3的longValue得到基礎類型為long的值300),然後對num1和mum2進行拆箱(分別執行了num1和num2的intValue得到基礎類型為int的值100和200),然後進行相關的基礎運算。

我們來對基礎類型進行一個測試:

int num1 = 100;

int num2 = 200;

long mum3 = 300;

System.out.println(num3 == (num1 + num2)); //true

上面就說明了為什麼最上面會返回true.

所以,當 「==」運算符的兩個操作數都是 包裝器類型的引用,則是比較指向的是否是同一個對象,而如果其中有一個操作數是表達式(即包含算術運算)則比較的是數值(即會觸發自動拆箱的過程)。

通過上面的分析我們需要知道兩點: 

1、什麼時候會引發裝箱和拆箱 

2、裝箱操作會創建對象,頻繁的裝箱操作會消耗許多內存,影響性能,所以可以避免裝箱的時候應該盡量避免。

我有一個微信公眾號,經常會分享一些Java技術相關的乾貨文章,還有一些學習資源。

如果你需要的話,可以用微信搜索「Java團長」或者「javatuanzhang」關注。

java包裝類怎樣理解?裝箱與拆箱又怎樣理解?請通俗的解釋一下,舉個例子也行

Java有一個類型系統有兩個部分組成,包含基本類型(byte、char、int、short、long、float、double、boolean)和引用類型。而基本類型則對應著各自的引用類型,稱為裝箱的基本類型。而引用類型對應著各自的基本類型,稱為拆箱的基本類型。對應的類型為:(Byte、Character、Integer、Short、Long、Float、Double、Boolean)

下面一具體例子來說明裝箱與拆箱

//java 1.5之前創建一個Integer對象Integer i = new Integer(10);//java 1.5之後有了裝箱的特性,直接用下列方式生成一個Integer對象//在這個過程中會將int 類型的10自動裝箱成為Integer類型Integer i = 10;//拆箱 輸出的值為20,這個過程中,會先將Integer類型的j自動拆箱為基本類型的10,最後完成運算Integer j = new Integer(10);int k = 10;

System.out.print(j+k);

java 包裝類 自動裝箱問題

Java包裝類,Wrapper~由於在java中,數據類型總共可分為兩大種,基本數據類型(值類型)和類類型(引用數據類型)。基本類型的數據不是對象,所以對於要將數據類型作為對象來使用的情況,java提供了相對應的包裝類。對於8種數據類型的包裝類分別是:

int—Integer

char—Character

float—Float

double—Double

byte—Byte

short—Short

long—Long

boolean–Boolean

所謂裝箱,就是把基本類型用它們相對應的引用類型包起來,使它們可以具有對象的特質,如我們可以把int型包裝成Integer類的對象,或者把double包裝成Double,等等。

所謂拆箱,就是跟裝箱的方向相反,將Integer及Double這樣的引用類型的對象重新簡化為值類型的數據

J2SE5.0後提供了自動裝箱與拆箱的功能,此功能事實上是編譯器來幫您的忙,編譯器在編譯時期依您所編寫的方法,決定是否進行裝箱或拆箱動作。

自動裝箱的過程:每當需要一種類型的對象時,這種基本類型就自動地封裝到與它相同類型的包裝中。

自動拆箱的過程:每當需要一個值時,被裝箱對象中的值就被自動地提取出來,沒必要再去調用intValue()和doubleValue()方法。

自動裝箱,只需將該值賦給一個類型包裝器引用,java會自動創建一個對象。例如:

Integer i=100; //沒有通過使用new來顯示建立,java自動完成。

自動拆箱,只需將該對象值賦給一個基本類型即可。

例如:

int j=i;

int i = 10;

Integer j =new Integer(i); //手動裝箱操作

int k = j.intValue(); //手動拆箱操作

int i = 11;

Integer j = i; //自動裝箱

int k = j //自動拆箱

什麼是java中的自動裝箱和自動拆箱

java自動裝箱和拆箱

基本數據類型,如int,float,double,boolean,char,byte,不具備對象的特徵,不能調用方法。

裝箱:將基本類型轉換成包裝類對象

int i=10;

Integer x=new Integer(i);手動裝箱

Integer y=10;自動裝箱

拆箱:將包裝類對象轉換成基本類型的值

Integer j=new Integer(8);

int m=j.intValue();//手動拆箱

int n=j;//自動拆箱

java為什麼要引入自動裝箱和拆箱的功能?又是怎麼實現的呢?

主要是用於java集合中,ListInteter list=new ArrayListInteger();

list集合如果要放整數的話,只能放對象,不能放基本類型,因此需要將整數自動裝箱成對象。

實現原理:javac編譯器的語法糖

public class Main {

public static void main(String[] args) {

Integer i1 = 100;

Integer i2 = 100;

Integer i3 = 200;

Integer i4 = 200;

System.out.println(i1==i2);

System.out.println(i3==i4);

}

}

//結果為:true false

在通過Integer.valueOf()方法創建Integer對象的時候,如果數值在[-128,127]之間,便返回指向IntegerCache.cache中已經存在的對象的引用(位於堆對象池中);否則創建一個新的Integer對象(創建在java堆中)。上面的代碼中i1和i2的數值為100,因此會直接從cache中取已經存在的對象,所以i1和i2指向的是同一個對象,而i3和i4則是分別指向不同的對象。

public class Main {

public static void main(String[] args) {

Double i1 = 100.0;

Double i2 = 100.0;

Double i3 = 200.0;

Double i4 = 200.0;

System.out.println(i1==i2);

System.out.println(i3==i4);

}

}

//結果為:false false

為什麼Double類的valueOf方法會採用與Integer類的valueOf方法不同的實現呢?很簡單:在某個範圍內的整型數值的個數是有限的,而浮點數卻不是。

public class Main {

public static void main(String[] args) {

Boolean i1 = false;

Boolean i2 = false;

Boolean i3 = true;

Boolean i4 = true;

System.out.println(i1==i2);

System.out.println(i3==i4);

}

}

//結果為:true true

至於為什麼是這個結果,同樣地,看了Boolean類的源碼也會一目了然。下面是Boolean的valueOf方法的具體實現:

public static Boolean valueOf(boolean b) {

return (b ? TRUE : FALSE);

}

public class H {

public static void main(String[] args) {

Integer m=10;

int n=10;

System.out.println(m==n);

}

}

//結果為:true

原創文章,作者:FFNH,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/145022.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
FFNH的頭像FFNH
上一篇 2024-10-26 11:55
下一篇 2024-10-26 11:55

相關推薦

  • Python官網中文版:解決你的編程問題

    Python是一種高級編程語言,它可以用於Web開發、科學計算、人工智慧等領域。Python官網中文版提供了全面的資源和教程,可以幫助你入門學習和進一步提高編程技能。 一、Pyth…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • 蝴蝶優化演算法Python版

    蝴蝶優化演算法是一種基於仿生學的優化演算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化演算法Python版…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • 如何解決WPS保存提示會導致宏不可用的問題

    如果您使用過WPS,可能會碰到在保存的時候提示「文件中含有宏,保存將導致宏不可用」的問題。這個問題是因為WPS在默認情況下不允許保存帶有宏的文件,為了解決這個問題,本篇文章將從多個…

    編程 2025-04-29
  • Python實現爬樓梯演算法

    本文介紹使用Python實現爬樓梯演算法,該演算法用於計算一個人爬n級樓梯有多少種不同的方法。 有一樓梯,小明可以一次走一步、兩步或三步。請問小明爬上第 n 級樓梯有多少種不同的爬樓梯…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29

發表回復

登錄後才能評論