文章目錄
- 面向物件編程(OOP)
- 介紹
- 什么是類
- 屬性和行為
- 方法
- 什么是方法?
- 定義方法的格式詳解
- Java中方法的分類
- 構造方法
- 靜態方法
- 實體/默認方法
- 抽象方法
- 私有方法
- 陣列作為方法引數和回傳值
- ## 陣列作為方法引數
- 物件的創建及使用
- 方法的多載和方法的重寫
- 多載(Overload)
- 重寫(Override)
- 三大基本特征
- 繼承 封裝 多型
- 繼承
- 封裝
- 多型(polymorphic)
- 多型的三種表現形式
- 多型的前提
- 多型有什么好處?
- 多型的弊端:
- 怎么才能使用子類特有的功能?
面向物件編程(OOP)
Object Oriented Programming
物件 : Object
C 面向程序
C++ 半面向程序半面向物件
Java 面向物件: 把大象裝進冰箱.
介紹
什么是類
具有相同特點(屬性)和行為(動作)的集合的總稱.
人類
植物類
屬性和行為
什么是物件
是某一類的具體體現 實體
將類的抽象概念具體化.
人類的物件: 張三,特朗普,…
植物類的物件 : 路邊的梧桐,楊樹
手機類的物件 : 正在使用的手機
什么是屬性
是一類事物的特點/特征.
人類的屬性/特征 : 膚色,年齡,身高,體重…
植物類的屬性 : 樹干,樹葉,樹根,花,果實
手機的屬性 : 價格,重量,顏色,形狀
什么是方法
一類事物都可以進行的動作/行為.
人類的動作 : 吃飯睡覺打豆豆
植物的動作 : 開花,結果,光合作用
手機的動作 : 打電話,發短信
方法
什么是方法?
方法:在程式中要去實作的某一個功能,需要包含多條陳述句,這些陳述句包含回圈陳述句結構,選擇陳述句結構等共同來處理一件事情.
定義方法的格式詳解
public static void main(String[] args){
//執行陳述句
System.out.println();
}
* [訪問修飾符] 回傳值型別 方法名([引數1],[引數2],...){
* 方法內的執行陳述句;
* ...
* }
* 訪問修飾符 : 控制訪問權限
* 回傳值型別 : 該方法執行后回傳的結果的資料型別
* 基本資料型別/參考資料型別
* void : 空,方法執行后不回傳任何資料
* ---
* 如果方法需要回傳資料,
* 1) 那就需要在回傳值型別處寫上回傳資料的資料型別
* 2) 在方法體的最后使用 return 值;的格式將值明確顯示回傳.
* 3)只要不是void,必須在方法后加: return 值;
* 4)return 后只能有一值;
* 5)如果需要回傳多個值需要將多個值放進陣列或方法,將陣列或方法回傳
* eg.public static void main(String[] args){
* int[] arr = returnMoreValue(1,2);
* System.out.println(arr[0]);
* System.out.println(arr[1]);
* }
* //方法執行回傳多個值:2個值為例
* //需要將多個值放入陣列,將陣列回傳
* public static int[] returnMoreValue(int a,int b){
* int[] arr = new int[2];
* arr[0] = a;
* arr[1] = b;
* return arr;
* }
* 方法名 : 見名知意,駝峰原則
* () 引數串列 :
* 1 形式引數 : 該方法執行可能用到的資料
* 2 形式引數的寫法: 資料型別 變數名;
* 3 串列內可以寫多個引數,多個引數之間用逗號隔開,或者可以不寫
* 4 當方法引數串列有引數時,在呼叫時(讓方法執行時)
* 就必須給方法的引數賦值
* 引數型別:進入方法當中的資料是一個什么樣的型別
* 引數名稱:進入方法當中的資料對應的變數名稱
* {} 方法體
* 備注:方法不允許嵌套
* 執行陳述句 : 該方法真正的功能體現
Java中方法的分類
JAVA中方法的分類
構造方法
- 構造方法:類或者抽象類中(介面沒有),與類名同名,無回傳值,不能用static修飾,
- 格式:權限修飾符 類名(引數){方法體}
- 作用:初始化實體物件,
- 呼叫:創建類的實體物件時,自動呼叫,
- 繼承性:無參構造其子類會自動呼叫父類的無斜體樣式參構造supper(),含參構造不會被繼承,
//顧客類的有參構造方法
public Customer(String name, String idCard, String tel, String address) {
this.name = name;
IdCard = idCard;
this.tel = tel;
this.address = address;
}
注意:構造方法分為含參構造和無參構造,JAVA會在編譯時自動生成無參構造,但若書寫了含參構造,則必須自己寫無參構造,否則只能呼叫含參構造,
靜態方法
- 定義:類/介面中,用static修飾的方法,
- 格式: 權限修飾符 static 回傳值型別 方法名(引數){} (static可與final,private共存)
- 特點:
- 靜態方法屬于整個類,不單獨屬于類的某一個物件,
- 靜態方法類加載便存在,比物件先存在,隨類而消亡,
- 呼叫:
- *類名/介面名.靜態方法或者 實體物件.靜態方法名 兩種方式呼叫,建議使用第一種,
- 靜態方法可以呼叫靜態成員,不能呼叫非靜態成員,(其先于非靜態成員產生),
- 繼承性:
- 類(包括抽象類)其靜態方法是可以被繼承的,即可以通過:子類名/子類物件.靜態方法的方式進行呼叫,
- 介面的靜態方法不能被其實作類或者子介面繼承,即不能采用:實作類名/實作類物件名/子介面名.靜態方法名的方式進行呼叫,
// 介面1
public interface MyInter1 {
public static void fly(){}
}
// 介面2 繼承于介面1
public interface MyInter2 extends MyInter1{
}
// 實作類實作介面1
public class Myclass implements MyInter1{
}
// 測驗類
public class Test02 {
public static void main(String[] args) {
Myclass myclass = new Myclass();
MyInter1.fly();
// Myclass.fly(); 錯誤,介面中的靜態方法不能被其實作類繼承
// myclass.fly(); 錯誤,介面中的靜態方法不能被其實作類繼承
// MyInter2.fly(); 錯誤,介面中的靜態方法不能被子介面繼承
}
}
實體/默認方法
- 定義:類中/介面中無static修飾的方法,類中無特殊修飾符,介面中用default修飾
- 格式:
類或者抽象類中:權限修飾符 回傳值型別 方法名(引數) {方法體}
介面中:權限修飾符default 回傳值 方法名 (引數) {方法體} - 特點:實體/默認方法屬于類的實體物件.隨時物件創建而加載,物件消失而消亡.
- 呼叫:只能通過:實體物件/介面的實作類物件.方法名進行呼叫
- 繼承性:可以被子類繼承(介面亦然)
// 介面
public interface MyInter3 {
public default void eat(){
System.out.println("走起,咱今天吃火鍋去!");
}
}
// 類
public class Myclass3 {
public void eat(){
System.out.println("走起,咱今天吃海鮮去!");
}
}
// 測驗類
public class Test03 {
public static void main(String[] args) {
// Myclass3.eat(); // 錯誤,不能使用類名呼叫,
new Myclass3().eat(); // 可以通過實體物件呼叫
// MyInter3.eat(); // 錯誤,不能使用介面名呼叫
new MyInter3(){}.eat(); // 可以通過介面的實作類物件呼叫,這里匿名內部類實際上是介面的實作類物件,
}
}
抽象方法
-
定義:抽象類或者介面中,用abstract修飾的方法
-
格式:權限修飾符 abstract 回傳值型別 方法名(引數);(abstract 不能與static 和final修飾符共存)
-
特點:必須被子類重寫,無方法體
-
呼叫:子類重寫后,按照實體方式的呼叫方式進行呼叫,
-
繼承性:必須重寫,談不上繼承不繼承,
// 抽象類
public abstract class AbstractClass01 {
// 抽象方法
public abstract void fun();
}
// 子類繼承于抽象類
public class Myclass4 extends AbstractClass01{
// 重寫抽象方法
@Override
public void fun() {
System.out.println("玩得真開心");
}
}
// 測驗類
public class Test04 {
public static void main(String[] args) {
// 創建物件使用重寫后的抽象方法
new Myclass4().fun();
}
}
// 運行結果
玩得真開心
私有方法
- 定義:使用private權限修飾符修飾的方法
- 格式:private 回傳值型別 方法名(引數){方法體} (private 可以與static,final,abstract共存)
- 特點:private只屬于本類,不屬于其子類物件,
- 呼叫:本類可直接呼叫,其他類或者子類或者該類物件,只能通過類中其他方法進行間接呼叫,
- 繼承性:可以被子類繼承(介面亦然),當也只能通過類中其他方法進行間接呼叫,
// 父類包含私有方法
public class Myclass5 {
// 私有方法
private void eat() {
System.out.print("吃 ");
}
// 公有實體方法
public void fun(){
eat();
System.out.println("玩");
}
}
// 子類
public class Myclass6 extends Myclass5{
}
// 測驗類
public class Test05 {
public static void main(String[] args) {
// 創建物件
Myclass5 my = new Myclass5();
// my.eat; // 報錯,不能直接呼叫私有方法,
my.fun(); // 可以間接呼叫私有方法
// 子類物件間接呼叫
System.out.println("分割線===========");
new Myclass6().fun();
}
}
陣列作為方法引數和回傳值
## 陣列作為方法引數
??陣列作為應用型別能夠當成方法的引數進行傳遞呢?當然可以
- 陣列作為方法引數傳遞,傳遞的引數是陣列記憶體的地址
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
//呼叫方法,傳遞陣列
println(arr);
}
public static void println(int[] arr){
for (int i = 0; i < arr.length - 1; i++) {
System.out.println(arr[i]);
}
}
物件的創建及使用
* 通過類 創建物件 <==> 實體化
* 類名 物件名 = new 類名();
* -----------------------
* 資料型別 變數名 = 值;
* -----------------------
* 物件屬性取值:
* 資料型別 變數名 = 物件名.屬性名;
*
* 物件屬性賦值:
* 物件名.屬性名 = 值;
*
* 呼叫物件的方法[重點]
* 三種呼叫格式:
* 1.單獨呼叫:物件名.方法名(引數具體值);
* 2.列印呼叫:System.out.println(物件名.方法名(引數具體值));
* 3.賦值呼叫:資料型別 變數名 = 物件名.方法名(引數具體值);
* 備注:當回傳值型別為void的時候,這種方法只能單獨呼叫,不能進行列印呼叫或者賦值呼叫
* 回傳值型別一般可以理解為資料型別(基本資料型別和參考資料型別),此外還包含一種型別void型別,當方法執行完畢不需要給程式呼叫者回傳人和的資料結果時,可以指定該方法的回傳值型別為void,此時只能[單獨呼叫]
* 1) 方法有引數,呼叫時必須傳入實參
* 實參與形參的個數,順序,資料型別要保持
* 2) 方法沒有引數,不能給引數
* 3) 方法無回傳值,一定不能接識訓傳值
* 4) 方法有回傳值,可以接收,也可以不接收
* A : 無回傳值
* A1 無回傳值無參
* 物件名.方法名();
* A2 無回傳值有引數
* 物件名.方法名(值1,值2,..);
* B : 有回傳值
* B1 有回傳值無參
* [資料型別 變數名 = ]物件名.方法名();
* B2 有回傳值有引數
* [資料型別 變數名 = ]物件名.方法名(值1,值2,..);
public static void main(String[] args){
// 創建物件
Student stu1 = new Student();
System.out.println(stu1);
// 獲得屬性值
String name = stu1.name;
int age = stu1.age;
String stuNo = stu1.stuNo;
String schoolName = stu1.schoolName;
System.out.println("name = "+name);
System.out.println("age = "+age);
System.out.println("stuNo = "+stuNo);
System.out.println("schoolName = "+schoolName);
// 屬性賦值
stu1.name = "張三";
stu1.age = 18;
stu1.schoolName = "北京大學";
stu1.stuNo = "100001";
System.out.println("name = "+stu1.name);
System.out.println("age = "+stu1.age);
System.out.println("stuNo = "+stu1.stuNo);
System.out.println("schoolName = "+stu1.schoolName);
System.out.println("----------分割線---------");
// A1 無回傳值無參
stu1.eat();
// A2 無回傳值有引數
stu1.sleep("地");
// B1 有回傳值無參
String result1 = stu1.playGame();
System.out.println("結果 : "+result1);
// B2 有回傳值有引數
String result2 = stu1.study("<java從入門到精通>", "黑筆");
System.out.println("誰在學習 ? : " + result2);
}
public class Student{
/*
* 屬性的寫法:
* [訪問修飾符] 資料型別 變數名;
* []內的代碼,可寫可不寫
*/
public String name;
public int age;
public String stuNo;
String schoolName;
public String study(String book,String pen) {
System.out.println("在學習"+book);
String name = "張三";
// return "李四";
return name;
}
void eat() {
System.out.println("吃");
}
void sleep () {
System.out.println("睡覺");
}
}
方法的多載和方法的重寫
多載(Overload)
1.在同類中,方法名一樣,引數串列不一樣的方法之間叫做多載.
2.方法多載與那些因素有關:
- 引數的個數不同
- 引數的型別不同
- 引數的多型別順序不同
3.方法多載與那些因素無關:
- 與引數的名稱無關
- 與方法的回傳值型別無關
- 與方法的修飾符無關
好處:只需要記住唯一一個方法名稱即可,就可以實作類似的多個功能.
重寫(Override)
定義:重寫是子類對父類的允許訪問的方法的實作程序進行重新撰寫,回傳值和形參都不能改變.
重寫的規則:
- 引數串列必須完全與被重寫方法相同
- 回傳值必須完全相同
- 訪問權限不能比父類中被重寫的方法的訪問權限更低
- 父類私有(private)方法不能被重寫
- 宣告為final的方法不能被重寫
- 宣告為static的方法不能被重寫,但能被再次宣告
- 如果子類不是抽象類,子類必須重寫父類中的abstract的方法
- 如果子類和父類在同一個包下,子類可以被重寫除private和final之外的所有方法
- 如果子類和父類不在同一個包下,子類能重寫父類中被public修飾和protected修飾的方法
- 重寫方法能夠拋出任何非強制例外,無論被重寫的方法是否拋出例外.但是,重寫的方法不能拋出新的強制性例外
注:所謂強制性例外,就是在撰寫程式的程序中,必須在拋出例外的部分try-catch或者向上throw例外
三大基本特征
繼承 封裝 多型
繼承
1.場景:
??如果多個類存在相同的屬性和行為時,將這些內容抽取到單獨一個類中,
那么多個類無需再定義這些屬性和行為,只要繼承那一個類即可,
其中,多個類可以稱為子類,單獨的那個類稱為父類、超類、基類
繼承描述的是事物之間的所屬關系,這種關系是:is-a的關系,
父類更通用,子類更具體,我們主要是通過繼承,可以使事物之間形成一種關系體系,
2.定義:
??就是子類繼承父類的屬性和行為,使得子類物件具有與父類相同的屬性、相同的行為,
??子類可以直接訪問父類中的非私有的屬性和行為,
3.好處:
1)提高代碼的復用性
2)使得類與類之間產生了關系,是多型的前提,
4.繼承格式:
??通過關鍵字extends,可以宣告一個子類繼承另一個父類
class SuperClass{
…
}
class Subclass extends SuperClass{
…
}
-
繼承后的特點—成員變數
1.成員變數不重名
如果子類父類中出現不重名的成員變數,這時訪問時沒有影響的,
如果重名,這時訪問是受影響的,
子父類中出現了同名的成員變數時,在子類中需要訪問父類中非私有成員變數,就需要使用super關鍵字,
修飾父類成員變數,類似于關鍵字this
2.使用格式:
super.父類成員變數名;
備注:父類中的成員變數是非私有的,子類才可以直接訪問,若父類中的成員變數私有了,子類不能直接訪問的,
通常編碼時,我們一般遵循封裝的原則,可以在父類中提供公共的setXxx()和getXxx()方法, -
繼承后的特點—成員方法
1.成員方法不重名
如果子類父類中出現不重名的成員方法時,這時的呼叫沒有任何的影響,
物件呼叫方法時,會先在子類中查找有沒有對應的方法,若子類存在就會執行子類中的成員方法,
若不存在就會執行父類中相應的方法,
2.成員方法重名—重寫(Override)
方法重寫:子類出現于父類一模一樣的方法時(回傳值型別,方法名和引數串列都相同),會出現覆寫效應
也稱為重寫或者復寫,宣告不變,重新實作,
3.重寫的應用
子類可以根據需要,定義特定于自己的行為,即沿襲了父類的功能名稱,又能根據子類的需要重新實作父類
的方法,從而進行擴展增強,比如:新的手機來電顯示功能,
備注:
1.子類方法重寫覆寫父類方法時,必須保證權限大于等于父類的權限,
2.子類方法重寫父類方法時,回傳值型別,方法名和引數串列必須一模一樣,
在沒有使用@Override時,子類定義父類方法時,方法名和引數串列可變,回傳值型別不可變,- 繼承的特點:
1.java只支持單繼承,不支持多繼承,
2.java支持多層繼承(繼承體系)
3.子類和父類是一種相對概念,
備注:頂層父類是Object類,所有的類默認都繼承Object類,
- 繼承的特點:
封裝
1.封裝:就是隱藏物件的屬性和實作細節,僅對外提供公共訪問方式,封裝使用get,set方法,
2.封裝的好處:
1、良好的封裝能夠減少耦合,
2、類內部的結構可以自由修改,
3、可以對成員進行更精確的控制,
4、隱藏資訊,實作細節,
3.封裝時的權限控制符區別如下:

假如:有一個學生類Student
public class Student{
public int age;
public string name;
public Date date;
}
外部使用Student時,
public static void main(String[] args){
Student stu = new Student();
stu.age=16;
stu.name="john";
stu.date=2017;
}
但是,現實中如果很多外部代碼都使用了Student這個類;某一天,如果這個類的age需要換成String型別,那么,外部使用它的任何地方都需要需改xxx.age=“xxx”,這將是非常繁瑣的一個程序,
但是如果使用封裝屬性,開放訪問介面的方法:
public class Student{
private String age; //修改int to String
private string name;
public void setAge(String age){
this.age = String.valueOf(age); //修改
}
public String getAge(){
return this.age;
}
}
這樣外部使用它的地方都不用修改,只用修改物件內部就可以了,更加方便快捷,到了這里我們確實可以看出,封裝確實可以使我們容易地修改類的內部實作,而無需修改使用了該類的客戶代碼,
多型(polymorphic)
Java中:同一個方法,傳入相同型別的引數,但是運行結果不一樣.
Java多型:讓程式在運行時自行決定執行哪些方法
多型的三種表現形式
1.普通類多型定義的格式
父類 變數名 = new 子類();
2.抽象類多型定義格式
3.介面多型定義格式
多型的前提
1.子父類關系
2.子類必須重寫父類方法
3.父類參考指向子類物件
??父型別 變數 = 子類物件;==>向上轉型
屬性沒有多型性,方法有多型性
編譯看父類,運行看子類
多型有什么好處?
有兩個好處:
A:提高了代碼的維護性(繼承保證)
B:提高了代碼的擴展性(由多型保證)
貓狗案例代碼
class Animal {
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("sleep");
}
}
class Dog extends Animal {
public void eat(){
System.out.println("狗吃肉");
}
public void sleep(){
System.out.println("狗站著睡覺");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("貓吃魚");
}
public void sleep() {
System.out.println("貓趴著睡覺");
}
}
class Pig extends Animal {
public void eat() {
System.out.println("豬吃白菜");
}
public void sleep() {
System.out.println("豬側著睡");
}
}
//針對動物操作的工具類
class AnimalTool {
private AnimalTool(){}
/*
//呼叫貓的功能
public static void useCat(Cat c) {
c.eat();
c.sleep();
}
//呼叫狗的功能
public static void useDog(Dog d) {
d.eat();
d.sleep();
}
//呼叫豬的功能
public static void usePig(Pig p) {
p.eat();
p.sleep();
}
*/
public static void useAnimal(Animal a) {
a.eat();
a.sleep();
}
//把所有的可能都歸為動物類
}
class DuoTaiDemo2 {
public static void main(String[] args) {
//我喜歡貓,就養了一只
Cat c = new Cat();
c.eat();
c.sleep();
//我很喜歡貓,所以,又養了一只
Cat c2 = new Cat();
c2.eat();
c2.sleep();
//我特別喜歡貓,又養了一只
Cat c3 = new Cat();
c3.eat();
c3.sleep();
//...
System.out.println("--------------");
//問題來了,我養了很多只貓,每次創建物件是可以接受的
//但是呢?呼叫方法,你不覺得很相似嗎?僅僅是物件名不一樣,
//我們準備用方法改進
//呼叫方式改進版本
//useCat(c);
//useCat(c2);
//useCat(c3);
//AnimalTool.useCat(c);
//AnimalTool.useCat(c2);
//AnimalTool.useCat(c3);
AnimalTool.useAnimal(c);
AnimalTool.useAnimal(c2);
AnimalTool.useAnimal(c3);
System.out.println("--------------");
//我喜歡狗
Dog d = new Dog();
Dog d2 = new Dog();
Dog d3 = new Dog();
//AnimalTool.useDog(d);
//AnimalTool.useDog(d2);
//AnimalTool.useDog(d3);
AnimalTool.useAnimal(d);
AnimalTool.useAnimal(d2);
AnimalTool.useAnimal(d3);
System.out.println("--------------");
//我喜歡寵物豬
//定義一個豬類,它要繼承自動物,提供兩個方法,并且還得在工具類中添加該類方法呼叫
Pig p = new Pig();
Pig p2 = new Pig();
Pig p3 = new Pig();
//AnimalTool.usePig(p);
//AnimalTool.usePig(p2);
//AnimalTool.usePig(p3);
AnimalTool.useAnimal(p);
AnimalTool.useAnimal(p2);
AnimalTool.useAnimal(p3);
System.out.println("--------------");
//我喜歡寵物狼,老虎,豹子...
//定義對應的類,繼承自動物,提供對應的方法重寫,并在工具類添加方法呼叫
//前面幾個必須寫,我是沒有意見的
//但是,工具類每次都改,麻煩不
//我就想,你能不能不改了
//太簡單:把所有的動物都寫上,問題是名字是什么呢?到底哪些需要被加入呢?
//改用另一種解決方案,
}
/*
//呼叫貓的功能
public static void useCat(Cat c) {
c.eat();
c.sleep();
}
//呼叫狗的功能
public static void useDog(Dog d) {
d.eat();
d.sleep();
}
*/
}
多型的弊端:
不能使用子類的特有功能,
怎么才能使用子類特有的功能?
A:創建子類物件呼叫方法即可,(可以,但是很多時候不合理,而且,太占記憶體了)
B:把父類的參考強制轉換為子類的參考,(向下轉型)
注:向下轉型中有可能的例外:
ClassCastException:型別轉換例外一般在多型的向下轉型中容易出現
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/223349.html
標籤:其他
