天天看點

java 基本類型和包裝類_Java基本資料類型及其包裝類型

前言

Java基礎有很多方面,基本資料類型及其包裝類型算是其一,我們必須得掌握。

一、基本資料類型

在Java中,基本資料類型可分為以下幾類:

數值型

整數類型

byte

short

int

long

浮點類型

float

double

字元型

char

布爾型

boolean

而整數類型又可使用三種進制來表示。

十進制 (預設)

八進制 (以0開頭)

十六進制 (以0X或0x開頭)

整數類型占用的記憶體及範圍如下所示。預設的整數類型為int,如果要使用long,需要在數值末尾加上小寫的l或大寫的L,推薦使用大寫的L,避免和字母i及其大寫字母I混淆。

整數類型

記憶體

取值範圍

byte

8 bit

-128 - 127

short

16 bit

-32768 - 32767

int

32 bit

-2^32 - 2^32-1

long

64 bit

-2^32 - 2^32-1

對于浮點類型,預設是double類型,如果要使用float,需在數值末尾加上小寫的f或大寫的F,推薦使用大寫的F。

boolean類型隻有1位,false用0表示,true用1表示。

char類型用于表示unicode表中的所有字元,unicode表幾乎涵蓋了所有國家所有語言的所有字元。其範圍為0 - 65535。char為字元串的組成單元,有着舉足輕重的作用。

char本質上還是一個數值,表示unicode表中的位置,例如下面的兩個語句其實是等價的。

char ch = 'a';

char ch = 97;

另外,在數值未越界的情況下,char和int可以自動轉換。

char word = 'd';

int p = 23045;

System.out.println("word is " + (int)word);

System.out.println("p is " + (char)p);

Java中有一些轉意字元,有特殊的含義,例如:

\' -- 單引号

\\ -- 反斜杠

\t -- 跳格

\r -- 回車

\n -- 換行

\b -- 倒退

\f -- 換頁

二、包裝類型

上面我們提到了8種基本資料類型,而每種資料類型又對應一種包裝類型,如下所示:

基本資料類型

包裝類型

boolean

Boolean

char

Character

int

Integer

byte

Byte

short

Short

long

Long

float

Float

double

Double

為什麼需要基本資料類型?

為了效率。new建立的對象存放在堆區,簡單的小變量如果使用對象建立的方式,效率并不會很高。是以,這類變量是直接存放在棧區,進而提高了效率。

為什麼需要包裝類型?

基本類型不具備對象的特性,比如有屬性和方法。包裝類型是為了讓基本類型具有對象的特性;

可以友善地使用泛型。例如,我們不能直接将基本資料類放入集合類。

為了靈活地支援包裝類型,Java編譯器提供了自動裝箱和拆箱的機制。例如:

Integer x = new Integer(36);

int y = x;

int z = 36;

Integer u = new Integer(z);

基本類型和包裝類型有一些差別,主要展現為下面幾點:

基本類型不能使用new關鍵字來建立,包裝類型必須使用new關鍵字來建立。

存儲的位置不同。基本類型存儲在棧區,包裝類型存儲在堆區。

初始值不同。基本類型中的int初始值為0,boolean初始值為false。包裝類型初始值都為null。是以在進行自動裝拆箱時一定要避免空指針異常。

使用場景不同。基本類型主要用于計算和指派。包裝類型用于泛型。

基本類型是值傳遞,包裝類型是引用傳遞。

【注】:應盡量避免使用xxx == yyy和xxx.equals(yyy)的方式進行比較,而是應該通過Objects.equals(xxx, yyy)的方式。

三、包裝類型常用方法

1. Boolean

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

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

public static final Class TYPE = (Class) Class.getPrimitiveClass("boolean");

public Boolean(boolean value) {

this.value = value;

}

public Boolean(String s) {

this(parseBoolean(s));

}

public static boolean parseBoolean(String s) {

return ((s != null) && s.equalsIgnoreCase("true"));

}

public boolean booleanValue() {

return value;

}

public static Boolean valueOf(boolean b) {

return (b ? TRUE : FALSE);

}

public static Boolean valueOf(String s) {

return parseBoolean(s) ? TRUE : FALSE;

}

public static String toString(boolean b) {

return b ? "true" : "false";

}

public String toString() {

return value ? "true" : "false";

}

public static boolean parseBoolean(String s) {

return ((s != null) && s.equalsIgnoreCase("true"));

}

2. Integer

public static final int MIN_VALUE = 0x80000000;

public static final int MAX_VALUE = 0x7fffffff;

public static final Class TYPE = (Class) Class.getPrimitiveClass("int");

public static Integer valueOf(String s);

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

public int intValue();

public static int parseInt(String s) throws NumberFormatException {

return parseInt(s,10);

}

3. Long

public static final long MIN_VALUE = 0x8000000000000000L;

public static final long MAX_VALUE = 0x7fffffffffffffffL;

public static final Class TYPE = (Class) Class.getPrimitiveClass("long");

public static Long valueOf(String s);

public static Long valueOf(long l) {

final int offset = 128;

if (l >= -128 && l <= 127) { // will cache

return LongCache.cache[(int)l + offset];

}

return new Long(l);

}

public long longValue();

public static long parseLong(String s) throws NumberFormatException {

return parseLong(s, 10);

}

4. Double

public static final double POSITIVE_INFINITY = 1.0 / 0.0;

public static final double NEGATIVE_INFINITY = -1.0 / 0.0;

public static final double NaN = 0.0d / 0.0;

public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308

public static final double MIN_NORMAL = 0x1.0p-1022; // 2.2250738585072014E-308

public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324

public static final int MAX_EXPONENT = 1023;

public static final int MIN_EXPONENT = -1022;

public static final int SIZE = 64;

public static final int BYTES = SIZE / Byte.SIZE;

@SuppressWarnings("unchecked")

public static final Class TYPE = (Class) Class.getPrimitiveClass("double");

public static Double valueOf(String s);

public static Double valueOf(double d) {

return new Double(d);

}

public double doubleValue() {

return value;

}

public static double parseDouble(String s) throws NumberFormatException {

return FloatingDecimal.parseDouble(s);

}

5. Float

public static final float POSITIVE_INFINITY = 1.0f / 0.0f;

public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;

public static final float NaN = 0.0f / 0.0f;

public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f

public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f

public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f

public static final int MAX_EXPONENT = 127;

public static final int MIN_EXPONENT = -126;

public static final int SIZE = 32;

public static final int BYTES = SIZE / Byte.SIZE;

@SuppressWarnings("unchecked")

public static final Class TYPE = (Class) Class.getPrimitiveClass("float");

public static Float valueOf(String s) throws NumberFormatException {

return new Float(parseFloat(s));

}

public static Float valueOf(float f) {

return new Float(f);

}

public static float parseFloat(String s) throws NumberFormatException {

return FloatingDecimal.parseFloat(s);

}

public float floatValue() {

return value;

}

6. Byte

public static final byte MIN_VALUE = -128;

public static final byte MAX_VALUE = 127;

public static final Class TYPE = (Class) Class.getPrimitiveClass("byte");

public static Byte valueOf(byte b) {

final int offset = 128;

return ByteCache.cache[(int)b + offset];

}

public static byte parseByte(String s) throws NumberFormatException {

return parseByte(s, 10);

}

public static Byte valueOf(String s) throws NumberFormatException {

return valueOf(s, 10);

}

public byte byteValue() {

return value;

}

7. Short

public static final short MIN_VALUE = -32768;

public static final short MAX_VALUE = 32767;

public static final Class TYPE = (Class) Class.getPrimitiveClass("short");

public static short parseShort(String s) throws NumberFormatException {

return parseShort(s, 10);

}

public static Short valueOf(String s) throws NumberFormatException {

return valueOf(s, 10);

}

public static Short valueOf(short s) {

final int offset = 128;

int sAsInt = s;

if (sAsInt >= -128 && sAsInt <= 127) { // must cache

return ShortCache.cache[sAsInt + offset];

}

return new Short(s);

}

public short shortValue() {

return value;

}

8. Character

public static final Class TYPE = (Class) Class.getPrimitiveClass("char");

public static Character valueOf(char c) {

if (c <= 127) { // must cache

return CharacterCache.cache[(int)c];

}

return new Character(c);

}

public char charValue() {

return value;

}

9. 簡單總結

通過對常用方法的分析,我們看到所有的包裝類型都有一些類似的字段或函數,他們主要的作用是簡化我們處理基本類型和包裝類型的操作。而自動裝箱和拆箱正是其中比較重要的一種機制。

四、自動裝箱和拆箱的原理

java為了簡化我們使用基本類型和包裝類型的複雜度,特意引入了裝箱和拆箱機制。

裝箱機制 - 将基本資料類型轉換為包裝類型

拆箱機制 - 将包裝類型轉換為基本資料類型

public class Main {

public static void main(String[] args) {

Integer a = 32323;

int b = a;

}

}

上述代碼,我們使用javap -c來反編譯一下,看到如下結果:

C:\Users\Administrator>javap -c D:\zhangfb\ws\demo\target\classes\com\juconcurre

nt\demo\Main.class

Compiled from "Main.java"

public class com.juconcurrent.demo.Main {

public com.juconcurrent.demo.Main();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":

()V

4: return

public static void main(java.lang.String[]);

Code:

0: sipush 32323

3: invokestatic #2 // Method java/lang/Integer.valueOf:

(I)Ljava/lang/Integer;

6: astore_1

7: aload_1

8: invokevirtual #3 // Method java/lang/Integer.intValue

:()I

11: istore_2

12: return

}

我們看到了#2和#3,他們分别對應的是裝箱和拆箱。其實,裝箱就是調用了valueOf()方法,而拆箱則調用了intValue()方法。與此類似,其他的類型有相同的機制。

總結

首先,我們引入了基本類型和包裝類型,然後介紹了其異同和作用。

然後,了解了包裝類型常用的字段和函數,他們的命名非正常範,函數的實作也非常簡潔。

最後,我們通過自動裝箱和拆箱機制,分析了這些函數在其中起到的作用。

參考