來看看一個程式片段:
class Ball {
double radius;
final double PI = 3.14159;
...
}
如果你建立了多個Ball物件,那每個Ball物件都會有自己的radius與PI成員:
不過我們都知道,圓周率其實是個固定的常數,不用每個物件各自擁有,你可以在PI上宣告static,表示它屬於類別:
class Ball {
double radius;
static final double PI = 3.141596;
...
}
被宣告為static的成員,不會讓個別物件擁有,而是屬於類別,如上定義後,如果建立多個Ball物件,每個Ball物件只會各自擁有radius:
被宣告為static的成員,是將類別名稱作為名稱空間,也就是說,你可以如下取得圓周率:
System.out.println(Ball.PI);
也就是透過類別名稱與.運算子,就可以取得static成員。你也可以將宣告方法為static成員。例如:
class Ball {
double radius;
static final double PI = 3.141596;
static double toRadians(double angdeg) { // 角度轉徑度
return angdeg * (Ball.PI / 180);
}
}
被宣告為static的方法,也是將類別名稱作為名稱空間,可以透過類別名稱與.運算子來呼叫static方法:
System.out.println(Ball.toRadians(100));
雖然語法上,也是可以透過物件名稱存取static成員,但非常不建議如此撰寫:
Ball ball = new Ball();
System.out.println(ball.PI); // 極度不建議
System.out.println(ball.toRadians(100)); // 極度不建議
Java程式設計領域,早就有許多良好命名慣例,沒有遵守會造成溝通與維護的麻煩。以static使用慣例來說,是透過「大寫開頭類別名稱.運算子」來存取,所以只要看到這種寫法,就會知道它是static成員。例如我們一直在用的System.out,沒錯!out就是System擁有的static成員!!
java允許我們在一個類裡面定義靜態類。比如內部類(nested class)。把nested class封閉起來的類叫外部類。在java中,我們不能用static修飾頂級類(top level class)。只有內部類可以為static。
靜態內部類和非靜態內部類之間到底有什麼不同呢?下面是兩者間主要的不同。
(1)內部靜態類不需要有指向外部類的引用。但非靜態內部類需要持有對外部類的引用。
(2)非靜態內部類能夠訪問外部類的靜態和非靜態成員。靜態類不能訪問外部類的非靜態成員。他只能訪問外部類的靜態成員。
(3)一個非靜態內部類不能脫離外部類實體被建立。
在kotlin中需要static時,
以下用「建立」來代表當一個變數或類別開始佔有記憶體空間。
class MainActivity : AppCompatActivity() {
//非靜態變數
//MainActivity被實例化時才會「建立」
//實例化了10個MainActivity就有10個變數i
val i = 1
//靜態內部類別
//MainActivity被class loader「建立」時,一併將A「建立」
//內部成員皆為靜態,將一併被「建立」
object A{
const val constA = 1
val a = 1
}
//靜態內部類別
//MainActivity被class loader「建立」時,一併將B「建立」
//內部成員皆為靜態,將一併被「建立」
//與object不同的是,內部成員皆隸屬於外部類別
companion object B{
const val constB = 1
val b = 1
}
//靜態內部類別
//MainActivity被class loader「建立」時一併被「建立」
//內部成員皆為非靜態
class C{
var c1 = 0
}
//非靜態內部類別
//MainActivity被實例化時才會「建立」
inner class D{
var d2 = 0
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
-------------------decompile之後----------------
public final class MainActivity extends AppCompatActivity {
//非靜態變數i
private final int i = 1;
public final int getI() {
return this.i;
}
//object A
public static final class A {
public static final int constA = 1;
private static final int a = 1;
public static final MainActivity.A INSTANCE;
public final int getA() {
return a;
}
private A() {
}
static {
MainActivity.A var0 = new MainActivity.A();
INSTANCE = var0;
a = 1;
}
}
//companion object B
public static final int constB = 1;
private static final int b = 1;
public static final MainActivity.B B = new MainActivity.B((DefaultConstructorMarker)null);
public static final class B {
public final int getB() {
return MainActivity.b;
}
private B() {
}
// $FF: synthetic method
public B(DefaultConstructorMarker $constructor_marker) {
this();
}
}
//class C
public static final class C {
private int c1;
public final int getC1() {
return this.c1;
}
public final void setC1(int var1) {
this.c1 = var1;
}
}
//inner class D
public final class D {
private int d2;
public final int getD2() {
return this.d2;
}
public final void setD2(int var1) {
this.d2 = var1;
}
}
}
你各位應該一清二楚了吧
霸脫如有講錯的地方請趕快糾正我
參考資料:
1.那些kotlin中的靜態事
2.static類別成員
3.Java中靜態內部類和非靜態內部類