java语言基础final_java语言中final的用法
許多程序設計語言都有自己的辦法告訴編譯器某個數據是“常數”。常數主要應用于下述兩個方面:
(1) 編譯期常數,它永遠不會改變
(2) 在運行期初始化的一個值,我們不希望它發生變化
對于編譯期的常數,編譯器(程序)可將常數值“封裝”到需要的計算過程里。也就是說,計算可在編譯期間提前執行,從而節省運行時的一些開銷。在java中,這些形式的常數必須屬于基本數據類型(Primitives),而且要用final關鍵字進行表達。在對這樣的一個常數進行定義的時候,必須給出一個值。
無論static還是final字段,都只能存儲一個數據,而且不得改變。
若隨同對象句柄使用final,而不是基本數據類型,它的含義就稍微讓人有點兒迷糊了。對于基本數據類型,final會將值變成一個常數;但對于對象句柄,final會將句柄變成一個常數。進行聲明時,必須將句柄初始化到一個具體的對象。而且永遠不能將句柄變成指向另一個對象。然而,對象本身是可以修改的。Java對此未提供任何手段,可將一個對象直接變成一個常數(但是,我們可自己編寫一個類,使其中的對象具有“常數”效果)。這一限制也適用于數組,它也屬于對象。
下面是演示final字段用法的一個例子:
//: FinalData.java
// The effect of final on fields
class Value {
int i = 1;
}
public class FinalData {
// Can be compile-time constants
final int i1 = 9;
static final int I2 = 99;
// Typical public constant:
public static final int I3 = 39;
// Cannot be compile-time constants:
final int i4 = (int)(Math.random()*20);
static final int i5 = (int)(Math.random()*20);
Value v1 = new Value();
final Value v2 = new Value();
static final Value v3 = new Value();
//! final Value v4; // Pre-Java 1.1 Error:
// no initializer
// Arrays:
final int[] a = { 1, 2, 3, 4, 5, 6 };
public void print(String id) {
System.out.println(
id + ": " + "i4 = " + i4 +
", i5 = " + i5);
}
public static void main(String[] args) {
FinalData fd1 = new FinalData();
//! fd1.i1++; // Error: can't change value
fd1.v2.i++; // Object isn't constant!
fd1.v1 = new Value(); // OK -- not final
for(int i = 0; i < fd1.a.length; i++)
fd1.a[i]++; // Object isn't constant!
//! fd1.v2 = new Value(); // Error: Can't
//! fd1.v3 = new Value(); // change handle
//! fd1.a = new int[3];
fd1.print("fd1");
System.out.println("Creating new FinalData");
FinalData fd2 = new FinalData();
fd1.print("fd1");
fd2.print("fd2");
}
} ///:~
由于i1和I2都是具有final屬性的基本數據類型,并含有編譯期的值,所以它們除了能作為編譯期的常數使用外,在任何導入方式中也不會出現任何不同。I3是我們體驗此類常數定義時更典型的一種方式:public表示它們可在包外使用;Static強調它們只有一個;而final表明它是一個常數。注意對于含有固定初始化值(即編譯期常數)的fianl static基本數據類型,它們的名字根據規則要全部采用大寫。也要注意i5在編譯期間是未知的,所以它沒有大寫。
不能由于某樣東西的屬性是final,就認定它的值能在編譯時期知道。i4和i5向大家證明了這一點。它們在運行期間使用隨機生成的數字。例子的這一部分也向大家揭示出將final值設為static和非static之間的差異。只有當值在運行期間初始化的前提下,這種差異才會揭示出來。因為編譯期間的值被編譯器認為是相同的。這種差異可從輸出結果中看出:
fd1: i4 = 15, i5 = 9
Creating new FinalData
fd1: i4 = 15, i5 = 9
fd2: i4 = 10, i5 = 9
注意對于fd1和fd2來說,i4的值是唯一的,但i5的值不會由于創建了另一個FinalData對象而發生改變。那是因為它的屬性是static,而且在載入時初始化,而非每創建一個對象時初始化。
從v1到v4的變量向我們揭示出final句柄的含義。正如大家在main()中看到的那樣,并不能認為由于v2屬于final,所以就不能再改變它的值。然而,我們確實不能再將v2綁定到一個新對象,因為它的屬性是final。這便是final對于一個句柄的確切含義。我們會發現同樣的含義亦適用于數組,后者只不過是另一種類型的句柄而已。將句柄變成final看起來似乎不如將基本數據類型變成final那么有用。
2. 空白final
Java 1.1允許我們創建“空白final”,它們屬于一些特殊的字段。盡管被聲明成final,但卻未得到一個初始值。無論在哪種情況下,空白final都必須在實際使用前得到正確的初始化。而且編譯器會主動保證這一規定得以貫徹。然而,對于final關鍵字的各種應用,空白final具有最大的靈活性。舉個例子來說,位于類內部的一個final字段現在對每個對象都可以有所不同,同時依然保持其“不變”的本質。下面列出一個例子:
//: BlankFinal.java
// "Blank" final data members
class Poppet { }
class BlankFinal {
final int i = 0; // Initialized final
final int j; // Blank final
final Poppet p; // Blank final handle
// Blank finals MUST be initialized
// in the constructor:
BlankFinal() {
j = 1; // Initialize blank final
p = new Poppet();
}
BlankFinal(int x) {
j = x; // Initialize blank final
p = new Poppet();
}
public static void main(String[] args) {
BlankFinal bf = new BlankFinal();
}
} ///:~
現在強行要求我們對final進行賦值處理——要么在定義字段時使用一個表達 式,要么在每個構建器中。這樣就可以確保final字段在使用前獲得正確的初始化。
3. final自變量
Java 1.1允許我們將自變量設成final屬性,方法是在自變量列表中對它們進行適當的聲明。這意味著在一個方法的內部,我們不能改變自變量句柄指向的東西。如下所示:
//: FinalArguments.java
// Using "final" with method arguments
class Gizmo {
public void spin() {}
}
public class FinalArguments {
void with(final Gizmo g) {
//! g = new Gizmo(); // Illegal -- g is final
g.spin();
}
void without(Gizmo g) {
g = new Gizmo(); // OK -- g not final
g.spin();
}
// void f(final int i) { i++; } // Can't change
// You can only read from a final primitive:
int g(final int i) { return i + 1; }
public static void main(String[] args) {
FinalArguments bf = new FinalArguments();
bf.without(null);
bf.with(null);
}
} ///:~
注意此時仍然能為final自變量分配一個null(空)句柄,同時編譯器不會捕獲它。這與我們對非final自變量采取的操作是一樣的。
方法f()和g()向我們展示出基本類型的自變量為final時會發生什么情況:我們只能讀取自變量,不可改變它。
總結
以上是生活随笔為你收集整理的java语言基础final_java语言中final的用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java工程化_(二)Java工程化--
- 下一篇: 复联三百度云