Java面向物件——類與方法
面向物件——能進行現實生活的抽象
世界是由一系列物件互相組合形成(多個物件之間的相互協作),每個物件有自己的屬性和方法。
通俗解釋:狗吃糧,狗和糧是兩個物件 ,吃是行為
每個物件——類,每個類有自己的屬性及方法
新興的程式設計正規化:
面向切面程式設計:EE-AOP
面向介面程式設計——介面優先原則
函數語言程式設計:Scala(JVM)
面向物件名字擴充套件:
面向物件三大特徵:
a.封裝性:將客觀事物封裝成抽象的類,,每個類都有自己的屬性與方法,並且類可以讓自己的資料與犯法只讓可信的類或物件操作,對不可信的進行資訊隱藏。內部操作對外部而言不可見,強調保護性
b.繼承性:可以實現現有類的所有功能,並且在無語重新編寫原有類程式碼的情況下進行功能上的擴充套件。
c.多型性:一個類例項的相同方法在不同情形下有不同的表現形式。好處:多型機制使得具有不同內部結構的物件可以共享相同的外部介面。(利用多型可以得到良好的設計)
類與物件的定義與使用
class 類名稱 {
屬性1;
屬性2;
屬性n...;
方法1(){}
方法2(){}
方法n(){}...
}
- 類是共性的概念;物件是一個具體的、可以使用的事物。
- 類的組成:方法(操作的行為)and屬性(變數,描述每個物件的具體特點)
- 類是生產物件的藍圖,先有類才可以產生物件。物件的所有屬性與行為,一定在類中進行了完整定義。
- 類中的屬性與方法(不帶static關鍵字的)只能通過物件呼叫
- 類的設計原則:編寫類時,沒有額外說明,所有屬性必須使用private封裝(成員變數)
- 類定義順序:
定義屬性 -> 定義構造方法 -> 定義普通方法
物件的產生:
物件在主方法中產生
產生語法:
類名稱 物件名稱 = new 類名稱
物件記憶體分析:
- 先簡單的將Java中的記憶體區域分為棧記憶體和堆記憶體兩塊區域
棧記憶體(虛擬機器區域性變量表):存放的是區域性變數(各種基本資料型別/物件引用-物件名字)
堆記憶體:儲存物件(new表示在堆上新分配空間)
垃圾空間:沒有任何棧記憶體指向的堆記憶體空間
構造方法:
- 抽象出一個類,若沒有給予一個構造方法,則有一個預設的構造方法;若給予了一個構造方法,則沒有預設的構造方法。
預設的構造方法:
public 類名(){
}
- 意義:類中屬性初始化
1Person 2person = 3new 4Person();
1類名:通過哪個類產生物件
2產生的物件名,引用一塊堆記憶體
3開闢一塊堆記憶體
4構造方法
疑問:
Person person;
Person person=null;
上述兩種表達有何不同???
解答:
第一種只是宣告,沒有初始化,無法通過編譯;第二種是將person初始化為null,執行時可能會出現空指標異常。
-
三大特徵:
a.構造方法名稱必須與類名稱相同
b.構造方法沒有返回值型別宣告(構造本身有返回值,返回當前構造的物件)
c.每個類中一定至少存在一個構造方法。如果沒有明確定義,系統會自動生成無參構造;若在類中自定義了構造方法,則 系統不會自動生成無參構造。
- 屬性、構造方法、普通方法
屬性是在物件開闢堆記憶體時開闢的空間
構造方法是在使用new後呼叫的
普通方法是在空間開闢了、構造方法執行之後可以多次呼叫的
- 構造方法過載:引數個數不同,可以創建出不同屬性資訊的物件
- 在進行類定義時:定義屬性 -> 定義構造方法 -> 定義普通方法
- 匿名物件:
new Person("張三",20).getPersonInfo();
由於匿名物件不會有任何的棧空間所指向,所以使用一次後就成為垃圾空間。
this關鍵字
a.表示呼叫方法
只要在類中訪問類的屬性,一定要加上this關鍵字
b.表示呼叫本類方法
(1)呼叫普通方法 this.方法名(引數)
當有類的繼承關係時,表示本類方法一定要加上this關鍵字。否則,可加可不加。
(2)呼叫構造方法 this.(引數)
this呼叫構造方法必須放在構造方法首行;this呼叫構造方法不允許成環
c.表示當前物件
程式碼示例:
public class OOP{
String name;
int age;
//無參的構造方法
public OOP(){
}
//構造方法過載
//有參的構造方法
public OOP(String name,int age){
this.name=name; //物件的名字=賦值的名字
this.age=age;
}
String personInfo(){
return "這個人叫"+name+"年齡"+age;
}
//具體物件
public static void main(String [] args){
//物件1
//建立物件
OOP per1=new OOP();
//對屬性賦值
per1.name="Tom";
per1.age=18;
//物件2
OOP per2=new OOP();
per2.name="Mary";
per2.age=20;
//物件3
OOP per3=new OOP("Alice",22);
//引用傳遞
//per1物件引用的地址賦值給砰然
OOP per4=per1;
per4.age=25;
//per1變數引用指向空
//per1=null;
//per4=null;//堆上的person物件已經沒有變數引用它,但依然存在
//呼叫物件的方法
System.out.println(per1.personInfo());
System.out.println(per2.personInfo());
System.out.println(per3.personInfo());
}
}
private實現封裝
將屬性、方法用private封裝後表示,被封裝的屬性與方法只能在本類中使用,類外部不可見。此時想要訪問被封裝的屬 性,必須提供getter和setter方法
- setter方法:主要進行屬性內容的設定與修改
getter方法:主要進行屬性內容的取得
- 當類中有一個屬性不希望被外部訪問或修改,則不需寫setter方法
程式碼示例:
public class OOP{
private String name;
private int age;
private String secret="***";
private String hobby;
//假設建立物件時必須同時賦予名字,因此,不提供無參的構造方法
//有參的構造方法
public OOP(String name){
this.name=name; //物件的名字=賦值的名字
}
//方法、行為
public String personInfo(){
return "這個人叫"+name+",年齡是"+age+",愛好是"+hobby;
}
//getter getXXX() XXX為屬性名稱
String getName(){
return name;
}
int getAge(){
return age;
}
String getSecret(){
return secret;
}
String getHobby(){
return hobby;
}
//setter setXXX() XXX為屬性名稱
void setAge(int age){
this.age=age;
}
void setHobby(String hobby){
this.hobby=hobby;
}
}
public class OOPTest{
public static void main(String [] args){
//物件1
//建立物件
//假設姓名不得修改,因此不提供setName()方法
OOP per1=new OOP("Tom");
// 對屬性賦值
per1.setAge(20);
per1.setHobby("跑步");
//OOP類的保護——封裝
//外部程式要訪問 封裝的屬性 通過提供的getter方法訪問
System.out.println(per1.getSecret());
System.out.println(per1.personInfo());
}
}