java學習筆記之—final 與 static



一、fianl

1、final數據

Final可以修飾靜態變量,實例變量和局部變量。
final修飾一個永不改變的編譯時常量或者是一個運行時被初始化的值,而你不希望他被改變。
對於基本數據類型final使其數值恆定不變,對於對象引用final使引用恆定不變。一旦引用被初始化指向一個對象,就無法再把它改爲指向另一個對象。(對象自身是可以被修改的)
必須在域的定義處或者每個構造器中用表達式對final進行賦值。
空白final:
final變量定義的時候,可以先聲明,而不給初值,稱爲空白final。編譯器確保空白final在使用之前必須被初始化。一個類中的final數據成員可以實現依對象而有所不同,卻有保持其恆定不變的特徵。(繞暈了,來看看代碼清醒一下吧)
代碼演示:

class Poppet{
	private int i;
	Poppet(int ii){
		ii=i;
	}
}
public class BlankFinal {
private final int i=0;//初始化final
private final int j;//空白final
private final Poppet p;
public BlankFinal(){
	j=1;
	p=new Poppet(1);
	System.out.println("j="+j);
}
public BlankFinal(int x){
	j=x;
	p=new Poppet(x);
	System.out.println("j="+j);
}
	public static void main (String args[]){
		new BlankFinal();
		new BlankFinal(47);	
	}
}

運行結果:
j=1
j=47

Final參數:
Java允許在參數列表中以聲明的方式將參數指明爲final,這意味着無法在方法中更改參數引用所指向的對象。
當函數參數爲final類型時,你可以讀取使用該參數,但是無法改變該參數的值。
代碼演示:

class Gizmo{
	public void spin(){System.out.println("可以在方法中改變無final修飾的參數引用所指對象");}
}
public class FinalArguments {
void with (final Gizmo g){
	//g=new Gizmo();不能在方法中更改final參數引用所指向的對象
	System.out.println("不能在方法中更改final參數引用所指向的對象");
}
void without(Gizmo g){
	g=new Gizmo();
	g.spin();
}
//void f(final int i){i++;}不能改變final參數的值
int g(final int i){
	return i+1;//這裏僅僅是返回了i+1,i的值本身沒有變
}
	public static void main(String[] args) {
		FinalArguments bf=new FinalArguments();
		bf.without(null);
		bf.with(null);
	}
}

運行結果:
可以在方法中改變無final修飾的參數引用所指對象
不能在方法中更改final參數引用所指向的對象

2、final方法

Final不能用於修飾構造方法。
使用final方法的原因:
一是鎖定方法,防止任何繼承類修改。
二是效率。
final和private關鍵詞:
類中所有的private方法都隱式的指定爲final,其他類因爲無法取用private方法,所以就無法覆蓋它,所以對private方法加final修飾詞沒有意義。
代碼演示:

class WithFinals{
	private final void f(){
		System.out.println("WithFinals.f()");
	}
	private void g(){
		System.out.println("WithFinals.g()");
	}
}
class OverridingPrivate extends WithFinals{
	private final void f(){
		System.out.println("OverridingPrivate.f()");
	}
	private void g(){
		System.out.println("OverridingPrivate.g()");
	}
}
class OverridingPrivate2 extends OverridingPrivate{
	public final void f(){//並沒有覆蓋父類方法,只是名字相同而已
		System.out.println("OverridingPrivate2.f()");
	}
	public void g(){//並沒有覆蓋父類方法,只是名字相同而已
		System.out.println("OverridingPrivate2.g()");
	}
}
public class FinalOverridingIllusion {
	public static void main(String[] args) {
		OverridingPrivate2 op2=new OverridingPrivate2();
		op2.f();
		op2.g();
		OverridingPrivate op=op2;
		//op.f();
		//op.g();
		WithFinals wf=op2;
		//wf.f();
		//wf.g();
	}
}

運行結果:
OverridingPrivate2.f()
OverridingPrivate2.g()
覆蓋只能是某方法是基類的接口的一部分時纔會出現,即,必須能將一個對象向上轉型爲它的基本類型並調用相同的方法,如果某方法爲private,他就不是基類的接口的一部分。

3、final類

不能被繼承,final類中的所有方法都隱式指定爲是final的

二、Static

被static修飾的成員變量和成員方法獨立於該類的任何對象,可以直接通過類名訪問或者調用,它不依賴類特定的實例,被類的所有實例共享。(有點兒全局變量,全局方法的意思)

1、static變量

成員變量分爲兩種:
一種是被static修飾的變量,叫做靜態變量。
另一種是沒有被static修飾的變量,叫做實例變量。
由於靜態變量獨立於該類的任何對象,它只被初始化一次分配一次內存,而實例變量是每new一次初始化一次,分配一次內存。

2、static方法

靜態方法中不能用this和super關鍵字,構造方法不能被static修飾,不能直接訪問所屬類的實例變量和實例方法,只能訪問所屬類的靜態成員變量和成員方法。因爲static方法獨立於任何實例,所以static方法必須被實現,而不能是抽象的abstract。

3、static塊

在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,每個代碼塊只會被執行一次。

三、既是static又是final的域

static final用來修飾的域只佔據一段不能改變的存儲空間。 對於變量,表示一旦給值就不可修改,對於方法,表示不可覆蓋,並且都可以通過類名直接訪問。
既是static又是final的域全部用大寫表示,並使用下劃線分割各個單詞:
代碼演示:

class Value{
	int i;
	public Value(int i){
		this.i=i;
	}
}
public class FinalData {
 static Random rand=new Random(47);
 final int valueOne=rand.nextInt(20);//雖然爲final值,但是對象不同,值就不同
 static final int VALUE_TWO=rand.nextInt(20);//static初始化一次,final值不因對象的變化變化
 static final int VALUE_THREE=39;
private Value v1=new Value(11);
private final Value v2=new Value(22);
private static final Value VAL_3=new Value(33);
private final int a []={1,2,3,4,5,6};
String id;
FinalData(String id){this.id=id;}
public String toString(){
	return id+":"+"valueOne="+valueOne+",VALUE_TWO="+VALUE_TWO+",VALUE_THREE="+VALUE_THREE;
}
	public static void main(String[] args) {
		FinalData fd1=new FinalData("fd1");
		//fd1.valueOne++;final修飾的值不能改變
		fd1.v2.i++;//v2是final引用,它所指的對象的值是可以改變的
		fd1.v1=new Value(9);
		//fd1.v2=new Value(0);final引用不能改變引用所指的對象
		//fd1.VAL_3=new Value(1);final引用不能改變引用所指的對象
		//fd.a=new int[3];final引用不能改變引用所指的對象
		for(int i=0;i<fd1.a.length;i++)
			fd1.a[i]++;//final引用不變,但是它指向的對象的值在改變
		System.out.print("a[]= ");
		for(int t:fd1.a)
		System.out.print(t+" ");
		System.out.println();
		System.out.println("Creating new FinalData");
		FinalData fd2=new FinalData("fd2");
		FinalData fd3=new FinalData("fd3");
	    System.out.println(fd1);
	    System.out.println(fd2);
	    System.out.println(fd3);
	}
}

運行結果:

a[]= 2 3 4 5 6 7

Creating new FinalData

fd1:valueOne=15,VALUE_TWO=18,VALUE_THREE=39

fd2:valueOne=13,VALUE_TWO=18,VALUE_THREE=39

fd3:valueOne=1,VALUE_TWO=18,VALUE_THREE=39



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章