Java™ 教程(變量)

變量

正如你在上一課中所瞭解到的,對象將其狀態存儲在字段中。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字母和數字序列,以字母開、美圓符號「$」或下劃線字符「_」開頭,可是,慣例是始終用字母開始變量名,而不是「$」或「_」,此外,按照慣例,美圓符號字符根本不會被使用。你可能會發現某些狀況,其中自動生成的名稱將包含美圓符號,但你的變量名稱應始終避免使用它,對於下劃線字符存在相似的約定;雖然用「_」開始變量的名稱在技術上是合法的,但不鼓勵這種作法,不容許有空格。
  • 後續字符能夠是字母,數字,美圓符號或下劃線字符,約定(和通用場景)也適用於此規則,爲變量選擇名稱時,請使用完整單詞而不是隱藏縮寫,這樣作可使你的代碼更易於閱讀和理解。在許多狀況下,它還會使你的代碼自我記錄,例如,名爲cadencespeedgear的字段比縮寫版本(如scg)更直觀,另請注意,你選擇的名稱不得是關鍵字或保留字。
  • 若是你選擇的名稱只包含一個單詞,則拼寫所有小寫字母,若是它由多個單詞組成,則將每一個後續單詞的首字母大寫,名稱gearRatiocurrentGear是此約定的主要示例,若是你的變量存儲一個常量值,例如static final int NUM_GEARS = 6;,約定略有變化,大寫每一個字母並用後下劃線分隔後續單詞,按照慣例,下劃線字符從未在別處使用過。

原始數據類型

Java編程語言是靜態類型的,這意味着必須首先聲明全部變量才能使用它們,這包括聲明變量的類型和名稱,如你所見:api

int gear = 1;

這樣作會告訴程序一個名爲「gear」的字段存在,保存數字數據,初始值爲「1」,變量的數據類型肯定它可能包含的值,以及可能對其執行的操做。除了int以外,Java編程語言還支持其餘七種原始數據類型,基本類型由語言預約義,並由保留關鍵字命名,原始值不與其餘原始值共享狀態,Java編程語言支持的八種原始數據類型是:數組

  • byte:字節數據類型是8位帶符號的二進制補碼整數,它的最小值爲-128,最大值爲127(含),字節數據類型可用於在大數組中保存內存,其中節省的內存實際上很重要。它們也能夠用於代替int,其限制有助於澄清你的代碼,變量範圍有限的事實能夠做爲一種文檔形式。
  • shortshort數據類型是16位帶符號的二進制補碼整數,它的最小值爲-32,768,最大值爲32,767(含)。與字節同樣,適用相同的準則:在內存節省實際上很重要的狀況下,你可使用short來節省大數組中的內存。
  • int:默認狀況下,int數據類型是32位帶符號的二進制補碼整數,其最小值爲-2^31,最大值爲2^31-1,在Java SE 8及更高版本中,你可使用int數據類型來表示無符號的32位整數,其最小值爲0,最大值爲2^32-1,使用Integer類將int數據類型用做無符號整數,有關詳細信息,請參閱「Number類」一節。已經將諸如compareUnsigneddivideUnsigned等靜態方法添加到Integer類中,以支持無符號整數的算術運算。
  • longlong數據類型是64位二進制補碼整數,帶符號的long的最小值爲-2^63,最大值爲2^63-1,在Java SE 8及更高版本中,你可使用long數據類型來表示無符號的64位長,其最小值爲0,最大值爲2^64-1,當須要比int提供的值更寬的值時,請使用此數據類型,Long類還包含compareUnsigneddivideUnsigned等方法,以支持無符號long的算術運算。
  • float:浮點數據類型是單精度32位IEEE 754浮點,它的值範圍超出了本討論的範圍,但在Java語言規範的浮點類型、格式和值部分中指定。與byteshort的建議同樣,若是須要在大型浮點數數組中保存內存,請使用float(而不是double),毫不應將此數據類型用於精確值,例如貨幣,爲此,你須要使用java.math.BigDecimal類,Numbers和Strings涵蓋了Java平臺提供的BigDecimal和其餘有用的類。
  • doubledouble數據類型是雙精度64位IEEE 754浮點,它的值範圍超出了本討論的範圍,但在Java語言規範的浮點類型、格式和值部分中指定,對於十進制值,此數據類型一般是默認選擇,如上所述,此數據類型不該用於精確值,例如貨幣。
  • boolean:布爾數據類型只有兩個可能的值:truefalse,將此數據類型用於跟蹤真/假條件的簡單標誌,此數據類型表示一位信息,但其「大小」不是精肯定義的內容。
  • charchar數據類型是單個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;

整數字面值

若是整數字面值以字母Ll結尾,則其長度爲long,不然它是int類型,建議你使用大寫字母L,由於小寫字母l很難與數字1區分開來。

能夠從int字面值建立整數類型byteshortintlong的值,能夠從long字面值建立超出int範圍的long類型的值,整數字面值能夠用這些數字系統表示:

  • 十進制:基數10,其數字由數字0到9組成,這是你天天使用的數字系統。
  • 十六進制:基數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;

浮點字面值

若是浮點字面值以字母Ff結尾,則浮點字面值爲float類型,不然它的類型是double的,它能夠選擇以字母Dd結尾。

浮點類型(floatdouble)也能夠用Ee(科學計數法),Ff(32位浮點數)和Dd(64位雙精度數,這是默認值,按慣例省略)表示。

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

字符和字符串字面值

類型charString的字面值能夠包含任何Unicode(UTF-16)字符,若是你的編輯器和文件系統容許,你能夠直接在代碼中使用這些字符,若是沒有,你可使用「Unicode轉義」,例如'\u0108'(帶有circumflex的大寫字母C),或"S\u00ED Se\u00F1or"(SíSeñor,西班牙語)。始終對char字面值使用「單引號」,對字符串字面值使用「雙引號」,Unicode轉義序列能夠在程序的其餘地方使用(例如在字段名中),而不只僅是在charString字面值中。

Java編程語言還支持charString字面值的一些特殊轉義序列:\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;

你只能在數字之間放置下劃線;你不能在如下地方放置下劃線:

  • 在數字的開頭或結尾
  • 與浮點字面值中的小數點相鄰
  • FL後綴以前
  • 在預期有一串數字的位置

如下示例演示了數字字面值中有效和無效的下劃線放置:

// 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方法中看到了一個數組示例,本節更詳細地討論了數組。

objects-tenElementArray.gif

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

在實際編程狀況下,你可能會使用其中一個受支持的循環結構來遍歷數組的每一個元素,而不是像前面的示例中那樣單獨編寫每一行,可是,該示例清楚地說明了數組語法,你將在控制流部分中瞭解各類循環結構(forwhiledo-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編程語言中,多維數組是一個數組,其組件自己就是數組,這與CFortran中的數組不一樣,這樣作的結果是容許行的長度不一樣,以下面的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修飾符聲明的字段,不管類被實例化多少次,都只有一個類變量的副本。局部變量在方法中存儲臨時狀態,參數是爲方法提供額外信息的變量,局部變量和參數老是被歸類爲「變量」(而不是「字段」),在命名字段或變量時,你應該(或必須)遵循規則和約定。

八種原始數據類型是:byteshortintlongfloatdoublebooleancharjava.lang.String類表示字符串。編譯器將爲上述類型的字段分配合理的默認值,對於局部變量,永遠不會分配默認值。字面值是固定值的源代碼表示,數組是一個容器對象,它包含固定數量的單個類型的值,建立數組時,將創建數組的長度,建立後,其長度是固定的。


上一篇:面向對象編程概念

下一篇:運算符

相關文章
相關標籤/搜索