static靜態的,能夠用來修飾變量,修飾方法,代碼塊,靜態內部類和靜態導包。 static關鍵字代表一個成員變量或方法在沒有所屬類的實例的狀況下被訪問。java
Java內存分爲,棧,堆,方法去和靜態域。 棧:存放的是局部變量,對象的引用名,數組的引用名。 堆:主要存放一些對象,也就是new出來的「東西」。 方法區:也叫字符串常量池。 靜態域:存放類中靜態的變量。 先看以下代碼:數組
public class TestStatic {
public static void main(String[] args) {
Supperman s1 = new Supperman("奧特曼", 800);
Supperman s2 = new Supperman("孫悟空", 1000);
System.out.println(s1);
System.out.println(s2);
}
}
class Supperman{
String name;
int age;
public Supperman(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "man [name=" + name + ", age=" + age + "]";
}
}
複製代碼
結果很簡單:ide
Supperman [name=奧特曼, age=800]
Supperman [name=孫悟空, age=1000]
複製代碼
再看看這段代碼的內存解析以下: 函數
綜上所述:若是不是靜態的,他就會在堆空間獨立佔有一塊,你修改s1屬性的值,不會影響到s2對應的值。 一樣是上面的代碼public class TestStatic {
public static void main(String[] args) {
Supperman s1 = new Supperman("奧特曼", 800);
Supperman s2 = new Supperman("孫悟空", 1000);
s1.sex = "男";
System.out.println(s1);
System.out.println(s2);
}
}
class Supperman{
String name;
int age;
String sex;
public Supperman(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Supperman [name=" + name + ", age=" + age + ", sex=" + sex
+ "]";
}
}
複製代碼
結果: Supperman [name=奧特曼, age=800, sex=男] Supperman [name=孫悟空, age=1000, sex=null] 如今更能夠看出,你改變一個對象的屬性值,不會影響其餘的對象,可是若是咱們加上static呢?測試
static String sex;
複製代碼
結果爲:this
Supperman [name=奧特曼, age=800, sex=男]
Supperman [name=孫悟空, age=1000, sex=男]
複製代碼
再看上述代碼的內存解析圖 spa
簡單來說就是:s1.name=""僅僅改變的是s1對象中name屬性值,不會影響s2中的name的值,可是s1.sex=""改變的但是全部該類的實例對象的sex的屬性值。當static修飾屬性時,由類建立的全部對象都共用這一個屬性。當其中一個對象對此屬性修改時,會致使其餘對象對此屬性的一個調用,靜態變量能夠經過類.類變量的形式來調用。類變量隨類的加載而加載的,並且只有一份,類變量的加載是早於對象的,類變量存在與靜態域中。 例如全部的中國人都有一個國家名稱,每個中國人都共享這個國家名稱,因此咱們沒必要爲中國人這個實例對象都單獨分配一個表明國家名稱的變量吧,這個時候就用到了static修飾變量。code
static修飾方法須要說明的是: 1.隨之類的加載而加載,在內存中也只有一份。 2.能夠直接經過類.類方法,普通的方法只能經過對象來調用。 3.內部能夠調用靜態的屬性和靜態方法,不能調用非靜態的屬性和方法,反之,非靜態的方法卻能夠調用靜態的屬性和方法。 4.靜態方法裏不能夠有this關鍵字和super關鍵字。 5.靜態的結構,例如靜態屬性,靜態方法,靜態代碼塊,內部類等等的生命週期要早於非靜態結構,被回收也要晚於非靜態結構。cdn
public class TestStatic {
public static void main(String[] args) {
Supperman.run();
}
}
class Supperman{
String name;
int age;
static String sex;
public static void run(){
System.out.println("sex"+sex);
System.out.println("超人飛走了!");
}
複製代碼
1.默認的初始化 2.顯示的初始化或者使用代碼塊進行初始化 3.使用構造器 4.經過屬性的setter方法進行修改對象
代碼塊的做用是用來初始化類的屬性,根據是否有static關鍵字修飾分爲靜態代碼塊和非靜態代碼塊 例若有以下類:
class Order{
private int orderId;
private String orderName;
public Order() {
super();
}
public Order(int orderId, String orderName) {
super();
this.orderId = orderId;
this.orderName = orderName;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", orderName=" + orderName + "]";
}
複製代碼
測試代碼以下:
public static void main(String[] args) {
Order o1 = new Order();
System.out.println(o1);
}
複製代碼
結果爲: Order [orderId=0, orderName=null] 下面就使用代碼塊來對屬性賦值。
1.裏面能夠有輸出語句。 2.隨着類的加載而加載,並且只被加載一次。 3.多個靜態代碼塊按照順序一次執行 4.靜態代碼快的執行要早於非靜態的 5.靜態的代碼塊裏只能執行靜態的結構(靜態屬性,靜態方法)
static{
System.out.println("我是靜態代碼塊");
}
複製代碼
1.能夠對類的屬性(靜態的或者非靜態)進行初始化操做,同時也能夠調用自身類中的方法(靜態的或者非靜態的) 2.裏面也能夠有輸出語句 3.一個類也能夠有多個非靜態的代碼塊,彼此之間順序執行, 4.每建立一個對象,非靜態類就加載一次,這個和靜態代碼塊不同 5.非靜態代碼塊的執行要在於構造器 在上述Order類中加入以下代碼
private int orderId = 1000;
private String orderName;
//初始化塊
{
orderId=1001;
orderName="AA";
}
複製代碼
一樣的測試語句,結果爲:
Order [orderId=1001, orderName=AA]
複製代碼
關於代碼塊的全部知識能夠經過下面這個代碼來解釋:
public class TestOrder {
public static void main(String[] args) {
Order o1 = new Order();
System.out.println(o1);
System.out.println("============我是帥氣分隔符========");
Order o2 = new Order();
System.out.println(o2);
}
}
class Order{
private int orderId = 1000;
private String orderName;
//初始化塊
static{
System.out.println("我是靜態代碼塊");
}
{
orderId=1001;
orderName="AA";
System.out.println("我是非靜態代碼塊1");
}
{
orderId=1002;
orderName="BB";
System.out.println("我是非靜態代碼塊2");
}
public Order() {
super();
}
public Order(int orderId, String orderName) {
super();
this.orderId = orderId;
this.orderName = orderName;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", orderName=" + orderName + "]";
}
}
複製代碼
執行結果爲:
我是靜態代碼塊
我是非靜態代碼塊1
我是非靜態代碼塊2
Order [orderId=1002, orderName=BB]
============我是帥氣分隔符========
我是非靜態代碼塊1
我是非靜態代碼塊2
Order [orderId=1002, orderName=BB]
複製代碼
若是咱們要使用靜態成員(方法和變量)咱們就要用類.類方法(類變量)。若是使用了靜態導包,就不用在給出類了,以下TestStaticPackge類
public class TestStaticPackge {
public static void output(){
System.out.println("Hello world");
}
}
複製代碼
若是咱們不使用靜態導包,訪問就是這個樣子的:
public static void main(String[] args) {
TestStaticPackge.output();
}
複製代碼
靜態導包的方法: import static 包名.類名.靜態成員變量;
import static 包名.類名.靜態成員函數;
注意導入的是成員變量和方法名。 例如上述:
import static com.java.study.TestStaticPackge.output;
public class TestOrder {
public static void main(String[] args) {
TestStaticPackge.output();//不使用靜態導包
output();//使用靜態導包
}
}
複製代碼
有static能夠脫離對象而執行,沒有就必須依賴對象