首先我們要知道什么是static以及instance
一. static(靜態(tài))
1. static關鍵字
- 一個類可以創(chuàng)建n個對象,如果n個對象中的某些數(shù)據(jù)需要n個對象共用窘奏,就需要使用static關鍵字修飾這些數(shù)據(jù)。
- Java中跟匆,一般情況下調(diào)用類的成員都需要先創(chuàng)建類的對象聋伦,然后通過類的對象進行調(diào)用度液。使用static關鍵字可以實現(xiàn)通過類名加“.”直接調(diào)用類的成員,不需要創(chuàng)建類的對象宙攻,但是類的對象也是可以調(diào)用的。
2. static修飾屬性
- 使用static修飾的屬性稱為靜態(tài)屬性或類變量。使用static修飾的屬性屬于類逾礁,不屬于具體的某個對象霹购。類屬性在類名首次出現(xiàn)時初始化,即使沒有創(chuàng)建對象溢陪,類屬性也是存在的萍虽。
3. static修飾方法
- 用static修飾的方法稱為靜態(tài)方法或者類方法,類方法不依賴于任何對象形真,用類名直接加“.”調(diào)用即可杉编,對象名也可以調(diào)用。使用static修飾的方法屬于類咆霜,不屬于具體的某個對象邓馒。類方法在類名首次出現(xiàn)時初始化,即使沒有創(chuàng)建對象蛾坯,類方法也是存在的光酣。
public class Boke {
public static void showDetails(String name,int age){
System.out.println("自我介紹一下,姓名:"+name+"脉课,年齡:"+age);
}
public static void main(String[] args) {
Boke.showDetails("張三",20);//類名調(diào)用靜態(tài)方法
}
}
4. static塊
還可以定義static塊
類名首次出現(xiàn)時救军,先為靜態(tài)變量分配內(nèi)存,然后調(diào)用靜態(tài)塊倘零,靜態(tài)塊可以為靜態(tài)變量初始化唱遭。還可以干別的事情。
靜態(tài)塊只在類名首次出現(xiàn)時調(diào)用一次视事,以后再也不調(diào)用了胆萧。
例如:
public class Demo{
//構造為實例變量初始化
public Demo(int i){
this.i = i;
}
//靜態(tài)塊,為static變量初始化俐东,靜態(tài)塊在首次類名出現(xiàn)時調(diào)用跌穗,但后于分配靜態(tài)變量。
static{
age = 20;
}
static int age=0;
int i;
}
二. instance(實例)
在面向?qū)ο蟪绦蛟O計中虏辫,“類”在實例化之后叫做一個“實例”蚌吸。 “類”是靜態(tài)的,不占進程內(nèi)存砌庄,而“實例”擁有動態(tài)內(nèi)存羹唠。
1. 實例變量
- 沒有使用static修飾的屬性稱為實例變量或叫成員變量
private String shopName;
private double shopPrice;
private int shopNum;
2. 實例方法
- 不使用static修飾的方法稱為實例方法
public double getAllTotal(){
if(this.goods==null){
throw new RuntimeException("商店中沒有任何商品奕枢,無法統(tǒng)計總金額");
}
double sum = 0;
for (int i = 0; i < goods.length; i++) {
sum += goods[i].getTotal();
}
return sum;
}
三. static和instance的區(qū)別
1. 大致區(qū)別
static:靜態(tài)(屬于類,只有一份)
instance:實例(實例也叫對象佩微,就是new出來的堆的內(nèi)存空間缝彬,實例是每個對象專有的,每new一次就分配一次內(nèi)存)
- 實例變量是在new類時在堆中分配內(nèi)存的哺眯。
- 構造函數(shù)可以為實例屬性初始化谷浅。構造函數(shù)不會為靜態(tài)屬性初始化。
- 由于靜態(tài)屬性是所有對象共有的奶卓,所有對象就是類一疯,因此靜態(tài)屬性也稱為類屬性,或者類變量夺姑,或者類成員墩邀。
- 既然靜態(tài)屬性屬于類,不屬于某個具體的對象盏浙,因此在new對象時眉睹,不會給靜態(tài)屬性分配內(nèi)存。那靜態(tài)時什么時候分配內(nèi)存呢只盹?
- 當在程序運行期間辣往,首次出現(xiàn)類名時,會暫時停止程序運行殖卑,去為類的靜態(tài)屬性分配內(nèi)存站削,然后繼續(xù)運行。
- 靜態(tài)變量被分配在方法區(qū)中孵稽,常駐內(nèi)存许起,永不回收。靜態(tài)變量只有一份菩鲜。相當于c語言的全局變量园细。
- 靜態(tài)變量由類名操作,由類名賦值接校,取值猛频。
- 類名調(diào)用靜態(tài)屬性時,可以省略類名蛛勉。
2. 靜態(tài)方法和實例方法的區(qū)別
1鹿寻、調(diào)用方式
在外部調(diào)用靜態(tài)方法時,可以使用 類名.方法名 的方式诽凌,也可以使用 對象.方法名 的方式毡熏,而實例方法只有后面這種方式。也就是說侣诵,調(diào)用靜態(tài)方法可以無需創(chuàng)建對象 痢法。
不過狱窘,需要注意的是一般不建議使用 對象.方法名 的方式來調(diào)用靜態(tài)方法。這種方式非常容易造成混淆财搁,靜態(tài)方法不屬于類的某個對象而是屬于這個類蘸炸。因此,一般建議使用 類名.方法名 的方式來調(diào)用靜態(tài)方法妇拯。
2幻馁、訪問類成員是否存在限制
- 靜態(tài)方法在訪問本類的成員時,只允許訪問靜態(tài)成員(即靜態(tài)成員變量和靜態(tài)方法)越锈,不允許訪問實例成員(即實例成員變量和實例方法),而實例方法不存在這個限制膘滨。
3. 靜態(tài)方法是不能調(diào)用非靜態(tài)成員的甘凭,為什么呢?
- 靜態(tài)方法是屬于類的火邓,在類加載的時候就會分配內(nèi)存丹弱,可以通過類名直接訪問。而非靜態(tài)成員屬于實例對象铲咨,只有在對象實例化之后才存在躲胳,需要通過類的實例對象去訪問。
public class Test {
public static void main(String[] args) {
}
public void sayHello(){
}
public static void sayHi(){
sayHello();
}
}//此時靜態(tài)方法是無法調(diào)用不知道是否存在的非靜態(tài)成員的
- 在類的非靜態(tài)成員不存在的時候靜態(tài)成員就已經(jīng)存在了纤勒,此時調(diào)用在內(nèi)存中還不存在的非靜態(tài)成員坯苹,屬于非法操作。