Java面向對象筆記 • 【第2章 面向對象進階】

全部章節   >>>>


本章目錄

2.1 成員變量

2.1.1 成員變量與局部變量的區別

2.1.2 成員變量的使用

2.1.3 實踐練習

2.2 this關鍵字

2.2.1 使用this關鍵字引用成員變量和成員方法

2.2.2 解決實例變量與局部變量同名的問題

2.2.3 實踐練習

2.3 隱藏和封裝

2.3.1 封裝

2.3.2 Java訪問控制符

2.3.3 實踐練習

2.4 static關鍵字

2.4.1 靜態成員變量

2.4.2 靜態方法

2.4.3 靜態代碼塊

2.4.4 實踐練習

總結:


2.1 成員變量

類體中定義的變量爲成員變量,作用範圍是整個類,只要在這個類中都可以訪問到它。

成員變量包括實例屬性了類屬性。

類屬性從類被加載開始存在,直到系統完全銷燬該類,類屬性的作用域與該類的生命週期相同

實例屬性則從類的實例被創建起開始存在,直到系統銷燬該實例,實例屬性的作用域與其對應的實例的生命週期相同

2.1.1 成員變量與局部變量的區別

類中的位置不同:

成員變量:在類中方法外面。

局部變量:在方法或者代碼塊中,或者方法的聲明上(即在參數列表中)。

內存中的位置不同:

成員變量在堆中(方法區中的靜態區)。

局部變量:在棧中。

生命週期不同:

成員變量隨着對象的創建而存在,隨着對象的消失而消失。

局部變量隨着方法的調用或者代碼塊的執行而存在,隨着方法的調用完畢或者代碼塊的執行完畢而消失。

初始值:

成員變量有默認初始值。

局部變量:沒有默認初始值,使用之前需要賦值,否則編譯器會報錯。

2.1.2 成員變量的使用

示例:測試英雄對象中成員屬性的賦值和引用

public class Hero {	
	String name;//英雄名字
	int  age;//英雄年齡

	public static void main(String[] args){
		//創建英雄對象hero1
		Hero hero1 = new Hero();
		hero1.name="德魯伊";  //爲hero1的實例屬性name賦值
		hero1.age=45;					
		//創建英雄對象hero2
		Hero hero2 = new Hero();
		System.out.println("英雄hero1的名字:"+hero1.name
			+"\t"+"年齡:"+hero1.age);
		System.out.println("英雄hero2的名字:"+hero2.name
			+"\t"+"年齡:"+hero2.age);	
	}
}

實例屬性內存分配示意圖

2.1.3 實踐練習

 

2.2 this關鍵字

1、this關鍵字代表自身

2、this關鍵字主要用途

  • this代表自身類的對象(直接使用this使用this引用成員變量、使用this調用成員方法)。
  • this在自身的構造方法內部調用其他的構造方法。

2.2.1 使用this關鍵字引用成員變量和成員方法

示例:測試在方法中使用this關鍵字引用成員變量和成員方法

public class Hero {
	public void jump(){
		System.out.println("---英雄遇到了障礙需要跳過去---");
	}
	public void run(){
		System.out.println("---執行run方法英雄正在奔跑---");
        		Hero hero = new Hero();//創建Hero對象
        		System.out.println("her對象已經被創建內存地址
        			爲:"+hero.hashCode()+",它將實行jump方法");
		hero.jump();//調用run()方法
	}
}
public class TestHero {
   	public static void main(String[] args){
		Hero hero = new Hero();//創建Hero對象
		System.out.println("hero對象已經被創建內存地址
       			爲:"+hero.hashCode()+",它將實行run方法");
		hero.run();//調用run()方法
	}
}

2.2.2 解決實例變量與局部變量同名的問題

示例:實例變量與句變量同名(實例變量前沒有this

public class Hero {
	 String name;

	 public void setName(String name){
		 name=name; //此處易混淆,可讀性差
	 }
	 public  static void main(String[] args){
		 Hero hero=new Hero();
		 hero.setName("風暴精靈");
		 System.out.println("hero的名字爲:"+hero.name);
	 }
}

分析:當方法中的局部變量與實例變量同名時,在方法中如果不使用this前綴調用實例變量,則在方法中默認調用方法中的局部變量(形參也是局部變量

示例:實例變量與句變量同名(實例變量前有this

public class Hero {
	 String name;

	 public void setName(String name){
		 this.name=name; 
	 }
	 public  static void main(String[] args){
		 Hero hero=new Hero();
		 hero.setName("風暴精靈");
		 System.out.println("hero的名字爲:"+hero.name);
	 }
}

2.2.3 實踐練習

 

2.3 隱藏和封裝

現實生活中的封裝

隱藏內部實現細節,封裝系統(部件、組件)功能

2.3.1 封裝

封裝是面向對象的三大特性之一

封裝對象的狀態信息隱藏在對象內部,不允許外部程序直接訪問對象內部信息,而是通過該類所提供的方法實現對內部信息的操作和訪問

封裝是面向對像編程語言對客觀世界的模擬,客觀世界中的屬性均被隱藏在對象內部,外界無法直接操作和修改

一個良好的封裝可以實現以下目的:

隱藏類的實現細節

使用者只能通過事先預定的方法訪問數據,從而可以在該方法中加入控制邏輯,限制對屬性的不合理訪問。

進行數據檢查,從而有利於保證對象信息的完整性

便於修改,提高代碼的可維護性

實現良好封裝的途徑:

隱藏對象的屬性和實現細節,不允許外部直接訪問

暴露出方法,讓方法控制對這些屬性進行安全的訪問和操作

封裝實際上有兩個方面的含義:隱藏該隱藏的,暴露該暴露

Java封裝的實質:使用訪問控制符private隱藏屬性,以及public暴露方法。

示例:利用封裝隱藏英雄屬性以及暴露屬性賦值和更新的方法

public class Hero {
	//使用private修飾屬性,隱藏這些屬性
	private String name;
	private int  age;

	//public方法公開對name屬性賦值
	public void setName(String name) {
		//執行合理校驗,要求用戶名必須在2~6之間
		if(name.length()>6||name.length()<2){
			System.out.println("您輸入的名字不符合要求");
			return;
		}else{
			this.name = name;
		}
	}
	//public方法公開對name屬性取值
	public String getName() {
		return name;
	}
	......
}

2.3.2 Java訪問控制符

Java通過修飾符來控制類、屬性和方法的訪問權限和其他功能,通常放在語句的最前端。

Java支持四種不同的訪問權限。

訪問控制級別圖:

Java訪問控制級別表:

訪問修飾符

同一個類中

同一個包中

子類中

所有類中

private

default

protected

public

示例:private訪問控制符修飾的屬性在同一個類中可以訪問

public class Person{
   private String name="李彥宏";  
 
   public static void main(String args[]){
       Person person = new Person();
       //同一類中可以訪問所有屬性
       System.out.println("姓名是:"+person.name); 
   }
}

示例:default訪問控制符修飾的屬性在同一個包中可以訪問

package com.vo;   
public class Person{
   //默認修飾符爲default
   String name="李彥宏"; 
}
 

public class Test{
    public static void main(String args[]){
        Person person = new Person();
        //訪問default修飾的屬性
        System.out.println(person.name);  
    }
}

示例:default訪問控制符修飾的屬性在同一個包中可以訪問

package com.vo;   
public class Person{
   //默認修飾符爲default
   String name="李彥宏"; 
}
 

public class Test{
    public static void main(String args[]){
        Person person = new Person();
        //訪問default修飾的屬性
        System.out.println(person.name);  
    }
}

示例:public訪問控制符修飾的屬性能夠被不同包中的類訪問

package com.vo;   
 
public class Person{
      //public爲公有訪問修飾符      
      public String name="李彥宏";
}
 
package com.test;   
public class Test{
       public static void main(String args[]){
                Person person = new Person();
                 //被public修飾的屬性在任何位置均可訪問
               System.out.println(person.name);
      }
}

2.3.3 實踐練習

 

2.4 static關鍵字

  • Java類的運行包括類加載和實例化兩個階段。
  • 一個類被加載至 JVM 中,靜態成員會被初始化。
  • 靜態成員不屬於某個對象,僅屬於靜態成員所在的類。

static 修飾的成員即爲靜態成員。

靜態代碼

靜態屬性

靜態方法

2.4.1 靜態成員變量

靜態成員變量屬於其所在類,被類中的所有實例共享

靜態成員變量可通過類直接訪問,也可通過類的實例訪問

示例:模擬個人銀行賬戶取款10

public class Bank {
	//靜態成員變量,賬戶餘額
	private static int count = 50000 ;
	public static void main(String[] args) {
	            //實例化10個Bank對象		
	            for(int i=0; i<10; i++){
		   Bank bank=new Bank();
		   //每次取款1000元,類的實例調用靜態成員屬性
		   bank.count = bank.count - 1000;
		  //Bank.count=Bank.count-1000; //通過類名之間訪問靜態成員
		   System.out.println("當前銀行總錢數="+Bank.count);
	        }
	}。
}

所有靜態成員變量都可以通過直接訪問。

2.4.2 靜態方法

  • static修飾的方法稱爲靜態方法
  • 靜態方法也可通過類名直接訪問,也可通過對象名訪問。
  • 靜態方法中不能訪問非靜態的成員,如實例屬性、實例方法
  • 靜態方法通常作爲工具方法因爲靜態方法不會因爲實例的不同,而影響方法最終的執行效果

示例:定義一個計算平方的靜態方法

public class MathUtils {
	//計算平方
	public static double square(double num){
		return num*num;
	}
    public static void main(String[] args){
    	double num=9.6;
    	double result=MathUtils.square(num);
    	System.out.println(num+"的平方="+result);
    }
}

爲什麼靜態方法不能訪問非靜態成員?

Java程序運行時首先由JVM加載類。

加載時會爲靜態的成員開闢內存空間,而實例成員在類的實例化       階段才被創建,所以當類加載時靜態的成員已經被創建,而此時並不存在實例成員,因此不能在靜態方法中訪問非靜態成員

但是實例方法可以訪問靜態成員。

2.4.3 靜態代碼塊

  • 如果需要在類加載時執行某一操作,則可以使用靜態代碼
  • 靜態代碼不存在任何方法體中,它在Java虛擬機加載類時執行
  • 如果類中包含多個靜態代碼塊,則Java虛擬機將按照它們在類中出現的順序依次執行
  • 靜態代碼塊只會被執行一次

爲什麼需要靜態代碼塊?什麼場合需要用到靜態代碼塊?

靜態方法在類加載後,雖然在內存中已經分配了內存空間,但只有顯式地調用靜態方法時,該方法纔會被執行。如果需要在類加載時執行某一操作,則可以使用靜態代碼塊

示例:靜態代碼塊程序演示

public class StaticBlock {
	//第一個靜態代碼塊
	static{
		System.out.println("---第一個靜態代碼塊---");
	}
	//第二個靜態代碼塊
	static{
		System.out.println("---第二個靜態代碼塊---");
	}
	//第三個靜態代碼塊
	static{
		System.out.println("---第三個靜態代碼塊---");
	}
              public static void main(String[] args){
    	        System.out.println("---main方法被執行了---");
              }
}

雖然main()方法是程序的入口方法,但該方法是在類加載完成後,由JVM虛擬機調用該方法

靜態代碼塊是在類加載就執行。

加載完靜態代碼塊後才執行main()方法。

2.4.4 實踐練習

 

總結:

  • 變量可以分爲成員變量和局部變量,成員變量是在類範圍定義的變量,局部變量是在方法中定義的變量
  • 成員變量分爲類屬性和實例屬性兩種,定義屬性時沒有static修飾符修飾的就是實例屬性類屬性的作用域與該類的生命週期相同例屬性的作用域與其對應的實例的生命週期相同
  • this關鍵字代表自身。
  • 封裝將對象的狀態信息隱藏在對象內部,不允許外部程序直接訪問對象內部信息,而是通過該類所提供的方法實現對內部信息的操作和訪問
  • Java訪問控制符可見性範圍由小到大爲:private->default->protected->public
  • 靜態成員變量屬於其所在類,被類中的所有實例共享,靜態成員變量可通過類直接訪問,也可通過類的實例訪問靜態方法不能訪問非靜態的成員
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章