1. 爲何要使用靜態變量、常量和方法java
一般,在處理問題,會遇到多個不一樣的類要使用同一變量,常量或方法,然而,同一個常量在不一樣的類中建立時系統都會爲之分配內存,形成內存浪費,若是能將這些不一樣類中的變量共享到一個內存中,那就大大減小了內存的使用,而靜態變量(關鍵字 static)就是解決這個問題的。以下圖所示:函數
2. 被聲明的static的變量,常量和方法被稱爲靜態成員,靜態成員屬於類全部,區別於個別對象,能夠在本類或其餘類使用類名「.」運算符調用靜態成員。以下代碼:ui
1 public class AnyThing { 2 static double PI = 3.1415; //在類中定義靜態常量 3 static int id; //在類中定義靜態變量 4 public static void method1(){ //在類中定義靜態方法 5 6 } 7 public void method2(){ 8 System.out.println(AnyThing.PI); //調用靜態常量 9 System.out.println(AnyThing.id); //調用靜態變量 10 AnyThing.method1(); //調用靜態方法 11 } 12 }
注意:(1) 雖然靜態成員可使用「對象.靜態成員」的形式進行調用,但一般不這麼使用,這樣容易混淆靜態成員和非靜態成員。this
(2) 在靜態方法中不可使用this關鍵字。code
(3) 在靜態方法中不能夠直接調用非靜態方法。orm
(4) 在Java中規定不能將方法中的局部變量聲明爲static的。對象
(5) 若是在執行類時,但願先執行類的初始化動做,可使用static定義一個靜態區域,例如blog
1 public class example{ 2 static{ 3 ... 4 } 5 }
當這段代碼被執行時,首先執行static塊中的程序,而且只會執行一次,即在類加載的時候就被執行,以後執行main()方法。而且只是自上而下的順序執行。繼承
3.在java中,靜態方法和普通方法的區別:內存
一、在外部調用靜態方法時,可使用"類名.方法名"的方式,也可使用"對象名.方法名"的方式。而實例方法只有後面這種方式。也就是說,調用靜態方法能夠無需建立對象。 二、靜態方法在訪問本類的成員時,只容許訪問靜態成員(即靜態成員變量和靜態方法),而不容許訪問實例成員變量和實例方法;實例方法則無此限制。 三、程序的static塊只能調用靜態方法,不能調用實例的方法。 若是要追溯其區別的根源,能夠這樣理解:在編譯期間靜態方法的行爲就已經肯定,而實例方法只有在運行期間當實例肯定以後才能肯定。
基本練習
package test_01; public class static_class { static int a =100; int b=200; //實例變量 public static void main(String[] args) { // TODO Auto-generated method stub // static int a =100; //局部變量不能定義static System.out.println("主函數"); static_fangfa(); //public_fangfa(); //也不能在靜態函數中調用靜態函數 ,除非把非靜態函數變爲靜態函數 } // 靜態塊 static { System.out.println("靜態塊"); } public static_class() { // TODO Auto-generated constructor stub System.out.println("構造方法"); } private static void static_fangfa() { System.out.println("靜態函數"); static_class static_class1 =new static_class(); System.out.println(static_class1.a); // System.out.println(static_class.b); // 靜態函數裏面不能調用靜態變量 } public void public_fangfa() { int c = 100+b; System.out.println("非靜態函數"+c); } }
輸出結果:
靜態塊 主函數 靜態函數 構造方法 100
4.靜態代碼段
a. 靜態代碼塊只能定義在類裏面,它獨立於任何方法,不能定義在方法裏面
b.靜態代碼塊裏面的變量都是局部變量,只在本塊內有效
c.靜態代碼塊會在類被加載時自動執行,而不管加載者是JVM仍是其餘的類
d. 一個類中容許定義多個靜態代碼塊,執行的順序根據定義的順序進行
e.靜態代碼塊只能訪問類的靜態成員,而不容許訪問實例成員
5.java中的初始化順序
JAVA類首次裝入時,會對靜態成員變量或方法進行一次初始化,但方法不被調用是不會執行的,靜態成員變量和靜態初始化塊級別相同,非靜態成員變量和非靜態初始化塊級別相同。
初始化順序:先初始化父類的靜態代碼--->初始化子類的靜態代碼-->
(建立實例時,若是不建立實例,則後面的不執行)初始化父類的非靜態代碼(變量定義等)--->初始化父類構造函數--->初始化子類非靜態代碼(變量定義等)--->初始化子類構造函數
類只有在使用New調用建立的時候纔會被JAVA類裝載器裝入建立類實例時,首先按照父子繼承關係進行初始化類實例建立時候,首先初始化塊部分先執行,而後是構造方法;而後從本類繼承的子類的初始化塊執行,最後是子類的構造方法類消除時候,首先消除子類部分,再消除父類部分
static 函數名() --> 能夠經過 類名.函數名() 調用,也能夠經過 類對象.函數名() 調用;
函數名() -->只能經過類對象.函數名() 調用;
6.Java靜態對象和非靜態對象的區別
靜態對象 非靜態對象
擁有屬性: 是類共同擁有的 是類各對象獨立擁有的
內存分配: 內存空間上是固定的 空間在各個附屬類裏面分配
分配順序: 先分配靜態對象的空間 繼而再對非靜態對象分配空間,也就是初始化順序是先靜態再非靜態。
7.Java靜態對象的特色
A,靜態對象的數據在全局是惟一的,一改都改。若是你想要處理的東西是整個程序中惟一的,弄成靜態是個好方法。非靜態的東西你修改之後只是修改了他本身的數據,可是不會影響其餘同類對象的數據。
B,引用方便。直接用類名.靜態方法名 或者 類名.靜態變量名就可引用而且直接能夠修改其屬性值,不用get和set方法。
C,保持數據的惟一性。此數據全局都是惟一的,修改他的任何一處地方,在程序全部使用到的地方都將會體現到這些數據的修改。有效減小多餘的浪費。
D,static final用來修飾成員變量和成員方法,可簡單理解爲「全局常量」。對於變量,表示一旦給值就不可修改;對於方法,表示不可覆蓋。
8.靜態變量、靜態方法和靜態塊
一般狀況下,類成員必須經過它的類的對象訪問,可是能夠建立這樣一個成員,它可以被它本身使用,而沒必要引用特定的實例。在成員的聲明前面加上關鍵字static就能建立這樣的成員。若是一個成員被聲明爲static,它就可以在它的類的任何對象建立以前被訪問,而沒必要引用任何對象(跟類是否有static修飾無關)。
你能夠將方法和變量都聲明爲static。static 成員的最多見的 例子是main( ) 。聲明爲static的方法有如下幾條限制: ·
A,它們僅能調用其餘的static 方法
B,它們只能訪問static數據
C,它們不能以任何方式引用this 或super(this涉及到對象,super 與繼承有關)
示例:Static 塊僅在該類被加載時執行一次。下面的例子顯示的類有一個static方法,一些static變量,以及一個static 初始化塊。
public class TestNew { static int a = 3; static int b; static void meth(int x){ System.out.println("x = "+x); System.out.println("a = "+a); System.out.println("b = "+b); } static { System.out.println("static block initialized"); b = a*4; } public static void main(String[] args) { // TODO Auto-generated method stub meth(42); } }
執行結果是:
static blockinitialized x = 42 a = 3 b = 12
上述classTestNew的執行順序是:首先static 塊執行(打印一條消息),a被設置爲3,最後b被初始化爲a*4 成12。而後調用main(),main () 調用meth() ,把值42傳遞給x。3個println ( ) 語句引用兩個static變量a和b,以及局部變量x 。
9.外部使用靜態變量或者靜態方法
在定義它們的類的外面,static方法和變量能獨立於任何對象而被使用,你只要在類的名字後面加點號運算符便可。能夠看到,這種格式與經過對象引用變量調用非static方法或者變量的格式相似。示例:
class StaticDemo{ static int a = 42; static int b = 99; static void callme(){ System.out.println("a = "+a); } } public class TestNew { public static void main(String[] args) { // TODO Auto-generated method stub StaticDemo.callme(); System.out.println("b = "+StaticDemo.b); } }
執行結果:
a = 42 b = 99
10.靜態內部類
靜態內部類是指在一個類的內部,又定義了一個用static修飾的類。
A,首先,用內部類是由於內部類與所在外部類有必定的關係,每每只有該外部類調用此內部類。因此沒有必要專門用一個Java文件存放這個類。
B,靜態方法、靜態成員變量。它惟一的做用就是隨着類的加載(而不是隨着對象的產生)而產生,以至能夠用類名+靜態成員名直接得到。這樣靜態內部類就能夠理解了,它能夠直接被用外部類名+內部類名得到。
public class Build { .............. public static class VERSION { ................ public static final String RELEASE =getString("ro.build.version.release"); ................ } ................ }
在外部能夠直接經過Build.VERSION.RELEASE來訪問。
11. 靜態常量
靜態常量不可變,能夠直接被訪問,如類名.靜態常量名。例如:
public class MathTest{ public static final double PI= 3.1415926; }
能夠直接採用MathTest.PI的形式訪問該PI常量。
13. 靜態類與內部類的區別
內部類
一、內部類擁有普通類的全部特性,也擁有類成員變量的特性
二、內部類能夠訪問其外部類的成員變量,屬性,方法,其它內部類
靜態內部類
一、只有內部類才能聲明爲static,也能夠說是靜態內部類
二、只有靜態內部類才能擁有靜態成員,普通內部類只能定義普通成員
三、靜態類跟靜態方法同樣,只能訪問其外部類的靜態成員
四、若是在外部類的靜態方法中訪問內部類,這時候只能訪問靜態內部類
/** * 外部類,不能聲明爲 static * * @author zhanqi * */ public class OuterClass { private int ab = 1; private static int sab = 2; /** * 普通內部類 */ public class NormalInnerClass { // private static int age = 22; private int age = 22; // 不能聲明爲static public NormalInnerClass() { // 能夠訪問外部類靜態與非靜態成員 System.out.println(ab); System.out.println(sab); } } /** * 靜態內部類 */ public static class StaticInnerClass { // 定義靜態與非靜態成員都是能夠的 private static int age = 22; private int age2 = 22; private void echo() { // System.out.println(ab); System.out.println(sab);// 只能訪問外部類的靜態成員 } } }
內部類實例化
1.訪問內部類,必須使用:外部類.內部類,OutClass.InnerClass
2.普通內部類必須綁定在其外部類的實例上
3.靜態內部類能夠直接 new
/** * 外部類訪問內部類 */ public class OuterClass {/** * 普通方法 */ public void method() { StaticInnerClass sic = new StaticInnerClass(); NormalInnerClass nic = new NormalInnerClass(); }/** * Main */ public static void main(String[] args) { // 在靜態方法中,只能訪問靜態成員,靜態內部類 // NormalInnerClass nic = new NormalInnerClass(); StaticInnerClass sic = new StaticInnerClass(); } }/** * 其它類訪問內部類 */ class Test { public static void main(String[] args) { /** * 1:其它類訪問內部類,必須使用:外部類.內部類,OutClass.InnerClass * 2:普通內部類必須綁定在其外部類的實例上 * 3:靜態內部類能夠直接 new */ OuterClass.StaticInnerClass sic = new OuterClass.StaticInnerClass(); // OuterClass.NormalInnerClass n = new OuterClass.NormalInnerClass();OuterClass oc = new OuterClass(); OuterClass.NormalInnerClass nic = oc.new NormalInnerClass(); } }
靜態對象
靜態對象咱們常用,可是對靜態對象和非靜態對象的區別卻並不必定那麼瞭解。下表格就是靜態對象和非靜態對象主要區別。
1.擁有的對象,靜態對象是類共同擁有的 ,而非靜態對象是由類單獨擁有; 2.內存空間,靜態對象內存空間是固定,非靜態類對象是附着相關類的分配; 3.分配順序,先分配靜態對象的空間,而後纔會分配非靜態對象也就是初始化。