【譯】Java8官方教程:語言基礎—變量

原文地址:docs.oracle.com/javase/tuto…html

變量(Variables)

正如咱們上一節中所學,對象將它的狀態存儲在"字段(fields)"中java

int cadence = 0;
int speed = 0;
int gear = 1;
複製代碼

"何爲對象?"中向您介紹了「字段(fields)」,可是您可能會存在一些疑問,例如:命名"字段(fields)"的規則和約定是什麼?除了int,還有一些什麼數據類型?字段聲明時必須初始化嗎?若是沒有顯示初始化,它們具備默認的值嗎?本節課咱們將探索這些問題的答案,可是在這以前,下面是您必須首先注意的一些技術區別。在Java編程語言中,術語「字段(fields)」和「變量(Variables)」都被採用,對於新開發人員來講,這是一個常見的困惑源,它們一般指代的彷佛是同一個事物。git

Java編程語言定義瞭如下幾種變量:編程

  • 實例變量(非靜態字段):技術上來講,對象將各自的狀態存儲在「非靜態字段」中,也就是說,聲明字段時沒有指定static關鍵字。非靜態字段也稱爲實例變量,由於他們的值在每一個類的實例中(或者說:在每一個對象中)都是不同的。一輛自行車的當前速度與另外一輛自行車的當前速度無關。api

  • 類變量(靜態字段):使用靜態修飾符(static)聲明的任何字段稱爲類變量;這告訴編譯器,無論這個類實例化了多少次,該變量都僅存在一個副本。對於特定類型自行車齒輪數的字段能夠聲明爲static,這將賦予全部實例相同的齒輪數。代碼段:static int numGears = 6;將建立一個靜態字段,此外,能夠添加關鍵字final來表示齒輪的數量永遠不會改變。數組

  • 局部變量:與對象將狀態存儲在字段中類似,方法常常將其暫時的狀態存在局部變量中。聲明局部變量的語法相似於聲明字段(int count = 0;)。沒有特殊的關鍵字指定其爲局部變量;這徹底取決於變量聲明的位置——方法的開括號和閉括號之間;所以,局部變量只對聲明它們的方法可見;其餘類沒法訪問它們。bash

  • 參數: 在自行車類和「Hello world!」應用中您已經看到過參數的示例。回想一下main方法:public static void main(String[] args),這裏,args是這個方法的參數。重要的是要記住參數老是被分類爲「變量」而不是「字段」。這也適用於其餘接受參數的構造方法(如構造函數和異常處理器),您將在本教程的後面學習這些併發

話雖如此,若是咱們談論的是「通常的字段」(不包括局部變量和參數),咱們能夠簡單地說「字段」。若是討論適用於「以上全部」,咱們能夠簡單地說「變量」。若是上下文須要區別,咱們將使用特定的術語(靜態字段、局部變量等)。你可能會常常看到"成員"這個術語。字段、方法和嵌套類型統稱爲其成員。oracle

命名

每種編程語言對於容許使用的命名方式都有本身的一套規則和約定,Java編程語言也不例外,變量命名的規則和約定能夠總結以下:編程語言

  • 變量名區分大小寫。變量的名稱能夠是任何合法的標識符——不限長度的Unicode字母和數字序列,以字母,「$」符,或下劃線「_」開頭。然而,習慣上,變量名老是以字母開頭,而不是「$」或「_」。此外,根據慣例,美圓符號字符從未使用過。您可能會發如今某些狀況下,自動生成的名稱將包含美圓符號,可是變量命名時應該避免使用。下劃線字符也有相似的約定;雖然從技術上講,以「_」做爲變量名的開頭是合法的,可是不鼓勵這樣作。空格是不被容許使用的。

  • 後續字符能夠是字母、數字、美圓符號或下劃線字符。當爲變量選擇名稱時,使用完整的單詞而不是模糊的縮寫。這樣作將使您的代碼更容易閱讀和理解。在許多狀況下,它還會使您的代碼更直觀;例如,名爲cadence、speed和gear的字段比縮寫版本(如s、c和g)更直觀。還要記住,您選擇的名稱不能是關鍵字或保留字

  • 若是您選擇的名稱只包含一個單詞,請將該單詞所有用小寫字母拼寫。若是由一個以上的單詞組成,則將後面每一個單詞的第一個字母大寫。如:gearRatio、currentGear。對於static final int NUM_GEARS = 6,約定有少量變化,將每一個字母大寫,而後用下劃線分隔後面的單詞。按照慣例,下劃線字符永遠不會在其餘地方使用

基本數據類型

Java編程語言是靜態類型語言,這意味着全部的變量在使用前必須先聲明。包括聲明變量的類型和名稱,正如你已經見過的:

int gear = 1;
複製代碼

這樣作會告訴程序存在一個名爲「gear」的字段,該字段保存數值數據,初始值爲「1」。 變量的數據類型決定了它可能包含的值,以及可能對其執行的操做。除了int,Java程序語言還支持其餘7種基本數據類型。基本類型由語言預約義,並由保留關鍵字命名。不一樣基本數據類型之間的值並不共享。Java支持的8種基本數據類型分別爲:

  • byte:byte數據類型是8-bit補碼錶示的有符號整數。最小值爲-128,最大值爲127(含)。byte數據類型在大數組中節省內存時顯得十分有用,在大數組中,內存的節省實際上很是重要。範圍限制有助於闡明代碼時能夠用其代替int;變量的範圍有限這一事實能夠做爲文檔的一種形式。

  • short:short數據類型是16-bit補碼錶示的有符號整數。最小值爲-32768,最大值爲32767(含)。與byte同樣,一樣的指導原則也適用:在實際須要節省內存的狀況下,您可使用short來在大數組中節省內存。

  • int:默認狀況下,int數據類型是一個32-bit補碼錶示的有符號整數,最小值爲-2^31,最大值爲2^31-1。在Java SE 8及更高版本中,可使用int數據類型表示範圍爲0到2^32-1的無符號32-bit整數。使用Integer類將int數據類型用做無符號整數,更多信息見The Number Classes一節,在Integer類中添加了compareUnsigned、divideUnsigned等靜態方法來支持無符號整數的算術運算。

  • long:long數據類型是一個64-bit補碼錶示的有符號整數,最小值爲-2^64,最大值爲2^64-1。在Java SE 8及更高版本中,您可使用long數據類型來表示範圍爲0到2^64-1的無符號64-bit整數。當您須要比int提供的值範圍更大的值時,可使用這種數據類型。Long類還包含compareUnsigned、divideUnsigned等方法來支持無符號long的算術操做

  • float:float數據類型是一個單精度的32位IEEE 754浮點數,它的取值區間超出了咱們的討論範圍,可是在Floating-Point Types, Formats, and Values一節中有詳細說明。與byte和short的建議同樣,若是須要在浮點數的大數組中節省內存,請使用float(而不是double)。這種數據類型不該該用於存儲精確的值,好比貨幣。爲此,您須要使用java.math.BigDecimal類。Numbers and Strings中涵蓋了BigDecimal和其它Java平臺提供的有用的類。

  • double:double數據類型是一個雙精度的64位IEEE 754浮點數,它的取值區間超出了咱們的討論範圍,可是在Floating-Point Types, Formats, and Values一節中有詳細說明。對於包含小數的值,這種數據類型一般是默認選擇。如上所述,這種數據類型永遠不該該用於精確的值,好比貨幣。

  • boolean:boolean數據類型只有兩個可能的值:true和false。使用此數據類型存儲"真/假"條件。這個數據類型表示1-bit的信息,可是它實際佔用內存的「大小」並非精肯定義的。

  • char: char數據類型是一個16位Unicode字符。 最小值爲 '\u0000' (0),最大值爲 '\uffff' (65535)

除了上面列出的八種基本數據類型以外,Java編程語言還經過Java .lang.String提供了對字符串的特殊支持。將字符串括在雙引號內將自動建立一個新的字符串對象;例如: String s = "this is a string";String對象是不可變的,這意味着一旦建立,它們的值就不能更改。String類在技術上不是原始數據類型,可是考慮到該語言對它的特殊支持,您可能會這樣認爲。您將在Numbers and Strings中瞭解關於String類的更多信息

默認值

聲明字段時並不老是須要賦值,編譯器將爲已經聲明但未初始化的字段設置合理的默認值。通常來講,根據數據類型的不一樣,這個默認值將是零或null。然而,依賴這些默認值一般被認爲是糟糕的編程風格
下表總結了上述數據類型的默認值:

局部變量略有不一樣;編譯器從不將默認值分配給未初始化的局部變量。若是沒法在聲明局部變量的地方初始化該變量,請確保在嘗試使用它以前爲其賦值。訪問未初始化的局部變量將致使編譯時錯誤。

字面量(Literals)

您可能已經注意到,在初始化基本類型的變量時不使用new關鍵字。基本類型是構建在語言中的特殊數據類型;它們不是經過類建立的對象。字面量是值的源代碼表示,直接在代碼中表示,不須要計算。以下所示,能夠將字面量賦值給基本類型的變量:

boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
複製代碼

整數字面量

若是以字母L或l結尾,整數字面量的類型爲long;不然它是int類型的。建議使用大寫字母L,由於小寫字母l很難與數字1區分.整數類型byte、short、int和long的值能夠從int字面量建立。long類型的值超出int的範圍,能夠從long字面量建立。整數字面值能夠由這些數字系統表示:

  • 十進制:以10爲基數,由數字0到9組成;這是你天天使用的數字系統
  • 16進制:以16爲基數,由數字0到9和字母A到F組成
  • 二進制:以2爲基數,由數字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位float字面量)和D或d(64位double字面量;這是默認值,按慣例可省略)來表示。

double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1  = 123.4f;
複製代碼

字符和字符串字面量

字符和字符串類型的字面量能夠包含任何Unicode (UTF-16)字符。若是編輯器和文件系統容許,能夠在代碼中直接使用這些字符。若是不容許,您可使用「Unicode轉義」,好比「\u0108」(大寫的C)或"S\u00ED Se\u00F1or"(西班牙語中的Sí Señor)。對於char字面量,請始終使用'單引號';對於String字面量,請使用「雙引號」。Unicode轉義序列能夠在程序的其餘地方使用(例如在字段名中),而不只僅是在字符或字符串字面量中。Java編程語言還支持一些用於字符和字符串字面量的特殊轉義序列:\b(退格)、\t(製表符)、\n(換行)、\f(表格換行)、\r(回車)、\"(雙引號)、\'(單引號)和\\(反斜槓)

還有一個特殊的null字面量,能夠用做任何引用類型的值。除基本類型的變量外,能夠將null賦給任何變量。除了測試null值的存在性以外,您對null值幾乎無能爲力。所以,在程序中常用null做爲標記來指示某些對象不可用。

最後,還有一種特殊的字面量,叫作類字面量,它是由一個類型名加上「.class」組成的;例如String.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後綴以前
  • 在須要一串數字的位置(原文:In positions where a string of digits is expected)

下面的例子演示了數字字面量中有效和無效的下劃線位置:

// Invalid: cannot put underscores
// 小數點相鄰位置
float pi1 = 3_.1415F;
// Invalid: cannot put underscores 
// 小數點相鄰位置
float pi2 = 3._1415F;
// Invalid: cannot put underscores 
// 在L後綴以前
long socialSecurityNumber1 = 999_99_9999_L;

// OK (decimal literal)
int x1 = 5_2;
// Invalid: cannot put underscores
// 字面量的開頭或結尾
int x2 = 52_;
// OK (decimal literal)
int x3 = 5_______2;

// Invalid: cannot put underscores
// 在0x前綴中
int x4 = 0_x52;
// Invalid: cannot put underscores
// 在數字的開頭
int x5 = 0x_52;
// OK (hexadecimal literal)
int x6 = 0x5_2; 
// Invalid: cannot put underscores
// 數字的結尾
int x7 = 0x52_;
複製代碼

數組

數組是一個容器對象,它存儲固定數量的單一類型值。數組的長度是在建立數組時肯定的。建立以後,它的長度就是固定的。您已經在「Hello World!」應用程序的主方法中看到了一個數組示例(main(String[] args))。本節更詳細地討論數組:

數組中的每一項都稱爲一個元素,每一個元素都由其數值索引訪問。如上圖所示,編號從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
複製代碼

在實際的編程環境中,您可能會使用受支持的循環結構來遍歷數組的每一個元素,而不是像前面的示例那樣單獨地編寫每一行。然而,這個例子清楚地說明了數組語法。在 "控制流(Control Flow)"一節中您將瞭解各類循環結構(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[][]名稱)聲明數組的數組(也稱爲多維數組)。所以,每一個元素必須由相應數量的索引值訪問。
在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][2] + names[1][1]);
    }
}
複製代碼

程序輸出爲:

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元素數組,存儲單詞「decaffeated」。它使用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示例使用系統類的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方法併發執行。在多處理器系統上對大數組進行並行排序要比順序數組排序快。
相關文章
相關標籤/搜索