本次談談java中的基本數據類型。java中8個基本數據類型說多不多說少也不少,相對簡單的記憶方式:整數型(byte,short,int,long)、浮點型(float,double)、邏輯型(boolean)、字符(char)。
java基本類型簡介:
| 類型 | 所占空間(bit) | 所占空間(byte) | 取值范圍 | 對應的裝箱基本類型 | 基本類型大小判斷 |
| byte | 8bit | 1byte | -128~127 | Byte | >、<、==等 |
| short | 16bit | 2byte | -32768~32767 | Short | >、<、==等 |
| int | 32bit | 4byte | -(2^31)~(2^31)-1 | Integer | >、<、==等 |
| long | 64bit | 8byte | -(2^63)~(2^63)-1 | Long | >、<、==等 |
| float | 32bit | 4byte | (+-)3.402823447E+38F | Float | Float.compare()或Double.compare() |
| double | 64bit | 8byte | (+-)1.79769313486231570E+308 | Double | Double.compare() |
| boolean | 1bit | 1/8byte | 0、1 | Boolean | 無 |
| char | 16bit | 2byte | 0~(2^16)-1 | Char | >、<、==等 |
基本類型&引用類型:
基本類型之所以叫基本類,是因為其數據能夠在方法的棧空間中分配;相對應的引用類型是不能夠在方法的棧空間中分配,而在堆空間中分配的。棧在性能上高於堆。這里的前提是方法的棧空間,類對象中基本類型域還是分配在堆空間中。
各自對應的裝箱基本類型就是屬於引用類型,封裝相應的裝箱基本類型是比較必要。
值傳遞or引用傳遞?:
所謂引用傳遞是指在調用函數時將實際參數的地址傳遞到函數中,那么在函數中對參數所進行的修改,將影響到實際參數。
在c/c++是存在引用傳遞,但是java中沒有引用傳遞(具體看:http://guhanjie.iteye.com/blog/1683637這位博主總結的還是不錯的)
1 public class Test { 2 private int id; 3 4 static Test test1; 5 static Test test2 = new Test(); 6 7 static public void main(String[] args) { 8 9 test2.id = 13; 10 System.out.println("doTest:"); 11 System.out.println("test1 is " +test1); 12 doTest(test1); 13 System.out.println("test1 is " +test1); 14 System.out.println("########################"); 15 System.out.println("test2 is " +test2); 16 doTest(test2); 17 System.out.println("test2 is " +test2); 18 } 19 20 static private void doTest(Test test) { 21 System.out.println("start doTest:"); 22 if (test == null) { 23 test = new Test(); 24 } 25 test.id = 31; 26 System.out.println("test is " +test); 27 System.out.println("end doTest."); 28 } 29 30 @Override 31 public String toString() { 32 return ""+this.id; 33 } 34 }
如果是引用傳遞那么其在函數中對參數的所進行的修改,將影響到實際參數。所以打印的結果應該是:
doTest:
test1 is null
start doTest:
test is 31
end doTest.
test1 is 31
########################
test2 is 13
start doTest:
test is 31
end doTest.
test2 is 31
但是現實容易打臉:

可以看到test1在執行完doTest之后還是null.即沒用影響實際參數。但是為什么test2受到影響了呢?

那么真正的引用傳遞是如何的呢?這里為了方便查看打印出變量的地址。(在線編譯器地址:http://codepad.org/)
#include <iostream> using namespace std; struct Test { int id; }test1,test2={13}; void doTest(Test &test) { cout<<"start doTest:"<<endl; cout<<"test address:"<<&test<<endl; test.id = 31; cout<<"test is " <<test.id<<endl; cout<<"end doTest."<<endl; } int main() { cout<<"doTest:"<<endl; cout<<"test1 is " <<test1.id<<endl; cout<<"test1 address:"<<&test1<<endl; doTest(test1); cout<<"test1 is " <<test1.id<<endl; cout<<"########################"<<endl; cout<<"test2 is " <<test2.id<<endl; cout<<"test2 address:"<<&test2<<endl; doTest(test2); cout<<"test2 is " <<test2.id<<endl; return 0; }
地址是一樣的。。。。(c忘光了,不敢隨便分析一下其內存分配,海涵)
這里給出java模型:
這里的test與test2沒直接的關系,唯一相同的就是都引用了堆中地址為AAAA的Test對象
基本類型Or裝箱基本類型:
這里探討基本類型與裝箱類型的應用場景:
1、能用基本類型就絕不用裝箱類型,我的准則而言。基本類型在性能上遠遠優於裝箱基本類型。
1 import java.util.*; 2 3 public class Test { 4 static public void main(String[] args) { 5 double startTime = System.currentTimeMillis(); 6 Long L = 0l; 7 for (int i = 0; i < Integer.MAX_VALUE; i++) { 8 L += 1; 9 } 10 double endTime = System.currentTimeMillis(); 11 System.out.printf("裝箱基本類型耗時:%f%n", (endTime - startTime)); 12 13 startTime = System.currentTimeMillis(); 14 long l = 0l; 15 for (int i = 0; i < Integer.MAX_VALUE; i++) { 16 l += 1; 17 } 18 endTime = System.currentTimeMillis(); 19 System.out.printf("裝箱基本類型耗時:%f%n", (endTime - startTime)); 20 } 21 }

代碼角度建議能不用裝箱基本類型就不用或者減少裝箱拆箱次數
2、泛型中只能使用裝箱基本類型。原因:存在類型擦除的,將類型都替換成頂級父類(Object)。
裝箱基本類型出現的必然性:
java作為一門面向對象的編程語言,各種編程邏輯應該都是基於對象。裝箱基本類型的出現,使得各種邏輯更加便捷易懂,基本類型中的各種邏輯划分更加明了清晰。(還有挺多的不總結啦。。。)
譬如:int的邊界直接定義在Integer中作為靜態常量,long的邊界直接定義在Long中作為靜態常量;兩者各司其職互不影響。
