[2014-02-27]JAVA筆記_Static關鍵字、代碼塊{}、main()、final關鍵字

Static關鍵字:可以用於修飾屬性,也可以用於修飾方法,還可以用於修飾類。

Static修飾屬性:無論一個類生產多少個對象,所有這些對象共同使用唯一一份靜態的成員變量;一個對象對該成員變量進行了修改,其他對象的該靜態成員變量的值也會隨之發生變化。如果一個成員變量是static的,那麼我們通過類名.成員變量名的方式來使用它(推薦使用這種方式)。

public class StaticTest{
	public static void main(String args[]){

		/*
		MyStatic myStatic = new MyStatic();
		MyStatic myStatic2 = new MyStatic();
		myStatic.a = 10;
		System.out.println(myStatic2.a);
		*/
		
		//使用類名訪問成員變量
		MyStatic.a = 10;
		System.out.println(MyStatic.a);
	
	}
}

class MyStatic{
	static int a;
}

在程序中使用static聲明屬性,則此屬性稱爲全局屬性(或成爲靜態屬性).

例1:使用static聲明屬性

class Person{
	String name;
	int age;
	static String country = "A城";			//使用static申明類屬性
	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	public void info(){
		System.out.println("姓名:" + this.name + " 年齡:"
		+ this.age + " 城市:" + this.country);
	}
};
public class StaticDemo02{
	public static void main(String args[]){
		Person p1 = new Person("張三", 30);
		Person p2 = new Person("李四", 30);
		Person p3 = new Person("王五", 30);
		System.out.println("------------修改之前---------");
		p1.info();
		p2.info();
		p3.info();
		System.out.println("------------修改之前---------");
		Person.country = "B城";			//直接修改static屬性
		p1.info();
		p2.info();
		p3.info();
		fun();
	}
	public static void fun(){
		System.out.println("靜態方法無法調用非靜態方法,必須有static關鍵字");
	};
}



static修飾方法:static 修飾的方法叫做靜態方法。對於靜態方法來說,可以使用類名.方法名 的方式來訪問。

public class StaticTest2{
	public static void main(String args[]){
	
		//MyStatic2 test = new MyStatic2();
		//test.output();
		
		MyStatic2.output();
	}
}

class MyStatic2{
	public static void output(){
		System.out.println("output");
	}
}


·靜態方法只能繼承,不能重寫(override)。
//靜態方法的繼承
public class StaticTest3{
	public static void main(String args[]){
		M m = new N();	//結果取決於調用着的類型
		//M m = new M();
		m.output();
	}
}

class M{
	public static void output(){
		System.out.println("M");
	}
}

class N extends M{
	public static void output(){
		System.out.println("N");
	}
}
//N類中的方法繼承了M中的方法。並隱藏了M中的方法
參考文獻:http://docs.oracle.com/javase/tutorial/java/IandI/override.html


例2:使用static聲明方法。使用static聲明的方法有時也成爲類方法

class Person{
	private String name;
	private int age;
	static String country = "A城";			//使用static申明類屬性
	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	public void info(){
		System.out.println("姓名:" + this.name + " 年齡:"
		+ this.age + " 城市:" + this.country);
	}
	public static void setCountry(String c){	//使用static申明方法
		country = c;			//修改static屬性
	}
	public static String getCountry(){
		return country;
	}
};
public class StaticDemo03{
	public static void main(String args[]){
		Person p1 = new Person("張三", 30);
		Person p2 = new Person("李四", 30);
		Person p3 = new Person("王五", 30);
		System.out.println("------------修改之前---------");
		p1.info();
		p2.info();
		p3.info();
		System.out.println("------------修改之前---------");
		Person.setCountry("B城");		//因爲是使用static聲明的方法,所以也可稱爲類方法
		p1.info();
		p2.info();
		p3.info();
	}
}

總結: 

        1. static聲明的方法是不能調用非static類型聲明的屬性或方法(因爲static得方法在裝載class得時候首先完成,比 構造方法早,此時非static得屬性和方法還沒有完成初始化。。。所以不能調用)。但是非static聲明的方法可以去調用static調用的屬性或方法。

        2. 使用 static 聲明的屬性或方法可以直接由類名稱調用。

        3. 只能訪問 static 聲明的屬性或方法,而非 static 聲明的屬性和方法是不能訪問,因爲 static 可以在對象沒有實例化時就直接調用,而其他的屬性或方法必須在對象實例化之後纔可以調用。


final關鍵字:final可以修飾 類、 方法、屬性。

final修飾類:當一個類被 final 所修飾時,表示該類是一個終態類,即不能被繼承。

public class FinalTest{
	public static void main(String args[]){
		
	}
}

final class E{	//該類不能被繼承

}

class F extends E{

}

final修飾方法:當一個方法被 final 所修飾時,表示改方法時一個終態方法,即不能被重寫(override)。

public class FinalTest2{
	public static void main(String args[]){
	
		H h = new H();
		h.output();
	}
}

class G{

	public final void output(){
	
		System.out.println("G");
	}
}

class H extends G{
	public  void output(){
		System.out.println("H");
	}
	
}

final 修飾屬性:當一個屬性被final 所修飾時,表示該屬性不能被改寫。

public class FinalTest3{
	public static void main(String args[]){
	
		People people = new People();
		people.age = 20;
	}
}

class People{
	final int age = 10;
}

//使用final修飾地址:
public class FinalTest3{
	public static void main(String args[]){
	
		People people = new People();
		
		//people.address = new Address();		//Error,將新的地址賦值給address引用

		people.address.name = "shanghai";	//修改的是address所指向的地址的內容
	}
}

class People{
	final Address address = new Address();	//將引用類型聲明爲final,意思是new出來的地址是不能改變的
}

class Address{
	String name = "bejing";
}
總結:當final 修飾一個原生數據類型時,表示該原生數據類型的值不能發生變化(比如說不能從8變爲20);如果final修飾的是一個引用數據類型時,表示該引用類型不能再指向其他對象了,但該引用所指向的對象的內容是可以發生變化的。

//final 陷阱
public class FinalTest4{
	final int a;	//必須顯示的給變量賦值,否則報錯。或者通過構造方法賦初值
	public FinalTest4(){
		a = 0;
	}

	public FinalTest4(int a){	//Error,因爲有2個構造方法,調用時不知道會先調用哪個構造方法
		//this.a = a;<span style="white-space:pre">		</span>//或者這樣也可以
	}
}

final陷阱:對於final 類型成員變量,一般來說有兩種賦初值方式:

                           a) 在聲明 final 類型成員變量時就賦上初值
                           b) 在聲明 final 類型成員變量時不賦初值,但在類的所有構造方法中都爲其賦上初值


·static 代碼塊: 靜態代碼塊。靜態代碼塊的作用也是完成一些初始化的工作。首先執行靜態代碼塊,然後執行構造方法。靜態代碼塊在類被加載的時候執行,而構造方法是在生成對象的時候執行;要想調用某個類生成對象,首先需要將類加載到 java 虛擬機上(JVM),然後由JVM 加載這個類生產對象。

//靜態代碼塊
public class StaticTest4{
	public static void main(String args[]){
		/*
		P p = new P();
		P p2 = new P();	//static只執行一次,因爲class只需要加載一次到JVM,然後每次new的時候執行構造方法。
		*/
		new S();	//因爲靜態代碼塊在加載到JVM的時候就執行了,所以先執行3個static方法,然後在依次查找子類上面的父類構造方法,從父類到一類依次執行。
		new S();
	}
}

class P{

	static{
		System.out.println("P static block");	//當將class文件加載到JVM時執行
	}

	public P(){
		System.out.println("P constructor");	//當 new 這個類生產對象的時候執行
	}
}

class Q extends P{
	static{
		System.out.println("Q static block");
	}
	public Q(){
		System.out.println("Q constructor");
	}
}
class S extends Q{
	static{
		System.out.println("S static block");
	}
	public S(){
		System.out.println("S constructor");
	}
}
 ·類的靜態代碼塊只會執行一次,是在類被加載的時候執行的,因爲每個類只會被加載一次,所以靜態代碼塊也只會被執行一次;而構造方法則不然,每次生成一個對象的時候都會調用類的構造方法,所以 new 一次就會調用構造方法一次。
 ·如果繼承體系中既有構造方法,又有靜態代碼塊,那麼首先執行最頂層的類的靜態代碼塊,一直執行到最底層的靜態代碼塊,然後在去執行最頂層類的構造方法,一直執行到最底層類的構造方法。注意:靜態代碼塊只會執行一次。

//靜態方法調用
public class StaticTest5{
	public static void main(String args[]){
		W w = new W();
		w.change();	
	}
}

class W{
	static int a = 10;

	int a = 10;	//不能在一個靜態方法裏面訪問一個非靜態的成員變量

	public static void change(){
	//public void change(){	//可以因爲a的值只有一份是全局的
		a++;
                this.a++;<span style="white-space:pre">	</span>//Error:this表示當前對象的引用。如果直接使用類名調用靜態方法的時候,就不存在對象,也就不知道this是什麼了
	}
}
//因爲每次new一個對象的時候都會有自己的一份a的值,所以在靜態方法不知道是修改了哪個a的值。
·不能在靜態方法中訪問非靜態成員變量;可以在靜態方法中訪問靜態的成員變量。可以在非靜態方法中訪問靜態的成員變量。
總結:靜態的只能訪問靜態的;非靜態的可以訪問一切。

·不能在靜態方法中使用 this 關鍵字。


java中的內存區域:

· 棧內存:可以保存對象的名稱

· 堆內存:保存每個對象的具體屬性

· 全局數據區:保存 static 類型的屬性

· 全局代碼區:保存所有方法的定義



main方法:

· public: 表示此方法可以被外部所調用

· static: 表示此方法可以由類名直接調用(執行一個java程序的時候,使用的是 java 類名稱)

· void: 主方法是程序的起點,所以不需要任何的返回值

· mian: 系統規定好的默認調用的方法名稱,執行的時候,默認找到main方法名稱

· String args[]: 表示的是運行時的參數

· 參數傳遞的形式: java 類名稱 參數1 參數2 參數3...


代碼塊:

概念:代碼塊是指用{}括起來的一段代碼,根據位置不同可以分爲  普通代碼塊、構造快、靜態代碼塊、同步代碼塊  4種。


class Demo{
	{					//定義構造快
		System.out.println("1、構造塊。");
	}
	static{				//定義靜態代碼塊
		System.out.println("0、靜態代碼塊。");
	}
	{					//定義構造方法
		System.out.println("2、構造方法。");
	}

}
public class CodeDemo03{
	static{				//在主方法所在的類中定義靜態塊
		System.out.println("在主方法所在的類中定義靜態塊");
	}
	public static void main(String args[]){
		new Demo();
		new Demo();
		new Demo();
	}
}
//執行順序:靜態代碼塊優先於主方法執行,而在類中定義的靜態代
//碼塊會優先於構造塊執行,而且靜態代碼塊只執行一次。



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