在前邊的博文中,我已經(jīng)介紹了Java核心的容器IO等,現(xiàn)在我來(lái)說(shuō)一下java中的數(shù)據(jù)類型。在java中,一切東西皆為對(duì)象(這句話意思是java中絕大數(shù)情況都用對(duì)象),極少數(shù)不是對(duì)象的,也存在與之對(duì)應(yīng)的對(duì)象(比如基本數(shù)據(jù)類型存在與之對(duì)應(yīng)的包裝類,數(shù)組有List對(duì)象可以代替)

  Java中數(shù)據(jù)類型 主要有“基本數(shù)據(jù)類型”、“String”、“引用類型” (基本的引用類型不多做介紹,在下一篇博文中著重介紹“枚舉”,也算是引用類型的一種)

一:基本數(shù)據(jù)類型 

1.1基本數(shù)據(jù)類型的定義

  byte、char、int、 float 、double、long...這些屬于java的基本數(shù)據(jù)類型。具體用法可以參照  (Java基本數(shù)據(jù)類型總結(jié) ) .在java看來(lái),使用基本類型并不是面向?qū)ο蟮脑O(shè)計(jì),于是提供一些專門的包裝類。實(shí)際開發(fā)中,不需要我們考慮到底是用基本類型還是包裝類(Java提供了自動(dòng)裝箱機(jī)制)。當(dāng)然基本類型還是有必要學(xué)習(xí)一下的。

1.1.1按種類了解基本類型

   基本類型可以分為三類,字符類型char,布爾類型boolean以及數(shù)值類型byte、short、int、long、float、double。JAVA中的數(shù)值類型不存在無(wú)符號(hào)的,它們的取值范圍是固定的,不會(huì)隨著機(jī)器硬件環(huán)境或者操作系統(tǒng)的改變而改變   

Java決定了每種簡(jiǎn)單類型的大小,并不隨著機(jī)器結(jié)構(gòu)的變化而變化。這正是Java程序具有很強(qiáng)移植能力的原因之一。下表列出了Java中定義的簡(jiǎn)單類型、占用二進(jìn)制位數(shù)及對(duì)應(yīng)的封裝器類。 

簡(jiǎn)單類型

boolean

byte

char

short

Int

long

float

double

void

二進(jìn)制位數(shù)

1

8

16

16

32

64

32

64

--

封裝器類

Boolean

Byte

Character

Short

Integer

Long

Float

Double

Void

  這張表可以簡(jiǎn)單的看一下,但不推薦花費(fèi)太多時(shí)間(實(shí)際開發(fā)不需要,如果是應(yīng)付考試還是需要記一下的)。因?yàn)?Java語(yǔ)言之所以流行就是希望程序員可以消耗更少的心力在語(yǔ)法上,從而省出更多的時(shí)間去整理具體的業(yè)務(wù)邏輯。在基本數(shù)據(jù)類型這一塊,Java提供自動(dòng)裝箱機(jī)制,下面簡(jiǎn)單介紹一下自動(dòng)裝箱。

1.1.2Java中自動(dòng)裝箱

   自動(dòng)裝箱就可以簡(jiǎn)單的理解為將基本數(shù)據(jù)類型封裝為對(duì)象類型,來(lái)符合java的面向?qū)ο?。比如你可以直接把一個(gè)int值復(fù)制給一個(gè)Integer對(duì)象

//聲明一個(gè)Integer對(duì)象
Integer num = 10;

   自動(dòng)裝箱的時(shí)候,存在一個(gè)細(xì)節(jié)點(diǎn)就是“對(duì)于值從–128到127之間的值,它們被裝箱為Integer對(duì)象后,會(huì)存在內(nèi)存中被重用,始終只存在一個(gè)對(duì)象”,測(cè)試如下

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

//在-128~127 之外的數(shù)
Integer num1 = 297;   Integer num2 = 297;           
System.out.println("num1==num2: "+(num1==num2));                    
 // 在-128~127 之內(nèi)的數(shù) 
 Integer num3 = 97;   Integer num4 = 97;   
System.out.println("num3==num4: "+(num3==num4)); 
//測(cè)試結(jié)果:num1==num2: false  \n  num3==num4: true

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

  有時(shí)候,只能用包裝類,不能用基本數(shù)據(jù)類型,比如集合內(nèi)

  具體的細(xì)節(jié)可以參考這幾位仁兄的博客 (Java 自動(dòng)裝箱與拆箱(Autoboxing and unboxing),java 自動(dòng)裝箱與拆箱

1.2 基本數(shù)據(jù)類型的保存位置

   基本類型存儲(chǔ)在棧中,處于效率考慮,基本類型保存在棧中。延伸一下,包裝類保存在堆中(注意我之前說(shuō)過(guò)的-127到128之間的包裝類Integer)

1.3 堆棧的簡(jiǎn)單介紹(這個(gè)和基本數(shù)據(jù)類型沒(méi)有太大關(guān)系相當(dāng)于是擴(kuò)展內(nèi)容)

  Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),不需要程序代碼來(lái)顯式的釋放,由垃圾回收來(lái)負(fù)責(zé)即可。堆的優(yōu)勢(shì)是可以動(dòng)態(tài)地分配內(nèi)存 大小,生存期也不必事先告訴編譯器(因?yàn)槭窃谶\(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存的,Java的垃圾收集器會(huì)自動(dòng)收走這些不再使用的數(shù)據(jù))。但缺點(diǎn)是,由于要在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存,存取速度較慢。

  棧的優(yōu)勢(shì)是,存取速度比堆要快,僅次于寄存器,棧數(shù)據(jù)可以共享。但缺點(diǎn)是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本類型的變量數(shù)據(jù)(int, short, long, byte, float, double, boolean, char)和引用數(shù)據(jù)類型(這個(gè)和基本數(shù)據(jù)類型無(wú)關(guān),不多做介紹)

1.3.1 數(shù)據(jù)共享簡(jiǎn)單介紹

//基本數(shù)據(jù)類型的共享和對(duì)象不一樣,對(duì)象共享的本質(zhì)上是引用,對(duì)象修改會(huì)影響另外一個(gè)變量,基本類型只是共享的值,當(dāng)值修改時(shí),實(shí)際上是讓變量又重新指向了另一個(gè)地方
public static void main(String[] args) { int a = 5; int b = 5;//一定是先找棧里有沒(méi)有5,有就讓b也指向5 a = 6;  //先找棧里有沒(méi)有6,如果沒(méi)有則新建6并讓a指向 
   System.out.println(b); }

1.3.2 局部變量與成員變量保存位置簡(jiǎn)單介紹

對(duì)于成員變量和局部變量:成員變量就是方法外部,類的內(nèi)部定義的變量;局部變量就是方法或語(yǔ)句塊內(nèi)部定義的變量。局部變量必須初始化。 

  • 形式參數(shù)是局部變量,局部變量的數(shù)據(jù)存在于棧內(nèi)存中。棧內(nèi)存中的局部變量隨著方法的消失而消失。 

  • 成員變量存儲(chǔ)在堆中的對(duì)象里面,由垃圾回收器負(fù)責(zé)回收

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

1.class BirthDate {  
2.    private int day;  //day是成員變量
3.    private int month;  
4.    private int year;      
5.    public BirthDate(int d, int m, int y) {  
6.        day = d;   //d是局部變量
7.        month = m;   
8.        year = y;  
9.    }  
10.    省略get,set方法………  
11.}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

1.3.3 java中常量簡(jiǎn)單介紹

  • 十六進(jìn)制整型常量:以十六進(jìn)制表示時(shí),需以0x或0X開頭,如0xaa,0X9f。

  • 八進(jìn)制整型常量:八進(jìn)制必須以0開頭,如0123,034。

  • 長(zhǎng)整型:             長(zhǎng)整型必須以L作結(jié)尾,如9L,342L。

  • 浮點(diǎn)數(shù)常量:      由于小數(shù)常量的默認(rèn)類型是double型,所以float類型的后面一定要加f(F)。同樣帶小數(shù)的變量默認(rèn)為double類型?!∪纾篺loat f;f=1.3f;//必須聲明f。

  • 字符常量:         字符型常量需用兩個(gè)單引號(hào)括起來(lái)(注意字符串常量是用兩個(gè)雙引號(hào)括起來(lái))。Java中的字符占兩個(gè)字節(jié)。

1.4 Java基本類型的“類型轉(zhuǎn)換”

  簡(jiǎn)單類型數(shù)據(jù)間的轉(zhuǎn)換,有兩種方式:自動(dòng)轉(zhuǎn)換和強(qiáng)制轉(zhuǎn)換,通常發(fā)生在表達(dá)式中或方法的參數(shù)傳遞時(shí)。

1.4.1 自動(dòng)轉(zhuǎn)換:是JVM根據(jù)條件自動(dòng)幫助我們轉(zhuǎn)換,可以簡(jiǎn)單了解一下轉(zhuǎn)換規(guī)則。

  當(dāng)一個(gè)較"小"數(shù)據(jù)與一個(gè)較"大"的數(shù)據(jù)一起運(yùn)算時(shí),系統(tǒng)將自動(dòng)將"小"數(shù)據(jù)轉(zhuǎn)換成"大"數(shù)據(jù),再進(jìn)行運(yùn)算  。

這些類型由"小"到"大"分別為 (byte,short,char)--int--long--float—double,這里我們所說(shuō)的"大"與"小",并不是指占用字節(jié)的多少,而是指表示值的范圍的大小 。所以byte --char--short之間不可以自動(dòng)轉(zhuǎn)換

1.4.2 強(qiáng)制轉(zhuǎn)換:

 將"大"數(shù)據(jù)轉(zhuǎn)換為"小"數(shù)據(jù)時(shí),你必須使用強(qiáng)制類型轉(zhuǎn)換。即你必須采用下面這種語(yǔ)句格式: int n=(int)3.14159/2;可以想象,這種轉(zhuǎn)換肯定可能會(huì)導(dǎo)致溢出或精度的下降

  1.  表達(dá)式的數(shù)據(jù)類型自動(dòng)提升  eg 所有的byte,short,char型的值將被提升為int型;

  2.  包裝類和基本類型轉(zhuǎn)換 :實(shí)際上Java存在一個(gè)自動(dòng)裝箱的機(jī)制,他可以自動(dòng)轉(zhuǎn)換。但是,我們可以用構(gòu)造器轉(zhuǎn)為包裝類;用包裝類對(duì)象的xxxValue()把包裝類轉(zhuǎn)為基本類型

  3.  其它類型間轉(zhuǎn)為字符串:①調(diào)用類的串轉(zhuǎn)換方法:X.toString();   ②自動(dòng)轉(zhuǎn)換:X+"";  ③使用String的方法:String.volueOf(X);

  4.  字符串轉(zhuǎn)為其它類型  ①先轉(zhuǎn)換成相應(yīng)的封裝器實(shí)例,再調(diào)用對(duì)應(yīng)的方法轉(zhuǎn)換成其它類型 new Double("3.1").doubleValue().或者Double.valueOf("32.1").doubleValue()②靜態(tài)parseXXX方法String s = "1";byte b = Byte.parseByte( s );

  5. Date類與其它數(shù)據(jù)類型的相互轉(zhuǎn)換 :整型和Date類之間并不存在直接的對(duì)應(yīng)關(guān)系,只是你可以使用int型為分別表示年、月、日、時(shí)、分、秒,這樣就在兩者之間建立了一個(gè)對(duì)應(yīng)關(guān)系 。具體轉(zhuǎn)換,可能用到format類

1.4.3 備注              

    只有boolean不參與數(shù)據(jù)類型的轉(zhuǎn)換  

二:String類型

   在實(shí)際開發(fā)中 String使用非常廣泛。于是Java設(shè)計(jì)者針對(duì)String做了非常多的優(yōu)化來(lái)提高效率,這雖然提高了程序的效率,但是在一定程度上也會(huì)給我們開發(fā)提高了難度,于是在Thinking in Java中單獨(dú)把String當(dāng)作一個(gè)章節(jié)。下面我會(huì)從整體上總結(jié)一下String,一些具體的方法可以去查詢API(Java API

 

2.1 String創(chuàng)建方式

  new是按照面向?qū)ο蟮臉?biāo)準(zhǔn)語(yǔ)法,在內(nèi)存使用上存在比較大的浪費(fèi)。所以String對(duì)象的創(chuàng)建是不需要new的(這樣可以提高效率,但是如果用new創(chuàng)建字符串也不會(huì)報(bào)錯(cuò))

 

 2.1.1在這里,延伸一下,java中創(chuàng)建對(duì)象的方式一共存在五種:

  分別是 new 關(guān)鍵字、Class類的 newInstance 方法、Constructor類的 newInstance 方法、String對(duì)象的 clone方法、反序列化機(jī)制。但是String對(duì)象還有一種特殊的創(chuàng)建方式,就是通過(guò)使用  或  包裹字符序列

 

    public static void main(String[] args)
    {
        String s = "Hello World!";//實(shí)際上當(dāng)""的時(shí)候java就創(chuàng)建了該對(duì)象
        System.out.println(s); 
                    
    }

下面的代碼詳細(xì)的對(duì)比了java的正常創(chuàng)建形式(“”)和 new的區(qū)別  (參照自  深入理解Java:String   ),在這里,我推薦一下  String的原理與用法總結(jié)  。該博主圖畫的還是挺清晰的,一目了然

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

public static void

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

2.1.2 簡(jiǎn)單的概括一下:

  用“”創(chuàng)建對(duì)象的時(shí)候,String對(duì)象是放到常量池中,只會(huì)創(chuàng)建一個(gè),每次都是先去找一下常量池有沒(méi)有該字符串

  用 new創(chuàng)建對(duì)象,會(huì)在隊(duì)中創(chuàng)建一個(gè)對(duì)象,然后在棧內(nèi)創(chuàng)建該對(duì)象應(yīng)用,每次都是新創(chuàng)建

2.2 String類初始化后是不可變的(immutable)

  String類初始化之后不可變,因?yàn)閖ava設(shè)計(jì)者不希望我們方法傳參是字符串的時(shí)候,方法內(nèi)修改會(huì)影響外邊的串,所以采取了一種傳遞拷貝的方式(也就是傳值)

 String ss = "this is the origen String";
 TestString.showString(ss);
public static void showString(String s){
    System.out.println(s);
}

2.2.1 Java中String不可變是怎么一回事

  java中,一旦產(chǎn)生String對(duì)象,該對(duì)象就不會(huì)在發(fā)生變化。但是String另一方面的確提供了修改String的方法。這看起來(lái)很矛盾,實(shí)際上是我們沒(méi)有仔細(xì)的了解那些修改的方法

比如replace(),如果可以看到源碼,可以清楚的看到該方法實(shí)際上新產(chǎn)生一個(gè)字符串,替換操作是針對(duì)新的字符串。(下圖參考自參考Java進(jìn)階01 String類,簡(jiǎn)單的表示replace()方法調(diào)用時(shí)

s的變化)

                                  大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計(jì)算培訓(xùn),高端軟件開發(fā)培訓(xùn),項(xiàng)目經(jīng)理培訓(xùn)

下邊的代碼 :我在原字符串的基礎(chǔ)上添加了一句話,然后判斷他們是否相同(如果是同一個(gè)對(duì)象修改,==輸出結(jié)果應(yīng)該是true)

 String s1 = "我";

s1+="我想在加點(diǎn)東西";
system.out.println(s1 == s2)//輸出結(jié)果是false

思考一下 "s1指向的對(duì)象中的字符串是什么"(我們潛意識(shí)的認(rèn)為s1也會(huì)被修改,但是當(dāng)s2 = "s2"時(shí),實(shí)際上s2的引用已經(jīng)被修改,它和s1沒(méi)關(guān)系了)

String s1 = "s1"

再重復(fù)一遍,無(wú)論是修改字符串的方法還是對(duì)字符串賦值,都和普通的對(duì)象不同。賦值是讓字符串指向一個(gè)新的字符串,方法傳參是copy一份值,傳入進(jìn)去

  再比如說(shuō):String str=”kv”+”ill”+” “+”ans”; 就是有4個(gè)字符串常量,首先”kv”和”ill”生成了”kvill”存在內(nèi)存中,然后”kvill”又和” ” 生成 “kvill “存在內(nèi)存中,最后又和生成了”kvill ans”;并把這個(gè)字符串的地址賦給了str

所以 + 會(huì)產(chǎn)生很多臨時(shí)變量。下文中會(huì)說(shuō)到StringBuilder 來(lái)避免這種情況。不過(guò)有一種特殊情況。 "ab"+"cd" 在JVM編譯后和"abcd"一樣

String str1 = "ab" + "cd";  //1個(gè)對(duì)象  
String str11 = "abcd";   
System.out.println("str1 = str11 : "+ (str1 == str11));

 

2.2.2 Java是怎樣做到String的不可變的

在String源碼中 ,使用private final char value[]來(lái)實(shí)現(xiàn)字符串的存儲(chǔ),就是因?yàn)閒inal,才說(shuō)String類型是不可變

 /** The value is used for character storage. */
    private final char value[];

2.3 String的保存位置

   深入一點(diǎn),我們了解一下String保存的位置(可以參考java+內(nèi)存分配及變量存儲(chǔ)位置的區(qū)別[轉(zhuǎn)],java中的String類常量池詳解

   String常量是保存在常量池中。JVM中的常量池在內(nèi)存當(dāng)中是以表的形式存在的, 對(duì)于String類型,有一張固定長(zhǎng)度的CONSTANT_String_info表用來(lái)存儲(chǔ)文字字符串值,注意:該表只存儲(chǔ)文字字符串值,不存儲(chǔ)符號(hào)引用。說(shuō)到這里,對(duì)常量池中的字符串值的存儲(chǔ)位置應(yīng)該有一個(gè)比較明了的理解了。在程序執(zhí)行的時(shí)候,常量池會(huì)儲(chǔ)存在Method Area,而不是堆中。常量池中保存著很多String對(duì)象; 并且可以被共享使用,因此它提高了效率

  什么是常量池

  常量池指的是在編譯期被確定,并被保存在已編譯的.class文件中的一些數(shù)據(jù)。

除了包含代碼中所定義的各種基本類型(如int、long等等)和對(duì)象型(如String及數(shù)組)的常量值(final)還包含一些以文本形式出現(xiàn)的符號(hào)引用。

2.4主要的方法   

  • s.length()                 返回s字符串長(zhǎng)度

  • s.charAt(2)                 返回s字符串中下標(biāo)為2的字符

  • s.substring(0, 4)             返回s字符串中下標(biāo)0到4的子字符串

  • s.indexOf("Hello")            返回子字符串"Hello"的下標(biāo)

  • s.startsWith(" ")             判斷s是否以空格開始

  • s.endsWith("oo")              判斷s是否以"oo"結(jié)  

作者:leader_Hoo 
出處:http://www.cnblogs.com/ldh-better/ 
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,如果有幫助,請(qǐng)多多支持。

http://www.cnblogs.com/ldh-better/p/7153594.html