java 自動裝拆箱


title: “java 自動裝拆箱”
tags:

  • Java

將基本數據類型封裝成對象的過程叫做裝箱(boxing),反之基本數據類型對應的包裝類轉換為基本數據類型的過程叫做拆箱(unboxing);

基本數據類型與其他對象的區別

基本數據類型

Java是一門面向對象的強類型語言,但它又不像python那樣一切皆對象,Java中有一部分使用最頻繁的數據結構并不是面向對象的,他們就是基本數據類型,也叫內置類型,他們在棧中儲存,比起其他用new創建的對象,更加高效,Java有9中基本數據類型,分為五類

類型標識符備注
整型byte, short, int, long
浮點float, dauble
字符char
布爾boolean
void不能操作

基本數據類型的范圍

整型的范圍

  • byte: 占一個字節,也就是8位,最高一位作為符號位,有效位只有7位(采用補碼存儲)。
最大值:0,111 1111(127)
最小值:1,000 0000(-128)

怎么算的?
最高一位是符號位,這是固定的,正數用0表示,負數用1表示,然后后面的七位最大是7個1,最小是7個0,這就是用補碼表示的byte能表示的最大最小數,把補碼轉換為原碼(正數的補碼就是源碼,負數的補碼變源碼取反加一)然后轉換為10進制。

  • short:占兩個字節,16位,有效15位
最大值:2^15 -1: 32,767
最小值:-(2^15): -32,768
  • int: 占4個字節,最大值【2^31 - 1】(2,147,483,647), 最小值【-2^31】(-2,147,483,648)
  • long: 占8字節,最大值【2^63 - 1】(9,223,372,036,854,775,807),最小值【-2^63】(-9,223,372,036,854,775,808)

包裝類型

Java中其他的對象都是繼承自object的,有自己的屬性和方法,為了方便基本基本數據類型和其他對象的的操作,Java為每個基本數據類型提供了對應的包裝類型,

基本數據類型包裝類
byteByte
booleanBoolean
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble
  • 為什么要使用包裝類型

Java是一門面向對象的語言,大部分操作都是針對對象的,比如容器,容器中能存入的最大的范圍就是object,而基本數據類型不屬于對象,那他就無法存入容器,為了解決這個問題,必須把基本數據類型“包裝”起來,讓他作為一個對象參與到編程中。

裝箱和拆箱

把基本數據類型包裝成對象的過程叫做裝箱,反之把對象轉換為基本數據類型的過程叫做拆箱。
Java SE5 后,為了簡化開發,提供了自動裝拆箱機制,Java會在適當時刻自動轉換基本數據類型和包裝類型,如:

public class Demo1 {public static void main(String[] args) {Integer integer = 3; // 自動裝箱int i = integer;  // 自動拆箱}
}

通過Javap反編譯得到

  public static void main(java.lang.String[]);Code:0: iconst_31: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4: astore_15: aload_16: invokevirtual #3                  // Method java/lang/Integer.intValue:()I9: istore_210: return

在自動裝箱時,其實是調用了包裝類的valueOf()方法,而在自動拆箱時則調用了包裝類的intValue()方法,所以如果在JavaSE5之前,沒有自動裝拆箱機制,上面的代碼我們需要這樣寫

public class Demo1 {public static void main(String[] args) {Integer integer = Integer.valueOf(3); // 裝箱int i = Integer.intValue(integer);  // 拆箱}
}

除int和Integer之外,其他基本類型和包裝類的自動轉換也一樣,裝箱時調用valueOf()方法,拆箱時調用xxxValue()方法。

什么時候自動裝箱

1. 初始化,賦值,函數返回時

當把基本數據類型賦值給包裝類時或者基本數據類型作為函數返回值但函數聲明要求返回包裝類型時,會自動裝箱,如上面的例子

2. 將基本數據類型放入容器中

public void func2(){List<Integer> list = new ArrayList<>();list.add(1);}

反匯編之后

  public void func2();Code:0: new           #4                  // class java/util/ArrayList3: dup4: invokespecial #5                  // Method java/util/ArrayList."<init>":()V7: astore_18: aload_19: iconst_110: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;13: invokeinterface #6,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z18: pop19: return

在第10步,使用了自動裝箱

什么時候自動拆箱

1. 初始化,賦值,函數返回時

把包裝類對象賦值給基本數據類型的變量時,會自動拆箱(函數返回值原理一樣)

2. 包裝類型做算數運算時

算數運算(包括比較大小)是針對基本數據類型的,所以無論是基本數據類型與包裝類型還是包裝類型與包裝類型之間做運算都會轉換成兩個基本數據類型

public void func3(){Integer integer = 3;int i = 1;Integer integer1 = 1;boolean b1 = integer > i; // 基本數據類型與包裝類型比較大小boolean b2 = integer > integer1; // 兩個包裝類型比較大小}

反匯編后

public void func3();Code:0: iconst_31: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4: astore_15: iconst_16: istore_27: iconst_18: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;11: astore_312: aload_113: invokevirtual #3                  // Method java/lang/Integer.intValue:()I16: iload_217: if_icmple     2420: iconst_121: goto          2524: iconst_025: istore        427: aload_128: invokevirtual #3                  // Method java/lang/Integer.intValue:()I31: aload_332: invokevirtual #3                  // Method java/lang/Integer.intValue:()I35: if_icmple     4238: iconst_139: goto          4342: iconst_043: istore        545: return

通過13步,說明基本數據類型與包裝類型比較大小會轉換為兩個基本數據類型再比較
通過28,32步,說明兩個包裝類型比較大小也會轉換為基本數據類型

普通的加減乘除也一樣

public void func4() {Integer integer = 3;int i = 1;Integer integer1 = 1;int s = integer + integer1;int s1 = integer + i;}
public void func4();Code://...13: invokevirtual #3                  // Method java/lang/Integer.intValue:()I16: aload_317: invokevirtual #3                  // Method java/lang/Integer.intValue:()I20: iadd21: istore        423: aload_124: invokevirtual #3                  // Method java/lang/Integer.intValue:()I//...

3. 三目運算

如果三目運算的第二三位一個是基本數據類型另一個是包裝類型時,會自動拆箱成兩個基本數據類型

public void func5() {boolean flag = true;Integer i = 8;int j;j = 3;int k = flag ? i: j;
}
  public void func5();Code:0: iconst_11: istore_12: bipush        84: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;7: astore_28: iconst_39: istore_310: iload_111: ifeq          2114: aload_215: invokevirtual #3                  // Method java/lang/Integer.intValue:()I18: goto          2221: iload_322: istore        424: return

因為i是包裝類型,j是基本數據類型,所以在14行把i自動拆箱成了基本數據類型(并不是應為三目運算返回的是int),所以做三目運算時應該注意,尤其是基本數據類型和對象混雜時,如果對象沒被賦值,可能導致NPL(空指針異常)

只有一個是基本數據類型,一個是包裝類對象時才會自動拆箱,兩個對象是不拆的。

裝箱和拆箱時的緩存問題

public class Demo2 {public static void main(String[] args) {Integer a1 = 1;Integer a2 = 1;int a3 = 1;System.out.println(a1 == a2);  // trueSystem.out.println(a1.equals(a2));  // trueSystem.out.println(a1 == a3);  // trueSystem.out.println(a1.equals(a3));  // true}
}
public class Demo2 {public static void main(String[] args) {Integer a1 = 133;Integer a2 = 133;int a3 = 133;boolean b1 = a1 == a2;boolean b2 = a1.equals(a2);boolean b3 = a1 == a3;boolean b4 = a1.equals(a3);System.out.println(b1);  // falseSystem.out.println(b2);  // trueSystem.out.println(b3);  // trueSystem.out.println(b4);  // true}
}

兩次結果不同,原因就是自動拆裝箱時存在緩存問題,當我們第一次使用Integer時,Java會初始化一個Integer[] cache然后通過循環把-128到127之間的數加入到這個緩存中,如果新new的Integer的值在這個范圍內,就直接返回這個創建好的對象,equals()比較值,==比較是不是同一對象,所以不管怎樣,equals的結果都是true,而==在-128 到 127 之間是true,超出這個范圍是false。

這個就類似于python中的小整數池,但python的范圍是[-5, 256]

除[-128, 127]之間的整數外,boolean的兩個值,以及\u0000\u007f之間的字符也在常量池中。

總結

  1. 什么是包裝類

為了方便操作基本數據類型,對每一種基本類型提供一個包裝類,他們將基本數據類型包裝成一個對象

  1. 什么是裝箱,拆箱

把基本數據類型包裝成包裝類的過程叫裝箱(使用包裝類的valueOf()方法
把包裝類轉換為基本數據類型的過程叫拆箱(使用包裝類的xxxValue()方法

  1. 什么是自動裝箱/拆箱

Java SE5 引入的一種在特定情況下將基本數據類型自動轉換為包裝類/包裝類自動轉換為基本數據類型 的機制

  1. 什么時候自動裝箱

  2. Integer a = 5

  3. 函數返回值

  4. 把基本數據類型加入容器時

  5. 什么時候自動拆箱

  6. 初始化,賦值, 函數返回值

  7. 三目運算第二第三個參數既有包裝類,也有基本數據類型時

  8. 算術運算,比較大小

  9. 什么是自動拆裝箱時的緩存

第一次使用某些包裝類時,Java會創建一個緩存池,以后每次需要包裝類對象,就先會找緩存池中有沒有,有就直接返回,沒有才創建。緩存池的范圍:

整型:[-128, 127]
布爾:[true, false]
字符:[\u0000, \u007f]

參考

什么是Java中的自動拆裝箱
Java中整型的緩存機制

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

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

相關文章

設計模式11---組合模式(Composite Pattern)

一、組合模式定義 將對象組合成樹形結構以表示“部分-整體”的層次結構&#xff0c;使得用戶對單個對象和組合對象的使用具有一致性。Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compos…

Linux 多核下綁定硬件中斷到不同 CPU(IRQ Affinity)

轉載 - Linux 多核下綁定硬件中斷到不同 CPU&#xff08;IRQ Affinity&#xff09; 作者 digoal 日期 2016-11-20 標簽 Linux , IRQ , 中斷 , CPU親和 , 綁定中斷處理CPU 背景 原文 http://www.vpsee.com/2010/07/load-balancing-with-irq-smp-affinity/ 原文 硬件中斷發生頻繁…

請列舉你了解的分布式鎖_這幾種常見的“分布式鎖”寫法,搞懂再也不怕面試官,安排!...

什么是分布式鎖&#xff1f;大家好&#xff0c;我是jack xu&#xff0c;今天跟大家聊一聊分布式鎖。首先說下什么是分布式鎖&#xff0c;當我們在進行下訂單減庫存&#xff0c;搶票&#xff0c;選課&#xff0c;搶紅包這些業務場景時&#xff0c;如果在此處沒有鎖的控制&#x…

leetcode 268

等差數列求值 1 class Solution {2 public:3 int missingNumber(vector<int>& nums) {4 int nnums.size();5 int kn*(n1)/2;6 for(int i0;i<n;i)7 k-nums[i];8 return k;9 } 10 }; 轉載于:https://www.cnblogs.…

301緩存重定向?301 Moved Permanently (from disk cache)

今天在寫一個博客系統時&#xff0c;發現首頁數據經常刷新不出來&#xff0c;甚至后端根本就沒有接受到這個請求&#xff0c;以為是Ajax的問題&#xff0c;但通過抓包發現Ajax請求確實已經發出去了&#xff0c;但狀態碼是 301 Moved Permanently (from disk cache),301是永久重…

Firefox 50優化Electrolysis

Mozilla正式發布Firefox 50。最新的版本中提升了來自多個內容進程用戶的用戶體驗&#xff0c;并修復了十幾個高影響的安全漏洞。\\在Firefox最新版本的變更中&#xff0c;我們注意到了它對于Electrolysis的進一步改進。Electrolysis是Mozilla實現在后臺進程中呈現和執行web相關…

ModuleNotFoundError: No module named '_ctypes' ERROR:Command errored out with exit status 1: python

Ubuntu下載 nginx 時報錯&#xff1a; ERROR: Command errored out with exit status 1:command: /usr/local/bin/python3.7 -c import sys, setuptools, tokenize; sys.argv[0] ""/tmp/pip-install-7e0xdb36/uwsgi/setup.py""; __file__""/tmp…

python opc plc_PYthon簡易OPC數據采集寫入Access

利用hollias comm opcserver 與Python實現交互。代碼如下&#xff1a;# -*- coding: utf-8 -*-from sys import *from getopt import *#from os import * 造成f open(test.txt, r) TypeError: an integer is required錯誤import signalimport sysimport osimport typesimport …

邊工作邊刷題:70天一遍leetcode: day 73

Read N Characters Given Read4 I/II 要點&#xff1a;這題的要點就是搞清楚幾個變量的內在邏輯&#xff1a;只有buffer是整4 bytes的。而client要讀的bytes&#xff08;需求&#xff09;和實際上disk上有的bytes&#xff08;供給&#xff09;都是不整的。所以&#xff0c; 循環…

javascript時間戳和日期字符串相互轉換

1 <html xmlns"http://www.w3.org/1999/xhtml">2 <head>3 <meta http-equiv"Content-Type" content"text/html; charsetutf-8" />4 <script type"text/javascript">5 // 獲取當前時間戳(以s為單位)6 var time…

wireshark 十六進制過濾_CTF流量分析之wireshark使用

01.基本介紹在CTF比賽中&#xff0c;對于流量包的分析取證是一種十分重要的題型。通常這類題目都是會提供一個包含流量數據的pcap文件&#xff0c;參賽選手通過該文件篩選和過濾其中無關的流量信息&#xff0c;根據關鍵流量信息找出flag或者相關線索。pcap流量包的分析通常都是…

vim 插件管理

1  進入自己的vim mkdir ./bundle/vundle 2  在vimrc同級中執行 git clone https://github.com/gmarik/vundle.git ./bundle/vundle 將一些插件文件 下載到./bundle/vundle中 3  編寫自己的vim配置&#xff0c;其實很簡單 set nocompatible " be iMp…

ubuntu install wiznote

sudo add-apt-repository ppa:wiznote-team #添加官方源sudo apt-get update #更新源sudo apt-get install wiznote #安裝為知筆記

python 對象序列化 pickling_python操作文件——序列化pickling和JSON

當我們在內存中定義一個dict的時候&#xff0c;我們是可以隨時修改變量的內容的&#xff1a;>>> ddict(namewc,age28)>>>d{name: wc, age: 28}我們可以隨時修改name和age的值。但是當我們重新運行程序的時候&#xff0c;name、age的初始化值還是wc和28&#…

python實現Redis訂閱發布

Redis 發布訂閱 Redis 發布訂閱可以用在像消息通知&#xff0c;群聊&#xff0c;定向推送&#xff0c;參數刷新加載等業務場景 發布訂閱模型有三個角色&#xff1a; 發布者&#xff08;Publisher&#xff09;訂閱者(Subscriber)頻道(channel) 每個訂閱者可以訂閱多個頻道&am…

nfs的快速部署

1、nfs內核自帶協議模塊不用安裝&#xff0c;如果沒有yum安裝yum -y install nfs-utils2、配置vim /etc/exports #配置文件 此文件一般為空&#xff0c;編寫格式為&#xff1a; /share/word 192.168.31.254(rw) 192.168.31.252(ro) # 共享/share/word目錄給192.168.…

redistemplate怎么修改數據_如何使用RedisTemplate訪問Redis數據結構?

在springboot項目中&#xff0c;集成各種框架變得非常容易。下面簡單介紹一下如何在springboot項目中集成單機模式redis。集群模式也差不多&#xff0c;這里就不過多介紹了。首先你得安裝redis服務&#xff0c;無論在linux還是windows系統上。如果沒有安裝&#xff0c;請自行百…

HyperLogLog原理與在Redis中的使用

Redis-HyperLogLog 基于HyperLogLog算法&#xff0c;使用極小的空間完成巨量運算 Redis 中HyperLogLog 基本使用 常用命令 PFADD key element [element …]: 將任意數量的元素添加到指定的 HyperLogLog 里面。PFCOUNT key [key …]: 計算hyperloglog的獨立總數prmerge destk…

iOS開發UI篇—xib的簡單使用

一、簡單介紹 xib和storyboard的比較&#xff0c;一個輕量級一個重量級。 共同點&#xff1a; 都用來描述軟件界面 都用Interface Builder工具來編輯 不同點: Xib是輕量級的&#xff0c;用來描述局部的UI界面 Storyboard是重量級的&#xff0c;用來描述整個軟件的多個界面&…

【云棲計算之旅】線下沙龍第2期精彩預告:Docker在云平臺上的最佳實踐

Docker是一個開源的應用容器引擎&#xff0c;提供了一種在安全、可重復的環境中自動部署軟件的方式&#xff0c;允許開發者將他們的應用和依賴包打包到一個可移植的容器中&#xff0c;然后發布到任何流行的Linux機器上&#xff0c;也可以實現虛擬化。容器完全使用沙箱機制&…