1.面向對象簡介
Java語言是一門面向對象的語言,Java語言最大的特點在於面向對象的編程設計,並且面向對象的編程設計也在由於Java自身的發展而不斷發展,同時最初不支持面向對象的編程也都開始轉向了面向對象。但是依然有許多的開發者認為面向過程編程會比較好。
最早並且一直到現在流行的編程語言C、C++、Java。其中C語言已經變成了面向過程開發的代表,C++、Java都是面向對象的變成語言。
所謂的面向過程指的是面對於一個問題的解決方案,更多的情況下不會做出重用的設計的思考,而面向對象主要的設計形式為模塊化設計,並且可以進行重用配置。在整個的面向對象的設計里面更多情況下考慮的是標准,在使用的時候根據標准進行拼裝,而對於面向對象設計有三個主要的特征:
-
-
- 封裝性:內部的操作對外而言不可見;當內部的操作都不可以直接使用的時候才是安全的;
- 繼承性:在已有結構的基礎上繼續進行功能的擴充;
- 多態性:是在繼承性的基礎上擴充而來的概念,指的是類型的轉換處理
-
在進行面向對象的開發中一般有三個步驟:
-
-
- OOA:面向對象分析
- OOD:面向對象設計
- OOP:面向對象編程
-
2.類與對象簡介
面向對象是一個非常龐大的話題,但是任何龐大的話題都有其核心的組成:類與對象
類是對某一類事物的共性的抽象概念,而對象描述的是一個具體的產物。
例如:現在我和某一位先生可以立刻區分出我還有別人。我和其他的人都一樣,都是一個個具體可以使用的個體產物,
但是這些個體都有一些共性的標志:人,中國人,美國人;
人和人是不同的:名字,膚色,性別,身高;
所謂的人和人之間的不同依靠的是我們各自的屬性,每一個屬性的集合就構成了一個對象,
但是所有的屬性都應該是群體的定 義,
而群體的定義就形成了一個類;
類是一個模板,而對象才是類可以使用的實例,先有類再有對象。
在類之中一般都會有兩個組成:
成員屬性(Field): 有些時候為了簡化稱其為屬性:
什么是屬性: 一個人的年齡、姓名都是不同的,所以這些對於整體來講就成為屬性
操作方法(Method): 定義對象具有處理行為;
什么是方法: 這個人可以唱歌、跳舞、游泳、運動;
3.類與對象的基本使用
在Java之中類是一個獨立的結構體,所以需要使用class來進行定義,而在類中主要由屬性和方法組成,
那么在類中的屬性就是一個個具體的變量,方法就是可以重復執行的代碼。
范例:定義一個類
public class Person{ //定義一個類 String name ; //人員的姓名 int age ; //人員的年齡
//定義一個方法 public void tell(){ System.out.println("姓名:" + this.name + "、年齡:" + age); } }
在這個類之中定義有兩個屬性(name、age)和一個方法(tell()) 於是說現在有了類之后
如果想使用類,必須通過對象來完成,而如果要產生對象,則必須使用以下語法格式來完成
聲明並實例化對象:類名稱 對象名稱 = new 類名稱();
分步驟完成:
聲明對象:類名稱 對象名稱 = null;
實例化對象:對象名稱 = new 類名稱();
當獲取了實例化對象之后,那么就需要通過對象對類中的屬性和方法調用
此時有兩種調用方式:
調用類中的屬性:實例化對象.成員屬性;
調用類中的方法:實例化對象.方法名稱();
當你不對屬性值進行設置的時候,則該屬性值為對應數據類型的默認值;
String 默認值為:null
int 默認值為:0
范例:使用對象操作類
public class JavaDemo{ public static void main(String args[]){ Person per = new Person(); //聲明並實例化對象 per.name = "張三"; //設置屬性姓名值 per.age = 18 ; //設置屬性年齡值 per.tel(); //進行方法的調用 } }
執行結果:
如果不設置屬性值執行結果:
4.對象內存分析
對象實例化操作初步分析
Java之中類屬於引用數據類型,引用數據類型最大的困難之處在於
要進行內存的管理,同時在進行操作的時候也會發生有內存關系的變化,
所以本次針對與之前的程序的內存關系進行一些簡單的分析。
范例:以下面的程序為主進行分析
public class JavaDemo{ public static void main(String args[]){ Person per = new Person(); //聲明並實例化對象 per.name = "張三"; //設置屬性姓名值 per.age = 18 ; //設置屬性年齡值 per.tel(); //進行方法的調用 } }
如果要進行內存分析,那么首先要給出兩塊最為常用的內存空間:
-
-
- 堆內存: 保存的是對象的具體信息。
- 棧內存: 保存的是一塊堆內存的地址,即:通過地址找到堆內存,而后找到對象內容,
-
但是為了分析簡化起見簡單的理解為對象的名稱保存在了棧內存之中
清楚了以前關系之后,那么下面針對之前的程序進行分析
將屬性的值設置后運行程序結果為:
在之前的內存分析操作中可以發現實例化對象有兩種方式:
1. 一種是之前使用的聲明並實例化對象
2 . 一種是分布完成實例化對象的操作;
下面對於分布的內存操作進行分析:
范例:定義程序代碼
public class JavaDemo{ public static void main(String args[]){ Person per = null; //聲明對象 per = new Person(); //實例化對象 per.name = "張三"; //設置屬性姓名值 per.age = 18 ; //設置屬性年齡值 per.tel(); //進行方法的調用 } }
結果還是一樣不變:
需要注意的是所有的對象必須在對象實例化完成之后才可以執行
范例:錯誤示范
public class JavaDemo{ public static void main(String args[]){ Person per = null; //聲明對象 //per = new Person();//將創建實例化的代碼注釋掉 //實例化對象 per.name = "張三"; //設置屬性姓名值 per.age = 18 ; //設置屬性年齡值 per.tel(); //進行方法的調用 } }
代碼中只聲明了對象而未實例化對象,所以此時無法調用它的屬性和方法。
程序報錯:
此時會報一個NullPointerException(空指向異常) ,就是 (實例化對象)沒有在堆內存開辟后時所產生的問題,
並且只有引用數據類型存在有此異常NullPointerException,基本數據類型不存在此異常,此異常將伴隨整個開發人生
5.對象引用分析
類本身屬於引用數據類型,那么就牽扯到內存的引用傳遞,
所謂的引用傳遞的本質:同一塊堆內存空間可以被不同的棧內存指向,也可以更換指向。
范例:定義一個引用傳遞的分析程序:
public class JavaDemo{ public static void main(String args[]){ Person per1 = new Person(); //聲明並實例化對象 per.name = "張三"; per.age = 18 ; Person per2 = per1 ; //引用傳遞 Person.age = 80 ; per.tell() ; //進行方法的調用 } }
運行結果:
6.引用傳遞與垃圾產生分析
范例:定義一個要分析的程序
public class JavaDemo{ public static void main(String args[]){ Person per1 = new Person(); //聲明並實例化對象 Person per2 = new Person(); //聲明並實例化對象 per1.name = "張三"; per1.age = 18 ; per2.name = "李四"; per2.age = 19 ; Person per2 = per1 ; //引用傳遞 Person.age = 80 ; per1.tell() ; //進行方法的調用 } }
此時已經明確的發生了引用傳遞,並且也成功的完成了引用傳遞的處理操作,
下面來觀察下內存分配與處理流程
所謂的垃圾空間指的就是沒有任何棧內存所指向的堆內存空間,所有的垃圾將被GC(Garbage Collector、垃圾收集器) 不定期進行回收,並且釋放無用內存空間,但是垃圾過多,一定將影響到GC的處理性能,從而降低整體的程序性能,那么在實際的開發之中,對於垃圾的產生應該越少越好。
一個棧內存只能夠保存有一個堆內存的地址數據,如果發生更改,則之前的地址數據將從此棧內存中徹底消失。
7.構造方法與匿名對象
現在的程序在使用類的時候一般都按照了如下的步驟進行:
- 聲明並實例化對象,這個時候實例化對象中的屬性並沒有任何的數據存在,都是其對應數據類型的默認值;
- 需要通過一系列的 setter 方法為類的屬性設置內容;
等於現在想要真正獲得一個可以正常使用的實例化對象,必須經過兩個步驟才可以調用
范例:傳統調用
public class JavaDemo{ public static void main(String args[]){ Person per = new Person(); //聲明並實例化對象 per.setName("張三");
per.setAge(18); per1.tell() ; //進行方法的調用 } }
通過以上案例可以發現,假設我們有8個屬性那么我們需要寫8個setter方法來進行設置值,這樣調用實在是太啰嗦了,
為了解決這個問題Java專門提供了構造方法。
既:可以通過構造方法實現實例化對象中的屬性初始化處理。
只有在關鍵字 new 的時候才會使用構造方法
在Java程序里面構造方法的定義要求如下:
- 構造方法名稱必須與類名稱保持一致;
- 構造方法不允許設置任何的返回值類型,即:沒有返回值定義;
- 構造方法是在使用關鍵字 new 實例化對象的時候自動調用的;
范例:定義構造方法
class Person{ //定義一個類 String name ; //人員的姓名 int age ; //人員的年齡
//方法名稱與類名稱相同,並且無返回值定義
public Person(String naem,int age){ //定義有參構造
this.name = name; //為類中的屬性賦值(初始化)
this.age = age ; //為類中的屬性賦值(初始化)
}
//定義一個方法 public void tell(){ System.out.println("姓名:" + this.name + "、年齡:" + age); }
}
public class JavaDemo{
public static void main(String args[]){
Person per = new Person("張三",18); //聲明並實例化對象
per1.tell() ; //進行方法的調用
} }
運行結果:
下面針對於當前的對象實例化格式與之前的對象實例化格式做一個比較:
- 之前的對象實例化格式:①Person ②per = ③new ④Person();
- 當前的對象實例化格式:①Person ②per = ③new ④Person("張三",18);
①Person :,類型決定了你可以調用的方法;
②per :實例化對象的名稱,所有的操作通過對象來進行訪問;
③new :開辟一塊新的堆內存空間;
④Person("張三",18) :調用有參構造、"④Person()"調用無參構造
在Java程序里面考慮到程序結構的完整性,所有的類都會提供有構造方法,也就是說如果現在你的類中沒有定義任何的構造方法,
那么Java一定會默認提供一個無參的,什么都不做的構造方法,這個構造方法是在程序編譯的時候自動創建的。
如果你現在已經在類中明確的定義有一個構造方法的時候,
那么這個默認的構造方法將不會被自動創建。
結論:一個類至少存在一個構造方法,永恆存在。
疑問:為什么構造方法上不允許設置返回值類型?
既然構造方法是一個方法,那么為什么不讓它定義返回值類型呢?
既然構造方法不會返回數據,為什么不使用 void 來定義呢?
分析:程序編譯器是根據代碼結構來進行編譯處理的,執行的時候也是根據代碼結構來處理的。
如果在構造方法上使用了void ,那么次結構就與普通方法的結構完全相同的了,這樣編譯器就會識別成普通方法、
普通方法和構造方法最大的區別:構造方法是在類對象實例化的時候調用的,而普通方法是在類對象實例化產生之后調用的。
既然構造方法本身是一個方法,那么方法就具有重載的特點,而構造方法重載的時候只需要考慮參數的類型及個數即可
public class Person{ private String name; private int age ; public Person(){}//無參構造 public Person(String name){//帶一個參數有參構造 this.name = name; } public Person(String name,int age){//帶兩個參數有參構造 this.name = name; this.age = age; } }