java構造函數,方法重載,this、super、finalize、static關鍵字及垃圾回收

、構造函數

1、構造函數:

       類中的構造方法用來初始化一個類,構造方法一般爲公有類型,沒有返回值。但是特殊情況是允許將構造函數定爲私有類型即通過private修飾,如單例模式中類的構造函數就是私有的。只允許在類的內部生成對象供外部訪問。

       定義形式一般爲:public+類名(數據類型1 變量1,數據類型2 變量2.......);當類中產生一個對象時,也就是通過關鍵字new一個對象時,構造方法就會被自動執行。如果程序中沒有寫構造方法,那麼編譯時會自動加上一個內部爲空的構造函數。如果在一個類中編寫了不爲空的構造函數,那麼系統就不會自動生成爲空的構造函數,所以要記得編寫一個爲空的構造函數。

2、方法重載:

      重載一般是相對於類中的方法而言的,方法重載是指在同一個類中可以有多個同名的方法,只要函數的參數列表不同即可,至於返回值類型可以相同也可以不同。

3.構造函數使用及重載:

(1)編程示例:

package com.jwang.facetoobject;

public class ConstructorAndOverload
{
	//成員變量的定義
	private int age;
	private String name;
	
	//無參數的構造函數
	public ConstructorAndOverload()
	{
		age = 10;
		System.out.println("無參數的構造方法正在執行。。。。。。。");
	}
	//構造函數重載,添加一個參數
	public ConstructorAndOverload(String x)
	{
		name=x;
		System.out.println("帶一個參數的構造方法正在執行。。。。。。。");
	}
	//構造函數重載,添加兩個參數
	public ConstructorAndOverload(String x,int y)
	{
		name=x;
		age=y;
		System.out.println("帶二個參數的構造方法正在執行。。。。。。。");
	}
	
	//成員方法1的定義
	public void shout()
	{
		int age = 60;
		//局部變量覆蓋全局變量,所以age打印的值爲60
		System.out.println(name+"`s age is "+age);
		System.out.println(name+"`s name is "+name);
	}
	//成員方法2的定義
	public void shout1()
	{
		System.out.println(name+"`s age is "+age);
		System.out.println(name+"`s name is "+name);
	}
	
	//成員方法3的定義:
	public void setAge(int x)
	{
		if(age<0)
                 return;
	         age=x;
	}
	//成員方法4的定義:
	public int getAge()
        {
		return age;
	}
	//成員方法4的定義,此方法接收一個對象類型的參數
	public void getsomeone(ConstructorAndOverload p)
	{
		//這裏的p是形參,new person()作爲實參會傳給形參。
		p.shout();
	}

	//主函數的定義使用
	public static void main(String [] args)
	{
		//new了一個對象p1,對象創建是會調用無參數的構造方法
		ConstructorAndOverload p1=new ConstructorAndOverload();
		//new了一個對象p2,對象創建會調用帶兩個參數的構造方法
		ConstructorAndOverload p2=new ConstructorAndOverload("張三",20);
		//new了一個對象p3,對象創建會調用帶一個參數的構造方法
		ConstructorAndOverload p3=new ConstructorAndOverload("王五");
		p1.age = -30;
		p1.name = "jwang";
		p1.shout();
		p1.shout1();
		
		p2.shout();
		p2.shout1();
		//對象作爲函數參數傳遞
        p1.getsomeone(p3);
	}
}

(2)測試結果:

4.java中的垃圾回收機制:

(1)如果某塊內存空間沒有任何引用指向它,那麼虛擬機就將其認定爲垃圾;這些垃圾不需要程序員自己釋放,jvm自帶垃圾回收機制

虛擬機並不是隨時隨地地立即回收垃圾,而是在系統比較空閒的時候,纔會執行回收任務。

(2)在程序中編寫System.gc()可以使得垃圾回收機制回收垃圾。

5.finalize()介紹:

(1)每一個類中都有一個finalize()方法,也有一個equals()方法。因爲這兩個方法是Object中的,而所有類默認繼承Object類

(2)當產生一個對象時,對象就會自動調用構造方法,所以當構造函數被調用的時候,就說明有對象產生了。類似的,當一個對象消亡之前,就會自動調用finalize()方法,就像人臨死前要交代後事一樣。所以當finalize()被調用的時候就說明有對象要消亡了。

(3)無論是構造方法還是finalize()方法被調用的時候,對象都是存在的。

(4)finalize()方法是在對象被當成垃圾從內存中釋放前調用,垃圾回收器的啓動不由程序員控制,也無規律可循,並不會一產生垃圾,他就被喚起,甚至有可能到程序結束他都沒有被啓動的機會。

(5)Java裏提供了system.gc()方法,使用這個方法能夠強制啓動垃圾回收器來回收垃圾。

程序示例:

package com.jwang.facetoobject;

public class TestFinalized
{
	// 成員變量的定義
	private int age;
	private String name;

	// 成員方法1的定義
	public void shout() 
	{
		int age = 60;
		System.out.println(name + "’s age is " + age);
	}

	// 成員方法2的定義:
	public void setAge(int x)
	{
		if (age < 0)
		{
			return;
		}
		age = x;
	}

	// 成員方法3的定義:
	public int getAge() 
	{
		return age;
	}

	// 成員方法4的定義,接收對象類型的參數
	public void getSomeone(TestFinalized p) 
	{
		p.shout();// testTestFinalized類方法內部調用TestFinalized類中的方法。
	}

	// 成員方法5的定義:
	public void fun1() 
	{
		System.out.println(name);
	}

	// 成員方法6的定義:
	public void fun2()
	{
		TestFinalized a2 = new TestFinalized("a2");
		a2.fun1();
		this.fun1();
		/*
		 * this是可以省略的,直接寫成fun1();也是可以的,就像同一個公司的職員在提及自己公司時省略公司名稱是一個道理 a1.fun1();
		 * 這樣調用就是錯誤的,因爲編譯時,fun2()中還不知道有a1對象,所以這裏要用this,
		 * 指fun2()被調用時所屬於的那個對象。也就是說fun2()運行時肯定是有一個對象在調用它,this就是指那個對象
		 */
	}

	// 複寫finalize()方法:
	// finalize()方法在程序中的對象變成垃圾將要被垃圾回收機制回收前自動調用;
	public void finalize() 
	{
		System.out.println("垃圾回收機制已經被喚醒,正在調用finalize方法");
	}

	// 無參數構造方法定義來給對象的屬性賦初值:
	public TestFinalized()
	{
		age = 10;
		System.out.println("============無參數的構造方法正在被調用===============");
	}

	// 定義一個帶一個參數的構造方法
	public TestFinalized(String name)
	{
		// this表示調用此構造函數的那個對象,this.name=name;相對於給那個對象的屬性name賦初值。賦值號右面的是傳進來的參數。
		this.name = name;
		System.out.println("============帶一個參數的構造方法正在被調用===============");
	}

	// 定義一個帶兩個參數的構造方法
	public TestFinalized(String name, int age) 
	{
		/*
		 * this.name = name; 上面一行的代碼和上一個構造方法的內容相同,可以用代碼實現這個構造方法對另一個構造方法的調用,
		 * 通過傳遞的參數的個數來確定哪個構造方法被調用,也就是說當一個構造方法調用另一個構造方法的時候, 必須要用this關鍵字。
		 */
		this(name);

		this.age = age;// this表示調用此構造函數的那個對象,this.age=age;相對於給那個對象的屬性name賦初值
		System.out.println("============帶兩個參數的構造方法正在被調用===============");
	}

	// 主函數的定義使用
	public static void main(String[] args) 
	{
		TestFinalized p1 = new TestFinalized();// new了一個對象p1
		TestFinalized p2 = new TestFinalized("張三", 20);// new了一個對象p2
		TestFinalized p3 = new TestFinalized("王五");
		p1.age = -30;// 對象的屬性賦值
		p1.shout();// 對象p1調用方法
		p2.shout();// 對象p2調用方法
		p1.getSomeone(p3);// p1通過getSomeone()方法調用p2的shout(),這種調用時可以的
		TestFinalized a1 = new TestFinalized("a1");
		a1.fun2();
		// 產生3個匿名對象,查看finalize()方法的作用
		new TestFinalized();
		System.gc();
		new TestFinalized();
		new TestFinalized();
		System.gc();// 垃圾回收機制的調用,相當於把收垃圾的叫過來,如果不加這個代碼,finalize方法可能不會立即被調用。
	}

}

測試結果:

二、this及super關鍵字:

1、this總結:

(1)this關鍵字說明:

Java關鍵字this只能用於方法體內。當一個對象創建後,Java虛擬機(JVM)就會給這個對象分配一個引用自身的指針,這個指針的名字就是this。因此,this只能在類中的非靜態方法中使用,靜態方法和靜態的代碼塊中絕對不能出現this,因爲靜態方法調用不需要創建對象。並且this只和特定的對象關聯,而不和類關聯,同一個類的不同對象有不同的this。下面給出一個使用this的綜合實例,以便說明問題:

(2)this關鍵字的應用實例

package com.jwang.facetoobject;

public class TestAboutThis 
{

	       private int number;
	   
	   private String username;
	   
	   private String password;
	   
	   private int x = 100;
	   
	   //定義一個帶一個參數的構造方法
	   public TestAboutThis(int n)
	   {
		   //下面還可以寫爲:this.number=n;構造方法被調用肯定是產生了一個對象,所以this表示當前對象
	       number = n; 
	   }
	   
	   //定義一個帶三個參數的構造方法
	   public TestAboutThis(int i, String username, String password)
	   {
	        // 成員變量和參數同名,成員變量被屏蔽,用"this.成員變量"的方式訪問成員變量.
	        this.username = username;
	        this.password = password;
	   }
	   
	   // 默認不帶參數的構造方法
	   public TestAboutThis()
	   {
		   //不帶參數的構造方法通過this調用另一個構造方法
	       this(0, "未知", "空"); 
	   }
	   
	   //定義一個帶一個參數的構造方法
	   public TestAboutThis(String name)
	   {
		    //帶一個參數的構造方法通過this調用另一個構造方法
	        this(1, name, "空"); 
	   }
	   
	   public static void main(String args[]) 
	   {
		    //產生一個實例對象,默認調用不帶參數的構造方法
	        TestAboutThis t1 = new TestAboutThis();
	        //產生另一個實例對象,默認調用帶一個參數的構造方法
	        TestAboutThis t2 = new TestAboutThis("遊客");
	        //第一個實例對象調用成員方法,並傳遞引用類型的數據變量t1.
	        t1.outinfo(t1);
	        //第二個實例對象調用成員方法,並傳遞引用類型的數據變量t2。
	        t2.outinfo(t2);
	   }
	   
	   private void outinfo(TestAboutThis t)
	   {
          //括號裏面表示該方法接受一個TestAboutThis類型的變量。
	      System.out.println("-----------");
	      System.out.println(t.number);
	      System.out.println(t.username);
	      System.out.println(t.password);
	      overed(); // 這個可以寫爲: this.overed();表示當前對象調用此方法
	   }
	   
	   private void overed()
	   {
	      //方法被對象調用,方法中有與類中成員變量同名的局部變量時,成員變量被屏蔽,用"this.成員變量"的方式訪問成員變量.
	       int x;
	       x = this.x++;
	       System.out.println(x);
	       System.out.println(this.x);
	    }
}

(3)運行結果展示:

(3)this使用情況總結

通過上面的例子,說明在什麼情況下需要用到this:

第一、通過this調用另一個構造方法,用法是this(參數列表),這個僅僅在類的構造方法中,別的地方不能這麼用。

第二、函數參數或者函數中的局部變量和成員變量同名的情況下,成員變量被屏蔽,此時要訪問成員變量則需要用“this.成員變量名”的方式來引用成員變量。當然,在沒有同名的情況下,可以直接用成員變量的名字,而不用this,用了也不爲錯,呵呵。

第三、在函數中,需要引用該函數所屬類的當前對象時候,直接用this。

其實這些用法總結都是從對“this是指向對象本身的一個指針”這句話的更深入的理解而來的,死記不然容易忘記而且容易搞錯,要理解!

2、super總結:

(1)super關鍵字說明;

super關鍵和this作用類似,是被屏蔽的成員變量或者成員方法或變爲可見,或者說用來引用被屏蔽的成員變量和成員成員方法。

不過super是用在子類中,目的是訪問直接父類中被屏蔽的成員,注意是直接父類(就是類之上最近的超類)。下面是一個綜合運用super的例子,有兩個類:一個Father類,一個Father類的子類Son,通過這兩個類完全演示了super的用法。

(2)super關鍵字的應用實例:

說明:此例子僅僅爲了說明super的用法,實際在設計類的時候一般都儘可能私有(private)化。

package com.jwang.facetoobject;

public class TestAboutSuperFather 
{
    public String v = "TestAboutSuperFather";
	
    public String x = "輸出了TestAboutSuperFather類的public成員變量x!!!";
    
    //父類中不帶參數的構造方法
    public TestAboutSuperFather() 
    {
        System.out.println("TestAboutSuperFather構造方法被調用!");
    }
    
    //父類中帶一個參數的構造方法
    public TestAboutSuperFather(String v)
    {
        this.v="TestAboutSuperFather類的帶參數構造方法!運行了.";
    }
    
    //父類中outinfo()方法,不帶參數
    public void outinfo()
    {
        System.out.println("TestAboutSuperFather的outinfo方法被調用");
    } 

}
package com.jwang.facetoobject;

public class TestAboutSuperSon extends TestAboutSuperFather
{
	public String v = "TestAboutSuperSon";

	public TestAboutSuperSon()
	{
		// 調用超類的構造方法,只能放到第一行
		super();

		System.out.println("TestAboutSuperSon無參數構造方法被調用!");

	}

	public TestAboutSuperSon(String str)
	{
		super(str);
		System.out.println("TestAboutSuperSon帶參數構造方法被調用!");
	}

	// 子類重寫了父類的成員方法outinfo()
	public void outinfo()
	{
		System.out.println("TestAboutSuperSon的outinfo()方法被調用");
	}

	public void test()
	{
		String v = "哈哈哈哈!"; // 局部變量v覆蓋了成員變量v和超類變量v
		System.out.println("------1-----");
		System.out.println(v); // 輸出局部變量v
		System.out.println(this.v); // 輸出(子類)成員變量v
		System.out.println(super.v); // 輸出超類成員變量v
		System.out.println("------2-----");
		System.out.println(x); // 輸出超類成員變量v,子類繼承而來
		System.out.println(super.x); // 輸出超類成員變量v
		System.out.println("------3-----");
		outinfo(); // 調用子類的outinfo()方法
		this.outinfo(); // 調用子類的outinfo()方法
		super.outinfo(); // 調用父類的outinfo()方法
	}

	public static void main(String[] args)
	{
		// 創建一個匿名對象調用test方法
		new TestAboutSuperSon().test();
	}
	
}

測試結果:

(3)通過上面的例子,下面總結一下super的用法:

第一:在子類構造方法中要調用父類的構造方法,用“super(參數列表)”的方式調用,參數不是必須的。同時還要注意的一點是:“super(參數列表)”這條語句只能用在子類構造方法體中的第一行。

第二:當子類方法中的局部變量或者子類的成員變量與父類成員變量同名時,也就是子類局部變量覆蓋父類成員變量時,用“super.成員變量名”來引用父類成員變量。當然,如果父類的成員變量沒有被覆蓋,也可以用“super.成員變量名”來引用父類成員變量,不過這是不必要的。

第三:當子類的成員方法覆蓋了父類的成員方法時,也就是子類和父類有完全相同的方法定義(但方法體可以不同),此時,用“super.方法名(參數列表)”的方式訪問父類的方法。

三、static關鍵字:

1.靜態成員變量:

(1)靜態成員變量的說明:

有時候,我們希望無論是否產生了對象或無論產生多少個對象的情況下,某些特定的數據在內存中只有一份,例如所有的中國人都有國家名稱,每一箇中國人都共享這個名稱,不必在每個中國人的實例對象中都單獨的分配一個用於代表國家名稱的變量。比如定義一個Chinese的類,類中有一個country=“中國”的成員變量。如果在他前面加上static關鍵字,那麼這個變量就是靜態成員變量。我們可以直接使用類名來訪問這個靜態的成員變量,還可以在類中的非靜態成員方法中像訪問其他成員非靜態成員變量一樣去訪問這個靜態的成員變量,當然了也可以用對象名來訪問這個靜態成員變量。

(2)靜態成員變量的使用示例:

package com.jwang.facetoobject;
public class TestStaticAboutProperty 
{
	   //定義靜態的成員變量
	   private static String country = "中國";
	   //定義靜態的成員變量
	   private static int age1 = 0;
	   //非靜態的成員變量的定義
	   private int age2 = 0;
	   
	   //定義一個非靜態的成員方法
	   public void singOurCountry()
           {
	       //訪問靜態成員變量的第一種方法:通過非靜態的成員方法來直接訪問
	       System.out.println("啊,親愛的"+country);
	   }
	   
	   @SuppressWarnings("static-access")
	   public static void main(String[] args)
          {
	       //訪問靜態成員變量的第二種方法:通過類名直接來訪問,不用產生對象
	       System.out.println("chinese country is"+TestStaticAboutProperty.country);
	       TestStaticAboutProperty ch1 = new TestStaticAboutProperty();//創建一個實例對象
	       //訪問靜態成員變量的第三種方法:通過對象名直接訪問。
	       System.out.println("chinese country is"+ch1.country);
	       ch1.singOurCountry();//對象調用方法,方法訪問靜態成員變量。
	       
	       TestStaticAboutProperty ch2 = new TestStaticAboutProperty();
	       TestStaticAboutProperty ch3 = new TestStaticAboutProperty();
	       TestStaticAboutProperty ch4 = new TestStaticAboutProperty();
	       
	       System.out.println("============第一次累加之後============");
	       System.out.println(++ch2.age1);
	       System.out.println(++ch2.age2);
	       System.out.println("============第二次累加之後============");
	       System.out.println(++ch3.age1);
	       System.out.println(++ch3.age2);
	       System.out.println("============第三次累加之後============");
	       System.out.println(++ch4.age1);
	       System.out.println(++ch4.age2);
	       
	   }
}

測試結果:

注意:我們不能把任何方法體內的變量聲明成靜態的。如:fun(){Static int i=0;}這樣的定義是非法的

2.靜態成員方法

(1)靜態成員方法說明:

我們有時也希望不必創建對象就可以調用某個方法,換句話說也就是使該方法不必和對象綁在一起。要實現這樣的效果,只需要在類中定義的方法前面加上static關鍵字即可,我們稱這種方法叫做靜態成員方法。同靜態成員變量一樣

第一:可以用類名直接訪問靜態成員方法。

第二:也可以用類的實例對象來訪問靜態成員方法。

第三:還可以在類的非靜態成員方法中,像訪問其他非靜態方法一樣訪問這個靜態的成員方法。

(2)靜態成員方法的使用:

package com.jwang.facetoobject;

public class TestStaticAboutProperty 
{
	   //定義靜態的成員變量
	   private static String country = "中國";
	   //定義靜態的成員變量
	   private static int age1 = 0;
	   //非靜態的成員變量的定義
	   private int age2 = 0;
	   
	   //定義一個非靜態的成員方法
	   public void singOurCountry()
	   {
		   //訪問靜態成員變量的第一種方法:通過非靜態的成員方法來直接訪問
	       System.out.println("啊,親愛的"+country);
	       addTest();
	   }
	   //定義一個靜態的成員方法
	   public static void test()
	   {
		   //靜態成員方法調用靜態成員方法
		   addTest();
	   }
	   
	   @SuppressWarnings("static-access")
	   //定義一個靜態的成員方法
	   public static void addTest()
	   {
		   TestStaticAboutProperty ch2 = new TestStaticAboutProperty();
	       TestStaticAboutProperty ch3 = new TestStaticAboutProperty();
	       TestStaticAboutProperty ch4 = new TestStaticAboutProperty();
	       System.out.println("============第一次累加之後============");
	       System.out.println(++ch2.age1);
	       System.out.println(++ch2.age2);
	       System.out.println("============第二次累加之後============");
	       System.out.println(++ch3.age1);
	       System.out.println(++ch3.age2);
	       System.out.println("============第三次累加之後============");
	       System.out.println(++ch4.age1);
	       System.out.println(++ch4.age2); 
	   }
	   
	   @SuppressWarnings("static-access")
	   public static void main(String[] args)
	   {
		   new TestStaticAboutProperty().singOurCountry();
		   //訪問靜態成員變量的第二種方法:通過創建對象來訪問
	       new TestStaticAboutProperty().addTest();
	       
	       //訪問靜態成員變量的第三種方法:通過類名直接訪問
	       TestStaticAboutProperty.test();
	       
	   }
	   
}

測試結果:

注意:

(1)靜態成員方法只能直接調用同類中的其他靜態成員(包括靜態成員變量和靜態的成員方法),而不能直接訪問類中的非靜態成員,這是因爲,對於非靜態的方法和變量,需要先創建類的實例對象之後纔可以被使用,而靜態方法在使用前不用創建任何對象。

(2)靜態成員方法不能以任何方式引用this和super關鍵字。與上面的道理一樣,因爲靜態方法在使用前不用創建任何實例對象,當靜態方法被調用的時候,this所引用的對象根本就還沒有產生。

(3)Main()方法是靜態的,因此jvm在執行main方法時不創建main方法所在類的實例對象,因而在main方法中,不能直接,訪問該類中的非靜態成員,必須創建該類的一個實例對象後,才能通過這個對象去訪問該類中的非靜態成員。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章