正如你在上一課中所瞭解到的,對象將其狀態存儲在字段中。html
int cadence = 0; int speed = 0; int gear = 1;
「什麼是對象?」討論向你介紹了字段,但你可能還有一些問題,例如:命名字段的規則和約定是什麼?除了int
以外,還有哪些其餘數據類型?在聲明字段時是否必須初始化字段?若是未明確初始化字段,是否爲字段分配了默認值?咱們將在本課中探討這些問題的答案,但在咱們開始以前,你必須首先了解一些技術差別。在Java編程語言中,使用術語「字段」和「變量」,這是新開發人員之間混淆的常見緣由,由於二者每每都是指同一件事。java
Java編程語言定義瞭如下幾種變量:編程
static
關鍵字的狀況下聲明的字段,非靜態字段也稱爲實例變量,由於它們的值對於類的每一個實例都是惟一的(換句話說,對於每一個對象),一輛自行車的當前速度獨立於另外一輛自行車的當前速度。static
修飾符聲明的任何字段,這告訴編譯器這個變量只有一個副本存在,不管該類被實例化多少次,定義特定類型自行車檔位數的字段能夠標記爲靜態,由於從概念上講,相同數量的檔位將適用於全部實例,代碼static int numGears = 6
會建立這樣一個靜態字段。此外,能夠添加關鍵字final
以指示檔位的數量永遠不會改變。int count = 0;
)。沒有特殊關鍵字將變量指定爲本地變量,該決定徹底來自聲明變量的位置 - 它位於方法的開括號和右括號之間。所以,局部變量僅對聲明它們的方法可見,他們沒法從類的其餘其餘訪問。Bicycle
類和「Hello World」應用程序的main
方法中看到了參數示例,回想一下main
方法的簽名是public static void main (String [] args)
,這裏,args
變量是此方法的參數。要記住的重要一點是參數老是被歸類爲「變量」而不是「字段」,這也適用於其餘參數接受構造(例如構造函數和異常處理程序),你將在本教程後面學習。每種編程語言都有本身的規則和約定,適用於你可使用的各類名稱,Java編程語言也不例外,命名變量的規則和約定可概括以下:segmentfault
Unicode
字母和數字序列,以字母開、美圓符號「$
」或下劃線字符「_
」開頭,可是,慣例是始終用字母開始變量名,而不是「$
」或「_
」,此外,按照慣例,美圓符號字符根本不會被使用。你可能會發現某些狀況,其中自動生成的名稱將包含美圓符號,但你的變量名稱應始終避免使用它,對於下劃線字符存在相似的約定;雖然用「_
」開始變量的名稱在技術上是合法的,但不鼓勵這種作法,不容許有空格。cadence
,speed
和gear
的字段比縮寫版本(如s
,c
和g
)更直觀,另請注意,你選擇的名稱不得是關鍵字或保留字。gearRatio
和currentGear
是此約定的主要示例,若是你的變量存儲一個常量值,例如static final int NUM_GEARS = 6;
,約定略有變化,大寫每一個字母並用後下劃線分隔後續單詞,按照慣例,下劃線字符從未在別處使用過。Java編程語言是靜態類型的,這意味着必須首先聲明全部變量才能使用它們,這包括聲明變量的類型和名稱,如你所見:api
int gear = 1;
這樣作會告訴程序一個名爲「gear」的字段存在,保存數字數據,初始值爲「1」,變量的數據類型肯定它可能包含的值,以及可能對其執行的操做。除了int
以外,Java編程語言還支持其餘七種原始數據類型,基本類型由語言預約義,並由保留關鍵字命名,原始值不與其餘原始值共享狀態,Java編程語言支持的八種原始數據類型是:數組
-128
,最大值爲127
(含),字節數據類型可用於在大數組中保存內存,其中節省的內存實際上很重要。它們也能夠用於代替int
,其限制有助於澄清你的代碼,變量範圍有限的事實能夠做爲一種文檔形式。short
數據類型是16位帶符號的二進制補碼整數,它的最小值爲-32,768,最大值爲32,767(含)。與字節同樣,適用相同的準則:在內存節省實際上很重要的狀況下,你可使用short
來節省大數組中的內存。int
數據類型是32位帶符號的二進制補碼整數,其最小值爲-2^31,最大值爲2^31-1,在Java SE 8及更高版本中,你可使用int
數據類型來表示無符號的32位整數,其最小值爲0,最大值爲2^32-1,使用Integer
類將int
數據類型用做無符號整數,有關詳細信息,請參閱「Number類」一節。已經將諸如compareUnsigned
、divideUnsigned
等靜態方法添加到Integer類中,以支持無符號整數的算術運算。long
數據類型是64位二進制補碼整數,帶符號的long
的最小值爲-2^63,最大值爲2^63-1,在Java SE 8及更高版本中,你可使用long
數據類型來表示無符號的64位長,其最小值爲0,最大值爲2^64-1,當須要比int
提供的值更寬的值時,請使用此數據類型,Long類還包含compareUnsigned
、divideUnsigned
等方法,以支持無符號long
的算術運算。byte
和short
的建議同樣,若是須要在大型浮點數數組中保存內存,請使用float
(而不是double
),毫不應將此數據類型用於精確值,例如貨幣,爲此,你須要使用java.math.BigDecimal類,Numbers和Strings涵蓋了Java平臺提供的BigDecimal
和其餘有用的類。double
數據類型是雙精度64位IEEE 754浮點,它的值範圍超出了本討論的範圍,但在Java語言規範的浮點類型、格式和值部分中指定,對於十進制值,此數據類型一般是默認選擇,如上所述,此數據類型不該用於精確值,例如貨幣。true
和false
,將此數據類型用於跟蹤真/假條件的簡單標誌,此數據類型表示一位信息,但其「大小」不是精肯定義的內容。char
數據類型是單個16位Unicode字符,它的最小值爲'\u0000'
(或0),最大值爲'\uffff'
(或65,535(含))。除了上面列出的八種原始數據類型以外,Java編程語言還經過java.lang.String類爲字符串提供特殊支持,將字符串括在雙引號內將自動建立一個新的String
對象,例如,String s =「this is a string」;
。字符串對象是不可變的,這意味着一旦建立,它們的值就不能更改,String
類在技術上不是原始數據類型,但考慮到語言給予它的特殊支持,你可能傾向於認爲它是這樣的,你將在簡單的數據對象中瞭解有關String
類的更多信息。oracle
聲明字段時並不老是須要分配值,聲明但未初始化的字段將由編譯器設置爲合理的默認值。通常來講,此默認值將爲零或null,具體取決於數據類型,然而,依賴於這樣的默認值一般被認爲是糟糕的編程風格。編程語言
下表總結了上述數據類型的默認值。編輯器
數據類型 | 默認值(對於字段) |
---|---|
byte |
0 |
short |
0 |
int |
0 |
long |
0L |
float |
0.0f |
double |
0.0d |
char |
'\u0000' |
String (或任何對象) |
null |
boolean |
false |
局部變量略有不一樣;編譯器永遠不會爲未初始化的局部變量分配默認值,若是沒法初始化聲明它的局部變量,請確保在嘗試使用它以前爲其賦值,訪問未初始化的局部變量將致使編譯時錯誤。ide
你可能已經注意到在初始化基本類型的變量時不使用new
關鍵字,原始類型是語言中內置的特殊數據類型,它們不是從類建立的對象。字面值是固定值的源代碼表示,字面值直接在代碼中表示,無需計算,以下所示,能夠將字面值分配給基本類型的變量:
boolean result = true; char capitalC = 'C'; byte b = 100; short s = 10000; int i = 100000;
若是整數字面值以字母L
或l
結尾,則其長度爲long
,不然它是int
類型,建議你使用大寫字母L
,由於小寫字母l
很難與數字1
區分開來。
能夠從int
字面值建立整數類型byte
、short
、int
和long
的值,能夠從long
字面值建立超出int
範圍的long
類型的值,整數字面值能夠用這些數字系統表示:
對於通用編程,十進制系統多是你將使用的惟一數字系統,可是,若是須要使用其餘數字系統,如下示例將顯示正確的語法,前綴0x
表示十六進制,0b
表示二進制:
// The number 26, in decimal int decVal = 26; // The number 26, in hexadecimal int hexVal = 0x1a; // The number 26, in binary int binVal = 0b11010;
若是浮點字面值以字母F
或f
結尾,則浮點字面值爲float
類型,不然它的類型是double
的,它能夠選擇以字母D
或d
結尾。
浮點類型(float
和double
)也能夠用E
或e
(科學計數法),F
或f
(32位浮點數)和D
或d
(64位雙精度數,這是默認值,按慣例省略)表示。
double d1 = 123.4; // same value as d1, but in scientific notation double d2 = 1.234e2; float f1 = 123.4f;
類型char
和String
的字面值能夠包含任何Unicode(UTF-16)字符,若是你的編輯器和文件系統容許,你能夠直接在代碼中使用這些字符,若是沒有,你可使用「Unicode轉義」,例如'\u0108'
(帶有circumflex的大寫字母C
),或"S\u00ED Se\u00F1or"
(SíSeñor,西班牙語)。始終對char
字面值使用「單引號」,對字符串字面值使用「雙引號」,Unicode轉義序列能夠在程序的其餘地方使用(例如在字段名中),而不只僅是在char
或String
字面值中。
Java編程語言還支持char
和String
字面值的一些特殊轉義序列:\b
(退格)、\t
(製表符)、\n
(換行)、\f
(換頁)、\r
(回車)、 \"
(雙引號)、\'
(單引號)和\\
(反斜槓)。
還有一個特殊的null
字面值,能夠用做任何引用類型的值,null
能夠分配給任何變量,但基本類型的變量除外。除了測試它的存在以外,你幾乎沒法使用null
值,所以,null
一般在程序中用做標記,以指示某些對象不可用。
最後,還有一種特殊的字面值稱爲類字面值,經過獲取類型名稱並附加「.class」造成,例如,String.class
,這指的是表示類型自己的對象(類型爲Class
)。
在Java SE 7及更高版本中,任何數量的下劃線字符(_
)均可以出如今數字字面值中的數字之間的任何位置,例如,此功能可使你分隔數字字面值中的數字組,這能夠提升代碼的可讀性。
例如,若是你的代碼包含具備多個數字的數字,則可使用下劃線字符來分隔三個組中的數字,相似於使用逗號或空格等標點符號做爲分隔符的方式。
如下示例顯示了在數字字面值中使用下劃線的其餘方法:
long creditCardNumber = 1234_5678_9012_3456L; long socialSecurityNumber = 999_99_9999L; float pi = 3.14_15F; long hexBytes = 0xFF_EC_DE_5E; long hexWords = 0xCAFE_BABE; long maxLong = 0x7fff_ffff_ffff_ffffL; byte nybbles = 0b0010_0101; long bytes = 0b11010010_01101001_10010100_10010010;
你只能在數字之間放置下劃線;你不能在如下地方放置下劃線:
F
或L
後綴以前如下示例演示了數字字面值中有效和無效的下劃線放置:
// Invalid: cannot put underscores // adjacent to a decimal point float pi1 = 3_.1415F; // Invalid: cannot put underscores // adjacent to a decimal point float pi2 = 3._1415F; // Invalid: cannot put underscores // prior to an L suffix long socialSecurityNumber1 = 999_99_9999_L; // OK (decimal literal) int x1 = 5_2; // Invalid: cannot put underscores // At the end of a literal int x2 = 52_; // OK (decimal literal) int x3 = 5_______2; // Invalid: cannot put underscores // in the 0x radix prefix int x4 = 0_x52; // Invalid: cannot put underscores // at the beginning of a number int x5 = 0x_52; // OK (hexadecimal literal) int x6 = 0x5_2; // Invalid: cannot put underscores // at the end of a number int x7 = 0x52_;
數組是一個容器對象,它包含固定數量的單個類型的值,建立數組時,將創建數組的長度,建立後,其長度是固定的。你已經在「Hello World!」應用程序的main
方法中看到了一個數組示例,本節更詳細地討論了數組。
10個元素的數組。
數組中的每一個項稱爲元素,每一個元素都由其數字索引訪問,如上圖所示,編號從0開始,例如,第9個元素將在索引8處訪問。
如下程序ArrayDemo
建立一個整數數組,將一些值放入數組中,並將每一個值打印到標準輸出。
class ArrayDemo { public static void main(String[] args) { // declares an array of integers int[] anArray; // allocates memory for 10 integers anArray = new int[10]; // initialize first element anArray[0] = 100; // initialize second element anArray[1] = 200; // and so forth anArray[2] = 300; anArray[3] = 400; anArray[4] = 500; anArray[5] = 600; anArray[6] = 700; anArray[7] = 800; anArray[8] = 900; anArray[9] = 1000; System.out.println("Element at index 0: " + anArray[0]); System.out.println("Element at index 1: " + anArray[1]); System.out.println("Element at index 2: " + anArray[2]); System.out.println("Element at index 3: " + anArray[3]); System.out.println("Element at index 4: " + anArray[4]); System.out.println("Element at index 5: " + anArray[5]); System.out.println("Element at index 6: " + anArray[6]); System.out.println("Element at index 7: " + anArray[7]); System.out.println("Element at index 8: " + anArray[8]); System.out.println("Element at index 9: " + anArray[9]); } }
該程序的輸出是:
Element at index 0: 100 Element at index 1: 200 Element at index 2: 300 Element at index 3: 400 Element at index 4: 500 Element at index 5: 600 Element at index 6: 700 Element at index 7: 800 Element at index 8: 900 Element at index 9: 1000
在實際編程狀況下,你可能會使用其中一個受支持的循環結構來遍歷數組的每一個元素,而不是像前面的示例中那樣單獨編寫每一行,可是,該示例清楚地說明了數組語法,你將在控制流部分中瞭解各類循環結構(for
,while
和do-while
)。
前面的程序使用如下代碼行聲明一個數組(名爲anArray
):
// declares an array of integers int[] anArray;
與其餘類型的變量的聲明同樣,數組聲明有兩個組件:數組的類型和數組的名稱。數組的類型寫爲type[]
,其中type
是包含元素的數據類型,括號是特殊符號,表示此變量包含數組,數組的大小不是其類型的一部分(這就是括號爲空的緣由)。數組的名稱能夠是你想要的任何名稱,前提是它遵循前面在命名部分中討論的規則和約定。與其餘類型的變量同樣,聲明實際上並不建立數組,它只是告訴編譯器該變量將包含指定類型的數組。
一樣,你能夠聲明其餘類型的數組:
byte[] anArrayOfBytes; short[] anArrayOfShorts; long[] anArrayOfLongs; float[] anArrayOfFloats; double[] anArrayOfDoubles; boolean[] anArrayOfBooleans; char[] anArrayOfChars; String[] anArrayOfStrings;
你還能夠將括號放在數組名稱後面:
// this form is discouraged float anArrayOfFloats[];
可是,公約不鼓勵這種形式;括號標識數組類型,並應顯示類型名稱。
建立數組的一種方法是使用new
運算符,ArrayDemo
程序中的下一個語句爲10個整數元素分配一個具備足夠內存的數組,並將該數組賦值給anArray
變量。
// create an array of integers anArray = new int[10];
若是缺乏此語句,則編譯器將輸出以下所示的錯誤,而且編譯失敗:
ArrayDemo.java:4: Variable anArray may not have been initialized.
接下來的幾行爲數組的每一個元素賦值:
anArray[0] = 100; // initialize first element anArray[1] = 200; // initialize second element anArray[2] = 300; // and so forth
每一個數組元素都經過其數字索引訪問:
System.out.println("Element 1 at index 0: " + anArray[0]); System.out.println("Element 2 at index 1: " + anArray[1]); System.out.println("Element 3 at index 2: " + anArray[2]);
或者,你可使用快捷語法來建立和初始化數組:
int[] anArray = { 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 };
這裏數組的長度由大括號之間提供的值的數量肯定,並用逗號分隔。
你還可使用兩組或更多組括號聲明一個數組數組(也稱爲多維數組),例如String [][] names
,所以,每一個元素必須由相應數量的索引值訪問。
在Java編程語言中,多維數組是一個數組,其組件自己就是數組,這與C
或Fortran
中的數組不一樣,這樣作的結果是容許行的長度不一樣,以下面的MultiDimArrayDemo
程序所示:
class MultiDimArrayDemo { public static void main(String[] args) { String[][] names = { {"Mr. ", "Mrs. ", "Ms. "}, {"Smith", "Jones"} }; // Mr. Smith System.out.println(names[0][0] + names[1][0]); // Ms. Jones System.out.println(names[0][10] + names[1][11]); } }
該程序的輸出是:
Mr. Smith Ms. Jones
最後,你可使用內置的length
屬性來肯定任何數組的大小,如下代碼將數組的大小打印到標準輸出:
System.out.println(anArray.length);
System
類有一個arraycopy
方法,你可使用它來有效地將數據從一個數組複製到另外一個數組:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
兩個Object
參數指定要從中複製的數組和要複製到的數組,三個int
參數指定源數組中的起始位置、目標數組中的起始位置以及要複製的數組元素的數量。
如下程序ArrayCopyDemo
聲明瞭一個char
元素數組,拼寫單詞「decaffeinated」,它使用System.arraycopy
方法將數組組件的子序列複製到第二個數組中:
class ArrayCopyDemo { public static void main(String[] args) { char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' }; char[] copyTo = new char[7]; System.arraycopy(copyFrom, 2, copyTo, 0, 7); System.out.println(new String(copyTo)); } }
該程序的輸出是:
caffein
數組是編程中使用的強大而有用的概念,Java SE提供了執行與數組相關的一些最多見操做的方法,例如,ArrayCopyDemo
示例使用System
類的arraycopy
方法,而不是手動迭代源數組的元素並將每一個元素放入目標數組中。這是在幕後執行的,使開發人員只使用一行代碼來調用該方法。
爲方便起見,Java SE提供了幾種在java.util.Arrays類中執行數組操做(常見任務,如複製、排序和搜索數組)的方法。例如,能夠修改前面的示例以使用java.util.Arrays
類的copyOfRange
方法,如ArrayCopyOfDemo
示例中所示:
class ArrayCopyOfDemo { public static void main(String[] args) { char[] copyFrom = {'d', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd'}; char[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9); System.out.println(new String(copyTo)); } }
正如你所看到的,此程序的輸出是相同的(caffein
),儘管它須要更少的代碼行,請注意,copyOfRange
方法的第二個參數是要複製的範圍的初始索引,包括,而第三個參數是要複製的範圍的最終索引,在此示例中,要複製的範圍不包括索引9處的數組元素(其中包含字符a)。
java.util.Arrays
類中的方法提供的一些其餘有用的操做是:
binarySearch
方法)。equals
方法)。fill
方法)。sort
方法串行完成,也可使用Java SE 8中引入的parallelSort
方法並行完成,在多處理器系統上並行排序大型數組比串行數組排序更快。Java編程語言使用「字段」和「變量」做爲其術語的一部分,實例變量(非靜態字段)對於類的每一個實例都是惟一的,類變量(靜態字段)是使用static
修飾符聲明的字段,不管類被實例化多少次,都只有一個類變量的副本。局部變量在方法中存儲臨時狀態,參數是爲方法提供額外信息的變量,局部變量和參數老是被歸類爲「變量」(而不是「字段」),在命名字段或變量時,你應該(或必須)遵循規則和約定。
八種原始數據類型是:byte
、short
、int
、long
、float
、double
、boolean
和char
,java.lang.String
類表示字符串。編譯器將爲上述類型的字段分配合理的默認值,對於局部變量,永遠不會分配默認值。字面值是固定值的源代碼表示,數組是一個容器對象,它包含固定數量的單個類型的值,建立數組時,將創建數組的長度,建立後,其長度是固定的。