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");
}
}
//靜態方法的繼承
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();
}
}
//執行順序:靜態代碼塊優先於主方法執行,而在類中定義的靜態代
//碼塊會優先於構造塊執行,而且靜態代碼塊只執行一次。