當前位置:首頁 » 編程語言 » forfinaljava

forfinaljava

發布時間: 2022-07-08 02:47:00

⑴ 在java中,final修飾的類有什麼特點

關於Java中的final(2010-09-09 14:19:48)轉載▼標簽: javafinal 分類: Java知識學習

Java中的final共有三種用法:

final成員變數
當你在類中定義變數時,在其前面加上final關鍵字,那便是說,這個變數一旦被初始化便不可改變,這里不可改變的意思對基本類型來說是其值不可變,而對於對象變數來說其引用不可再變,但引用變數所指向的對象中的內容還是可以改變的。

其初始化可以在三個地方,
一是其定義處,也就是說在final變數定義時直接給其賦值,
二是在構造函數中。而且在Java1.1以前,只能是在定義時給值。
三是在初如化代碼塊中{} 或者static{}
下面這段代碼演示了這一點:更加詳細的探討請參考關於final變數的初始化探討

import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

public class Bat {

final double PI = 3.14; // 在定義時便給址值
final int i; // 因為要在構造函數中進行初始化,所以此處便不可再給值
final List list; // 此變數也與上面的一樣

Bat() {
i = 100;
list = new LinkedList();
}

Bat(int ii, List l) {
i = ii;
list = l;
}

public static void main(String[] args) {
Bat b = new Bat();
b.list.add(new Bat());//引用不可變,但引用指向的內容是可以變的
// b.i=25; syntax error i是不可變的
//b.list=new ArrayList();錯誤,對象引用是不可變的
System.out.println("I=" + b.i + " List Type:" + b.list.getClass());
b = new Bat(23, new ArrayList());
b.list.add(new Bat());
System.out.println("I=" + b.i + " List Type:" + b.list.getClass());
}
}

再例如,對於如下語句:

final StringBuffer a=new StringBuffer("immutable");
執行如下語句將報告編譯期錯誤:

a=new StringBuffer("");
但是,執行如下語句則可以通過編譯:

a.append(" broken!");

有人在定義方法的參數時,可能想採用如下形式來阻止方法內部修改傳進來的參數對象:

public void method(final StringBuffer param)

{

}

實際上,這是辦不到的,在該方法內部仍然可以增加如下代碼來修改參數對象,其它對象亦如此:

param.append("a");

在看一個例子
//: 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:for 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,因為i1是final的
fd1.v2.i++; // Object isn't constant!這個可以是因為類Value中的i是普通變數
fd1.v1 = new Value(); // OK -- not final
for (int i = 0; i < fd1.a.length; i++)
fd1.a[i]++; // Object isn't constant!

//下面三個犯同樣的錯誤 Error: Can'tchange handle
// ! fd1.v2 = new Value();
// ! fd1.v3 = new Value(); //
// ! fd1.a = new int[3];
fd1.print("fd1");
System.out.println("Creating new FinalData");

FinalData fd2 = new FinalData();
fd1.print("fd1");
fd2.print("fd2");
}
}
輸出結果(由於上面用了隨機函數,所以輸出結果可能不一樣,但是規律是一樣的):
fd1: i4 = 4, i5 = 6
Creating new FinalData
fd1: i4 = 4, i5 = 6
fd2: i4 = 10, i5 = 6
結果分析:fd1與fd2的i4發現值總是不一樣,但i5的值卻是一樣的,這是為什麼呢?
我們可以發現定義i4與i5惟一的區別是後者多了一個static,由於final變數和static變數可以說
都只能存一個數據,他們惟一的區別是static變數是屬於類的,是類變數,只會被載入一次。
請參考該文章:Java_父類與子類的載入原理
而i4雖然是final的,但是它仍是個普通變數,屬於實例變數,每創建一個對象還是會被載入一次,又
由於是個隨機函數,所以最終的結果不一樣。
所以:一定要區分final與static final的細微差別。

使用final關鍵字修飾一個變數時,是指引用變數不能變,引用變數所指向的對象中的內容還是可以改變的。

此程序很簡單的演示了final的常規用法。在這里使用在構造函數中進行初始化的方法,這使你有了一點靈活性。如Bat的兩個重載構造函數所示,第一個預設構造函數會為你提供默認的值,重載的那個構造函數會根據你所提供的值或類型為final變數初始化。然而有時你並不需要這種靈活性,你只需要在定義時便給定其值並永不變化,這時就不要再用這種方法。在main方法中有兩行語句注釋掉了,如果你去掉注釋,程序便無法通過編譯,這便是說,不論是i的值或是list的類型,一旦初始化,確實無法再更改。然而b可以通過重新初始化來指定i的值或 list的類型,輸出結果中顯示了這一點:
I=100 List Type:class java.util.LinkedList
I=23 List Type:class java.util.ArrayList

還有一種用法是定義方法中的參數為final,對於基本類型的變數,這樣做並沒有什麼實際意義,因為基本類型的變數在調用方法時是傳值的,也就是說你可以在方法中更改這個參數變數而不會影響到調用語句,然而對於對象變數,卻顯得很實用,因為對象變數在傳遞時是傳遞其引用,這樣你在方法中對對象變數的修改也會影響到調用語句中的對象變數,當你在方法中不需要改變作為參數的對象變數時,明確使用final進行聲明,會防止你無意的修改而影響到調用方法。

另外方法中的內部類在用到方法中的參變數時,此參變也必須聲明為final才可使用,如下代碼所示:
public class INClass {
void innerClass(final String str) {
class IClass {
IClass() {
System.out.println(str);
}
}
IClass ic = new IClass();
}

public static void main(String[] args) {
INClass inc = new INClass();
inc.innerClass("Hello");
}
}

final方法
將方法聲明為final,那就說明你已經知道這個方法提供的功能已經滿足你要求,不需要進行擴展,並且也不允許任何從此類繼承的類來覆寫這個方法,但是繼承仍然可以繼承這個方法,也就是說可以直接使用。

另外有一種被稱為inline的機制,它會使你在調用final方法時,直接將方法主體插入到調用處,而不是進行例行的方法調用,例如保存斷點,壓棧等,這樣可能會使你的程序效率有所提高,然而當你的方法主體非常龐大時,或你在多處調用此方法,那麼你的調用主體代碼便會迅速膨脹,可能反而會影響效率,所以你要慎用final進行方法定義。

類中所有的private方法從某種意義上講都是屬於final的,因為他們在其它地方沒法覆蓋,你可以在一個private方法前加final修飾符,但沒什麼意義。

final類
當你將final用於類身上時,你就需要仔細考慮,因為一個final類是無法被任何人繼承的,那也就意味著此類在一個繼承樹中是一個葉子類,並且此類的設計已被認為很完美而不需要進行修改或擴展。對於final類中的成員變數,你可以定義其為final,也可以不是final。而對於方法,由於所屬類為final的關系,自然也就成了final型的。你也可以明確的給final類中的方法加上一個final,但這顯然沒有意義。
下面的程序演示了final方法和final類的用法:

final class finals {
final String str = "final Data";
public String str1 = "non final data";

final public void print() {
System.out.println("final method.");
}

public void what() {
System.out.println(str + "\n" + str1);
}

}

public class FinalDemo { // extends final 無法繼承
public static void main(String[] args) {
finals f = new finals();
f.what();
f.print();
}
}

從程序中可以看出,final類與普通類的使用幾乎沒有差別,只是它失去了被繼承的特性。final方法與非final方法的區別也很難從程序行看出,只是記住慎用。

附註:
final在設計模式中的應用
在設計模式中有一種模式叫做不變模式,在Java中通過final關鍵字可以很容易的實現這個模式,在講解final成員時用到的程序Bat.java就是一個不變模式的例子。如果你對此感興趣,可以參考閻宏博士編寫的《Java與模式》一書中的講解。

⑵ Java for循環幾種寫法整理

1:遍歷數組的傳統方式
/* 建立一個數組 */
int[] integers = {1, 2, 3, 4};
/* 開始遍歷 */
for (int j = 0; j<integers.length; j++){
int i = integers[j];
System.out.println(i);
}

2:遍歷Collection對象的傳統方式

/* 建立一個Collection */
String[] strings = {"A", "B", "C", "D"};
Collection stringList = java.util.Arrays.asList(strings);
/* 開始遍歷 */
for (Iterator itr = stringList.iterator(); itr.hasNext();) {
Object str = itr.next();
System.out.println(str);
}

3:遍歷數組的簡單方式

/* 建立一個數組 */
int[] integers = {1, 2, 3, 4};
/* 開始遍歷 */
for (int i : integers) {
System.out.println(i);/* 依次輸出「1」、「2」、「3」、「4」 */
}
4:遍歷數組的簡單方式的等價代碼

/* 建立一個數組 */
int[] integers = {1, 2, 3, 4};
/* 開始遍歷 */
for (int 變數名甲 = 0; 變數名甲<integers.length; 變數名甲++) {
System.out.println(integers[變數名甲]);/* 依次輸出「1」、「2」、「3」、「4」 */
}
5:遍歷Collection的簡單方式

/* 建立一個Collection */
String[] strings = {"A", "B", "C", "D"};
Collection list = java.util.Arrays.asList(strings);
/* 開始遍歷 */
for (Object str : list) {
System.out.println(str);/* 依次輸出「A」、「B」、「C」、「D」 */
}
6:遍歷Collection的簡單方式的等價代碼

/* 建立一個Collection */
String[] strings = {"A", "B", "C", "D"};
Collection stringList = java.util.Arrays.asList(strings);
/* 開始遍歷 */
for (Iterator 變數名乙 = list.iterator(); 變數名乙.hasNext();) {
Object str = 變數名乙.next();
System.out.println(str);/* 依次輸出「A」、「B」、「C」、「D」 */
}
7:禁止重新賦值

int[] integers = {1, 2, 3, 4};
for (final int i : integers) {
i = i / 2; /* 編譯時出錯 */
}
8:允許修改狀態

Random[] randoms = new Random[]{new Random(1), new Random(2), new Random(3)};
for (final Random r : randoms) {
r.setSeed(4);/* 將所有Random對象設成使用相同的種子 */
System.out.println(r.nextLong());/* 種子相同,第一個結果也相同 */
}
9:使用和要被遍歷的數組中的元素相同類型的循環變數

int[] integers = {1, 2, 3, 4};
for (int i : integers) {
System.out.println(i);/* 依次輸出「1」、「2」、「3」、「4」 */
}

10:使用和要被遍歷的Collection中的元素相同類型的循環變數

Collection< String> strings = new ArrayList< String>();
strings.add("A");
strings.add("B");
strings.add("C");
strings.add("D");
for (String str : integers) {
System.out.println(str);/* 依次輸出「A」、「B」、「C」、「D」 */
}
11:使用要被遍歷的對象中的元素的上級類型的循環變數

String[] strings = {"A", "B", "C", "D"};
Collection< String> list = java.util.Arrays.asList(strings);
for (Object str : list) {
System.out.println(str);/* 依次輸出「A」、「B」、「C」、「D」 */
}

12:使用能和要被遍歷的對象中的元素的類型自動轉換的類型的循環變數

int[] integers = {1, 2, 3, 4};
for (Integer i : integers) {
System.out.println(i);/* 依次輸出「1」、「2」、「3」、「4」 */
}

⑶ java中final修飾的變數不是不能被修改嗎

基本數據類型是不可以被修改了,
包括String. 但是也有例外.如Map,List等,即使你用final修飾了,
依然可以put和add 說到底,還是引用問題.final意味著引用不可變罷了

⑷ java中for循環內加入final變數聲明並初始化為什麼不報錯

因為每次循環 此jbu非彼jbu

String a[]={"s","g","k"};
final JButton jbu
for(int i=0;i<9;i++)

jbu=new JButton(a[i]);

這樣寫就有問題了,因為jbu 是同一個,採納!!!!~ 速度的....

⑸ java 中,怎樣判斷一個變數是否是 final 常量

第一是在聲明的時候
第二是在在賦值的時候看報錯不,報錯說明是final常量。
不報錯說明不是常量。
那你就用全局變數不就完了。

⑹ java中的final定義變數問題

首先final是不能被修改的 、但是你在創建final類型的欄位時沒有初始化 所以是可以進行初始化工作的
其次 你定義的final是類屬性 類在創建後為類的實例即對象 那麼對象就有這個final的欄位
最後 列印出來的5個值 並不是同一個final欄位的值 是每個對象里的final的值 是不沖突的
不知道你明白了嗎

⑺ java中通過for循環創建button,然後獲得每個的gettext,但是需要加final,final該怎麼加,求大神

改為下面的:
for(int i=0;i<16;i++){
but[i]=new JButton("dsf"+i);
final int j=i;
but[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
buttonNow=but[j];

⑻ Java final 變數為什麼可以改變值

你那個代碼,counter是static,也就是說,是類范圍的,所有Apple 類共享此變數,是可變的。

這個id的final修飾符表示是個對象實例級常量,每個對象實例有自己單獨的值,對象實例創建完成後,常量值不能改變。
每次創建Apple對象實例時,都會為該實例初始化id值,你採用了counter++,所以每次counter值都會加1,其值依次為0(初始值)、1、2、3,其值在加1前,賦給id作為其初始值,依次為0、1、2。所以列印出來就是0、1、2了。
常量在初始化的時候,可以使用任何合法表達式來進行,甚至若定義時沒有指定值,也可以在構造方法里為其賦值(只能賦值一次)。

熱點內容
滑板鞋腳本視頻 發布:2025-02-02 09:48:54 瀏覽:432
群暉怎麼玩安卓模擬器 發布:2025-02-02 09:45:23 瀏覽:557
三星安卓12彩蛋怎麼玩 發布:2025-02-02 09:44:39 瀏覽:743
電腦顯示連接伺服器錯誤 發布:2025-02-02 09:24:10 瀏覽:537
瑞芯微開發板編譯 發布:2025-02-02 09:22:54 瀏覽:146
linux虛擬機用gcc編譯時顯示錯誤 發布:2025-02-02 09:14:01 瀏覽:235
java駝峰 發布:2025-02-02 09:13:26 瀏覽:651
魔獸腳本怎麼用 發布:2025-02-02 09:10:28 瀏覽:538
linuxadobe 發布:2025-02-02 09:09:43 瀏覽:212
sql2000資料庫連接 發布:2025-02-02 09:09:43 瀏覽:726