Static與this關鍵字
1static
static是什麼意思?靜止的;
他是一個屬性。
屬性:
靜态屬性:在類體中,方法外被static關鍵字修飾的。
成員屬性:在類體中,方法外沒有帶static關鍵字。
方法:
構造方法:不用寫傳回值類型,方法名為類名.
靜态方法:被static關鍵字修飾的方法 。static test();
成員方法:不帶static關鍵字的方法 。 test();
- 靜态變量
我們時常會遇到這樣一種情況,某個類的對象他們有一些共同的特點。
class TestUser
{
private String name; // 很可能不一樣
private int age; // 很可能不一樣
private String career; // 假設都是程式員
public TestUser() {
}
public TestUser(String sName,int uAge , String uCareer) {
name = sName;
age = uAge;
career = uCareer;
}
public String toString() {
return "{ " + name + ", " + age +", " + career + " }";
}
}
public class TestUser1
{
public static void main(String[] args) {
TestUser wrr = new TestUser("wrr", 21, "程式員");
TestUser lr = new TestUser("lr", 20, "程式員");
System.out.println(wrr);
System.out.println(lr);
/*輸出結果
{ wrr, 21, 程式員 }
{ lr, 20, 程式員 }
*/
}
}
其記憶體圖為:
在這裡我們可以看見career職業這個屬性對每個對象來說都是相同的,如果有很多的對象,他被大量的在堆記憶體中建立,這樣就造成了記憶體的浪費,此時我們就想,是否有什麼東西能夠讓他被重複的部分不被重複建立呢?答案就是static。
上面記憶體圖中可以看出jvm記憶體主要分為三大塊。
棧中主要儲存局部變量,堆中儲存成員變量,是以我們要把他存放在方法區記憶體中去。
被static修飾的變量,方法都會被存儲在方法區記憶體中。方法區記憶體最先加載内容且在其被加載完成之後内容就被固定了,static修飾的變量與方法在類被加載的時候被加載,若是變量則會在内加載的時候被指派,且與類加載一樣都隻執行一次。
那為什麼其可以被共用?因為其修飾的變量是與類一個級别的。是類中所有的對象都共有的,值是一樣的。我們用"類名."就可以使用它。我們可以把其了解為這是所有對象都共有的特征,比如人和動物都有個共同的概念,他們都是生命。
class TestUser
{
private String name; // 很可能不一樣
private int age; // 很可能不一樣
private static String career = "程式員"; // 假設都是程式員
public TestUser() {
}
public TestUser(String sName,int uAge) {
name = sName;
age = uAge;
}
public String toString() {
return "{ " + name + ", " + age +", " + career + " }";
}
}
public class TestUser1
{
public static void main(String[] args) {
TestUser wrr = new TestUser("wrr", 21);
TestUser lr = new TestUser("lr", 20);
System.out.println(wrr);
System.out.println(lr);
/*輸出結果
{ wrr, 21, 程式員 }
{ lr, 20, 程式員 }
與之前一樣
*/
}
}
是以說當我們遇到這種類中所有對象都共有一個成員屬性的時候我們把它設為靜态變量,而且因為他是累計别的對象是以我們需要用"類名."來通路他。
注意:靜态變量是類級别的,是以他在main函數壓棧之前便已經加載好了。
- 靜态代碼
既然有靜态變量,那麼也就存在靜态的代碼
static {
java語句;
java語句;
…………
}
public class TestUser1
{
private int i = 100;
static {
System.out.println("靜态代碼start");
System.out.println("i = " + i);
System.out.println("靜态代碼end");
//如果這裡輸出則說明i與類一起被加載靜态代碼後于main()
// TestUser1.java:7: 錯誤: 無法從靜态上下文中引用非靜态 變量 i
// System.out.println("i = " + i);
// ^
//由此可知其先于main
}
public static void main(String[] args){
System.out.println("main start");
System.out.println("main end");
}
}
public class TestUser1
{
private static int i = 100;
static {
System.out.println("靜态代碼start");
System.out.println("i = " + i);
System.out.println("靜态代碼end");
/*輸出結果
靜态代碼start
i = 100
靜态代碼end
main start
main end
這樣更加可以看出其順序。
*/
}
public static void main(String[] args){
System.out.println("main start");
System.out.println("main end");
}
}
順序:靜态代碼塊(以及類等)——main——調用
如果我們在靜态代碼塊中構造一個對象那麼其還是在堆記憶體中申請對象,隻不過說其引用位址存放在方法區記憶體中。
那麼不加static的代碼塊是什麼?可以被執行嗎?
執行個體代碼塊
{
java語句;
java語句;
…………
}
那麼他的執行順序又是如何呢?
public class TestUser1
{
public TestUser1(){
System.out.println("構造方法start");
}
private int i = 100;
{
System.out.println("執行個體代碼start");
System.out.println("i = " + i);
System.out.println("執行個體代碼end");
/*輸出結果
執行個體代碼start
i = 100
執行個體代碼end
構造方法start
執行個體代碼start
i = 100
執行個體代碼end
構造方法start
這樣更加可以看出其與構造方法有關,每次構造都會執行一次,且在構造方法之前。
*/
}
public static void main(String[] args){
TestUser1 t1 = new TestUser1();
TestUser1 t2 = new TestUser1();
}
}
當我們把career設為靜态變量後記憶體圖如下:
2.this關鍵字
this(這個)他被用來表示一個确定的對象。
通常用 this.變量
-應用執行個體
重名:在我們進行指派的時候會出現這樣一個問題,當成員變量和形參同名的時候,他的指派會出現問題,那麼是什麼問題?
class TestUser
{
private String name;
private int age;
private static String career = "程式員";
public TestUser() {
}
public TestUser(String name,int age) {
name = name;
age = age;
//因為就近原則這裡的name和age都是指構造方法中的形參本身。
//左為形參,右邊為實參的值相當于自己給自己指派,對于成員變量沒有影響。
}
public String toString() {
return "{ " + name + ", " + age +", " + career + " }";
}
}
public class TestUser1
{
public static void main(String[] args) {
TestUser wrr = new TestUser("wrr", 21);
TestUser lr = new TestUser("lr", 20);
System.out.println(wrr);
System.out.println(lr);
/*輸出結果
{ null, 0, 程式員 }
{ null, 0, 程式員 }
為什麼沒有被指派?因為在java中存在就近原則,這裡的兩個age都是指的同一個age即構造方法中的形參自然不存在指派。
*/
}
}
class TestUser
{
private String name;
private int age;
private static String career = "程式員";
public TestUser() {
}
public TestUser(String name,int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "{ " + name + ", " + age +", " + career + " }";
}
}
public class TestUser1
{
public static void main(String[] args) {
TestUser wrr = new TestUser("wrr", 21);
TestUser lr = new TestUser("lr", 20);
System.out.println(wrr);
System.out.println(lr);
/*輸出結果
{ wrr, 21, 程式員 }
{ lr, 20, 程式員 }
我們通過使用this關鍵字來解決這個問題,this标注後他表示左邊的name與age是成員變量與右邊的形參區分開來,這樣就實作了對變量的指派。
*/
}
}
//通過上面的例子我們可以對其功能有一定的了解,他指定了誰是成員變量。
this是什麼?
我們可以看到,this的使用方法是 this.變量
而’.‘的使用為 ” 引用 . 成員屬性 “由此可見this為一個引用他存的是一個位址即其所對應對象的堆記憶體首位址,這樣就不難了解了,’ . '是通過位址來調用對象中的成員變量以此來區分成員變量與局部變量。
記憶體圖如下:
同時,在很多的代碼中都存在this關鍵字來指定輸出的對象,例如println(xx),他是如何找到xx的就是省略了參數中的this,這個在檢視源碼的時候可以發現。