語言的基本特性,包括變量,基本數據類型,數組,運算符和控制流。
變量(Variables)
一個對象將狀態存儲在域(字段)中,在Java中也會使用術語“變量”來表示。
int cadence = 0;
int speed = 0;
int gear = 1;
學習對象的概念時,介紹了字段。但您可能還有幾個問題,例如:
- 命名字段有什么規則和約定?
- 除了int,還有什么其他數據類型?
- 是否必須在聲明時初始化字段?
- 如果字段未顯式初始化,字段是否會被分配了默認值?
注意:filed翻譯成域或者字段,variables翻譯成變量,在Java編程語言中,“字段”和“變量”這兩個術語很容易被混淆,因為它們通常似乎指的是同一個東西(后面講兩者該如何區分)。
Java編程語言定義了以下幾種變量:
-
Instance Variables (Non-Static Fields)實例變量(非靜態字段)
從技術上講,非靜態字段就是沒有聲明static關鍵字的字段。非靜態字段也稱為實例變量,因為它們的值對于類的每個實例(每個對象)是唯一的;一輛自行車的currentSpeed與另一輛自行車的currentSpeed是獨立不相關的。 -
Class Variables (Static Fields)類變量(靜態字段)
類變量是使用了static修飾符聲明的字段;它告訴編譯器,不管這個類被實例化多少次,這個變量只有一份。如果某種特定種類的自行車的齒輪數量是相同的,那么這個自行車類表示齒輪數量的字段可以被標記為靜態字段:static int numGears = 6。另外,可以添加關鍵字final來表示齒輪的數量將保持不變。 -
Local Variables局部變量
類的方法通常將其臨時狀態存儲在局部變量中。聲明局部變量的語法與聲明字段一樣(例如,int count = 0;),沒有特殊的關鍵字將變量指定為局部變量。一個變量是不是局部變量,看這個變量被聲明的位置是不是在類的方法。因此,局部變量僅對它們被聲明的方法可見;類的其余部分不能訪問它們。 -
Parameters參數
您已經在Bicycle類的main()方法中看到過參數的示例:public static void main(String [] args)。這里,args變量是此方法的參數。注意,參數總是被分類為“變量”而不是“字段”。這也適用于其他參數接收結構(例如構造函數和異常處理程序)。
字段和變量這兩個術語很容易混淆,在討論字段和變量時使用以下準則:
如果我們談論“一般的字段”(不包括局部變量和參數,即上面4種變量的前兩種),我們可以說“字段”。 如果討論適用于“上述所有”,我們說“變量”。 如果上下文要求區分,我們可以適當地使用特定的術語(靜態字段,局部變量等)。
你可能有時還會看到“成員”member一詞。 字段,方法和嵌套類型統稱為類的成員。
變量的命名
Java命名變量的規則和約定可以總結如下:
變量名稱區分大小寫,長度不限。
不允許使用空格。
命名名稱不能是關鍵字或保留字。
-
變量名的首字符可以是:
- 字母
- 美元符號“$”
- 下劃線字符“_”
我們約定始終以字母作為您的變量名的開頭,而不是“$”或“_”。一般來說美元符號字符在命名中從未使用過。您可能會發現在某些情況下,自動生成的名稱可能會包含美元符號,但您自己定義的變量名稱應該避免使用它。下劃線字符也是類似的。用“$”和“_”開始的變量名是合法的,但不鼓勵這種做法。
后續字符可以是字母,美元符號,下劃線字符,數字。變量名稱使用全詞,不要用隱晦的縮寫,這樣可以使代碼更容易閱讀和理解。例如,cadence, speed和gear比縮寫s,c和g更直觀。
如果您的變量命名的名稱只包含一個詞,請用小寫字母拼寫整個單詞,例如cadence和speed;如果由多個單詞組成,則第一個詞全小寫,后面每個詞的首字母大寫,例如gearRatio和currentGear;如果變量存儲一個常量值,大寫每個字母,并用下劃線字符分隔后續單詞,例如static final int NUM_GEARS = 6。按照前面的約定,下劃線字符不在其他地方使用。
基本數據類型(Primitive Data Types)
A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values.
Java編程語言是靜態的,這意味著所有變量必須先聲明,然后才能使用,包括聲明變量的類型和名稱,如您所見:
int gear = 1;
這行代碼會告訴程序,一個名為“gear”的字段用于保存的數據類型是數字,并且初始值為“1”。 變量的數據類型決定了其可能包含的值,以及可對其執行的操作。
Java編程語言支持八種基本數據類型:
byte
short
int
long
float
double
boolean
char
除了上面的8種基本數據類型之外,Java還通過java.lang.String類提供對字符串的特殊支持。 將字符串括在雙引號中將自動創建一個String對象;例如,String s =“this is a string”; String對象是不可變的,String一旦被創建,它的值不能被改變。
String類在不是原始數據類型
默認值
在聲明字段時,不是必須要分配值。 聲明但未初始化的字段將由編譯器設置一個默認值。 一般來說,默認值為零或null(取決于數據類型)。 但是,依賴編譯器賦予字段默認值,通常被認為是壞的編程風格。
Data Type | Default Value |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
boolean | false |
char | '\u0000' |
String(or any object) | null |
局部變量略有不同; 編譯器不會為未初始化的局部變量分配一個默認值。 如果您無法在聲明它的地方初始化局部變量,請確保在使用它之前為其分配一個值。 訪問未初始化的局部變量將導致編譯時報告錯誤。
字面量
您可能已經注意到,在初始化基本數據類型的變量時,不使用new關鍵字。 基本數據類型是內置于語言中的特殊數據類型; 它們不是從類創建的對象。 直接為一個基本類型的變量賦值:
boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
整數字面量
整數數據類型,如果以字母L或l結尾,數據類型是long,否則是int類型; long類型結尾建議使用大寫字母L,因為小寫字母l難以與數字1區分開。
整數類型byte,short,int和long的值可以從int類型數據創建。 數據值超過int范圍能表示的整數類型可以從long類型數據創建。整數可以用這些進制表示:
- 十進制:其數字由數字0至9組成; 我們日常用的計數就是十進制計數
- 十六進制:其數字由數字0至9和字母A至F組成
- 二進制:其數字由數字0和1組成(您可以在Java SE 7和更高版本中創建二進制數據)
前綴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'(大寫C 頂上有個^符號)或“S \ u00ED Se \ u00F1or”(西班牙語SíSe?or)。
字符使用‘單引號’
字符串使用“雙引號”
Java編程語言支持char和String的一些特殊轉義序列:\ b(退格),\ t(制表),\ n(換行),\ f(換頁),\ r(回車),\“(雙引號),'(單引號)和\(反斜杠)。
有一個特殊字面量null,null可以作為任何類型的值,可以分配給任何變量(除了基本類型的變量)。null通常在程序中用來指示某些對象不可用。
最后,還有一種特殊類型的字面量稱為類字面量,由類型名稱和“.class”構成。例如,String.class。類字面量是 表示該類型本身的對象(這個對象的類型是Class)。
java中任何一個類,都會有一個Class對象與這個類對應,在這個Class對象中,保存著實例化該類時所需要的基本信息,A.class 返回的就是類A的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后綴之前
- 在字符串里的數字之間的位置
Arrays(數組)
數組是一個容器對象,容納一定數量的一種數據類型的值。 數組的長度在創建數組時確定;創建后,其長度是固定的。
數組中的每個條目都稱為元素,每個元素通過其數字索引訪問。 如上圖所示,數字索引的編號從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)。
聲明一個數組
// 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操作符
// 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。和C,Fortran語言中的數組不一樣的是,java中的多位數組的元素本身也是數組,比如二維數組實際上是一個數組,它的每個元素都是一個一維數組。數組x的長度是數組中元素的個數,可以用x.length獲取該值;元素x[0],x[1],x[2],x[3],...,,x[x.length-1]也是數組,可以使用x[0].length,x[1].length,...,x[x.length-1].length獲取它們的長度。
下面是一個多維數組的例子:
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][2] + names[1][1]);
}
}
程序輸出如下:
Mr. Smith
Ms. Jones
二維數組就是將一維數組當成元素,放到一個一維數組里去;三維數組就是將二維數組當成元素放到一個一維數組里去:
一維數組{1,2,3},
二維數組{{1,2,3},{4,5,6}},
三維數組{{{1,2},{3,4}},{{5,6},{7,8}}},
你可以使用內建方法得到數組的大小:
System.out.println(anArray.length);
數組的復制
系統提供了數組復制的方法,可以讓用戶將數據從一個數組復制到另一個數組:
public static void arraycopy(Object src, int srcPos,
Object dest, int destPos, int length)
Object src是源數組,Object dest是目標數組;將源數組的值復制到目標數組;srcPos是源數組復制的起始位置,destPos是目標數組復制的起始位置,length是復制的元素的個數:
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提供了一些常用的數組操作方法,比如上面的例子用了System類中的方法arraycopy來將數組中的元素復制到另一個數組中,而不是手動迭代源數組的元素,并將每個元素放入目標數組。 這樣開發人員可以只需要使用一行代碼調用方法來完成數組復制的功能。
為了方便,Java SE通過類java.util.Arrays提供了一些方法來執行數組操作(常見操作比如復制,排序和搜索數組)。 例如,前面的示例可以修改為使用java.util.Arrays類的copyOfRange方法,如下面的ArrayCopyOfDemo示例所示。 這兩個方法的區別在于,使用copyOfRange方法不需要在調用方法之前創建目標數組,因為目標數組由該方法返回:
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類表示字符串。編譯器將為上述類型的字段分配一個默認值;對于局部變量,永遠不會分配默認值。數組是容納單個類型的固定數量的值的容器對象;數組的長度在創建數組時建立;創建后,其長度是固定不變的。