1. 基礎篇語法篇:一.基礎篇:基礎語法-CSDN博客
面向對象進階
本章主要學習內容:
- static
- 繼承
- 包,final,權限修飾符,代碼塊
- 抽象類
- 接口
- 多態
- 內部類
1. static
- static翻譯過來就是靜態的意思
- static表示靜態,是java中的一個修飾符,可以修飾成員方法,成員變量
- 被static修飾的成員變量,叫做靜態變量
- 特點:
- 被該類所有對象共享
- 不屬于對象,屬于類
- 隨著類的加載而加載,優先于對象存在
- 特點:
- 被static修飾的成員方法,叫做靜態方法
- 特點:
- 多在測試類和工具類中
- javabean類中很少會用
- 特點:
- 調用方式:
- 類名調用(推薦)
- 對象名調用
需求:寫一個javaBean類來描述班級的學生
- 屬性:姓名,年齡,性別
- 行為:學習逆向
public class Test {public static void main(String[] args) {// 創建兩個學生對象Student.teacherName = "劉老師";Student s1 = new Student();s1.setName("小明");s1.setAge(10);s1.setGender("男");s1.show();s1.study();System.out.println("==========================");Student s2 = new Student();s2.setGender("女");s2.setAge(12);s2.setName("小紅");s2.show();s2.study();}
}// 學生類
class Student{// 屬性: 姓名,年齡,性別// 新增屬性: 老師的姓名private String name;private int age;private String gender;// 使用static修飾后,Student類中所有對象都共享teacherNamepublic static String teacherName;public Student() {}public Student(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}/*** 獲取* @return gender*/public String getGender() {return gender;}/*** 設置* @param gender*/public void setGender(String gender) {this.gender = gender;}// 重寫toString方法public String toString() {return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";}// 行為: 學習方法public void study(){System.out.println(name + "正在學習");}// 輸出學生信息public void show(){System.out.println(name + ", " + age + ", " + gender + ", " + teacherName);}
}
工具類
類的分類
工具類的定義規范:
- 類名見名知意
- 私有化構造方法
- 方法都定義為靜態的,方便調用
示例代碼:
需求:在時機開發中,經常會遇到一些數組使用的工具類,按照以下要求編寫一個數組的工具類: ArrayUtil
- 提供一個工具類方法printArr,用于返回整數數組的內容
- 返回的字符串格式如:[10,20,30,40]?
- 提供一個工具方法 getAerage,用于返回平均分
- 定義一個測試類TestDemo,調用工具類的工具方法
public class Test {public static void main(String[] args) {int[] arr1 = {1,2,3,4,5,6};String s = ArrayUtil.printArr(arr1);System.out.println(s); // [1, 2, 3, 4, 5, 6]System.out.println("========================");double[] arr2 = {1.1,22.2,33.3,44.4};double average = ArrayUtil.getAverage(arr2);System.out.println(average);}
}// ArrayUtil工具類
class ArrayUtil{// 私有化構造方法// 目的: 為了不讓外界創建他的對象private ArrayUtil(){}// 定義靜態方法,方便使用public static String printArr(int[] arr){StringBuilder sb = new StringBuilder();sb.append("[");for (int i = 0; i < arr.length; i++) {// i 索引 arr[i] 元素if(i == arr.length - 1){sb.append(arr[i]);}else{sb.append(arr[i]).append(", ");}}sb.append("]");return sb.toString();}public static double getAverage(double[] arr){double sum = 0;for (int i = 0; i < arr.length; i++) {sum = sum + arr[i];}return sum / arr.length;}
}
示例代碼:
需求:定義一個集合,用于存儲3個學生對象
- 學生類的屬性為:name,age,gender
- 定義一個工具類,用于獲取集合中最大學生的年齡
import java.util.ArrayList;public class Test {public static void main(String[] args) {// 1. 創建一個集合,用來存儲學生對象StudentArrayList<Student > list = new ArrayList<>();// 2.創建3個學生對象Student stu1 = new Student("小明",1,"男");Student stu2 = new Student("小紅",12,"女");Student stu3 = new Student("小芳",16,"女");// 3.把學生對象,添加到集合中list.add(stu1);list.add(stu2);list.add(stu3);// 計算集合中年齡最大的學生int studentAgeMax = StudentUtil.getStudentAgeMax(list);System.out.println("最大學生的年齡: " + studentAgeMax);}
}// 學生類(標準的javaBean類)
class Student{private String name;private int age;private String gender;public Student() {}public Student(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}/*** 獲取* @return gender*/public String getGender() {return gender;}/*** 設置* @param gender*/public void setGender(String gender) {this.gender = gender;}public String toString() {return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";}
}// 定義一個工具類,用于獲取最大學生的年齡
class StudentUtil{private StudentUtil(){}// 靜態方法public static int getStudentAgeMax(ArrayList<Student> list){//1.定義一個參照物int max = list.get(0).getAge();for (Student student : list) {int age = student.getAge();if (age > max){max = age;}}return max;}
}
static注意事項
- 靜態方法中,只能訪問靜態
- 非靜態方法,可以訪問所有
- 靜態方法中沒有this關鍵字
2. 繼承
- 繼承是面向對象三大特征之一
- java中提供了一個關鍵字 extends,用這個關鍵字,可以讓一個類和另一個類建立起繼承關系
- public class Student extends Person{}
- Student稱為子類(派生類), Person稱為父類(基類或超類)
- 使用繼承的好處:
- 可以把多個子類重復的代碼抽取到父類中,提高代碼的復用性
- 子類可以在父類的基礎上,增加其他的功能,使子類更強大
- 什么時候使用到繼承?
- 當類與類之間,存在相同(共性)的內容,并滿足子類是父類中的哪一種,就可以考慮使用繼承,來優化代碼
- 繼承需要學習的點:
- 編寫自己的父類,使用子類繼承
- 繼承已經寫好的父類
- 繼承的特點:
- java只支持單繼承,不支持多繼承,但支持多層繼承
示例代碼:
public class Test {public static void main(String[] args) {// 創建對象并調用方法Ragdoll ragdoll = new Ragdoll();ragdoll.eat();ragdoll.drink();ragdoll.catchMouse();}
}// 動物類(父類)
class Animal{public void eat(){System.out.println("吃飯");}public void drink(){System.out.println("喝水");}}// 貓類
class Cat extends Animal{public void catchMouse(){System.out.println("貓在抓老鼠");}
}// 狗類
class Dog extends Animal{public void lookHome(){System.out.println("狗看家");}
}// 布偶貓
class Ragdoll extends Cat{}// 貍花貓
class LiHuaMao extends Cat{}// 哈士奇
class Husky extends Dog{public void breakHome(){System.out.println("哈士奇在拆家");}
}// 泰迪
class Teddy extends Dog{public void touch(){System.out.println("泰迪又在蹭腿");}
}
繼承中的成員變量和成員方法訪問特點
繼承中成員變量的訪問特點
- 通過this關鍵字,訪問自身類上的屬性
- 通過super關鍵字,訪問父類上的屬性
小結:
- 繼承中成員變量的訪問特點:就近原則
- 先在局部位置找,本類成員位置找,父類成員位置找,逐級往上
- 如果出現重名的成員變量怎么辦?
繼承中成員方法的訪問特點,和成員變量訪問特點一樣
方法的重寫
- 當父類的方法不能滿足子類現在的需求時,需要進行方法重寫
- 方法重寫格式:
- 在繼承體系中,子類出現了和父類一模一樣的方法聲明,就稱子類這個方法是重寫的方法
- @Override重寫注解:@Override是放在重寫后的方法上,校驗子類重寫時語法是否正確
示例代碼:
public class Test {public static void main(String[] args) {XM xm = new XM();xm.jn();}
}class Person{public void jn(){System.out.println("java");}
}class XM extends Person{// 重寫父類的jn方法// 注意: 子類重寫父類的方法需要在方法上加上 @Override@Overridepublic void jn(){System.out.println("逆向");}
}
方法重寫注意事項和要求:
繼承中的構造方法
構造方法的訪問特點:
小結:
3. 多態
基本使用
示例代碼:
public class Test {public static void main(String[] args) {Student student = new Student();student.setName("小明");student.setAge(10);Teacher teacher = new Teacher();teacher.setName("王老師");teacher.setAge(32);Administrator administrator = new Administrator();administrator.setAge(53);administrator.setName("管理員");register(student);register(teacher);register(administrator);}// 注冊// 這個方法即能接收老師,又能接收學生,又能接收管理員public static void register(Person p){p.show();}
}// 父類
class Person{private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Person{name = " + name + ", age = " + age + "}";}public void show(){System.out.println(name + ", " + age);}
}// 學生類(子類) 基礎 父類
class Student extends Person{// 重寫父類方法@Overridepublic void show(){System.out.println("學生的信息為: " + getName() + ", " + getAge());}
}// 老師類(子類) 基礎 父類
class Teacher extends Person{// 重寫父類方法@Overridepublic void show(){System.out.println("老師的信息為: " + getName() + ", " + getAge());}
}// 管理員類(子類) 基礎 父類
class Administrator extends Person{// 重寫父類方法@Overridepublic void show(){System.out.println("管理員的信息為: " + getName() + ", " + getAge());}
}
小結:
多態調用成員的特點
- 變量調用:編譯看左邊,運行也看左邊
- 方法調用:編譯看左邊,運行看右邊
示例代碼:
public class Test {public static void main(String[] args) {// 創建對象(多態的方式創建)Animal cat = new Cat();// 多態中調用成員變量: 編譯看左邊,運行也看左邊// 編譯看左邊: javac編譯代碼的時候,會看左邊的父類中有沒有這個變量,如果有,編譯成功,如果沒有就編譯失敗// 運行也看左邊: java運行代碼的時候,實際獲取的是左邊父類中成員變量的值System.out.println(cat.name); // 調用的是父類的name// 多態中調用成員方法: 編譯看左邊,運行看右邊// 編譯看左邊: javac編譯代碼的時候,會看左邊的父類中有沒有這個方法,如果有,編譯成功,如果沒有就編譯失敗// 運行看右邊: java運行代碼的時候,實際上是運行子類中的方法cat.show(); // Cat-show方法}
}class Animal{String name = "動物";public void show(){System.out.println("Animal-show方法");}
}class Cat extends Animal{String name = "貓";@Overridepublic void show(){System.out.println("Cat-show方法");}
}class Dog extends Animal{String name = "狗";@Overridepublic void show(){System.out.println("Dog-show方法");}
}
多態的優勢和弊端
多態的練習
需求:
代碼:
public class Test {public static void main(String[] args) {// 創建對象并調用方法Person p1 = new Person("老王",30);Dog dog = new Dog(2,"黑");p1.keepPet(dog,"骨頭");System.out.println("========================");Cat cat = new Cat(10,"白");p1.keepPet(cat,"魚");}
}// 動物的父類(將貓和狗的共性包裝到父類中)
class Animal{// 屬性private int age;private String color;public Animal() {}public Animal(int age, String color) {this.age = age;this.color = color;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}/*** 獲取* @return color*/public String getColor() {return color;}/*** 設置* @param color*/public void setColor(String color) {this.color = color;}public String toString() {return "Animal{age = " + age + ", color = " + color + "}";}/*** 吃東西的方法* @param something*/public void eat(String something){System.out.println("動物再吃" + something);}
}// 狗類
class Dog extends Animal{// 空參構造public Dog() {}// 帶父類全部參數的構造public Dog(int age,String color) {super(age,color);}// 重寫父類的eat方法@Overridepublic void eat(String something) {System.out.println(getAge() + "歲 " + getColor() +"顏色的狗在吃" + something );}// 狗特有的方法public void lookHome(){System.out.println("狗看家");}
}// 貓類
class Cat extends Animal{// 空參構造public Cat() {}// 帶父類全部參數的構造public Cat(int age,String color) {super(age,color);}@Overridepublic void eat(String something) {System.out.println(getAge() + "歲 " + getColor() +"顏色的貓在吃" + something );}// 貓特有的方法public void catchMouse(){System.out.println("貓抓老鼠");}
}// 飼養員
class Person{private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Person{name = " + name + ", age = " + age + "}";}public void keepPet(Animal a,String something){if(a instanceof Dog d) {System.out.println("年齡為" + age + "歲的" + name + "養了一只" + a.getColor() + "顏色的" + a.getAge() + "歲的" + "狗");a.eat(something);} else if (a instanceof Cat d) {System.out.println("年齡為" + age + "歲的" + name + "養了一只" + a.getColor() + "顏色的" + a.getAge() + "歲的" + "貓");a.eat(something);}else{System.out.println("沒有這種動物");}}
}
4.? 包
什么是包?
- 包就是文件夾。用來管理各種不同功能的java類,方便后期維護
- 包名的規則:域名反寫+包的作用,需要全部英文小寫,見名知意。
- 例如:
- 域名為:spider.github.com
- 包那么就命名為:com.github.spider
- 例如:
使用規則:
- 在com.spider.github 軟件包下軟件一個名為Student的類
- 在Test類中通過import關鍵字引用Student類
小結:
5. final關鍵字
- final表示是最終的,不能被改變的
- final可以修飾,方法,類,變量
- 被final修飾的方法,表示該方法是最終方法,不能被重寫
- 應用場景:當父類中定義的一些方法不希望別人(子類)去改變,就可以使用final修飾
- 被final修飾的類,表示該類是最終類,不能被繼承
- 應用場景:
- 安全性:如果一個類的實現已經是完整和安全的,不希望被其他類繼承并改變其行為,則可以將該類聲明為final。這樣可以確保該類的行為不會被修改或者被繼承后導致不安全的變化
- 應用場景:
- 被final修飾的變量,叫常量,只能被賦值一次
- 應用場景,當不想變量發生改變時,可以使用final修飾
示例代碼:
- 被final修飾的方法,表示該方法是最終方法,不能被重寫
- 被final修飾的類,表示該類是最終類,不能被繼承
- 被final修飾的變量,叫常量,只能被賦值一次
6. 常量
- 實際開發中,常量一般作為系統的配置信息,方便維護,提高可讀性
- 常量的命名規范:
- 單個單詞:全部大寫
- 多個單詞:全部大寫,單詞之間用下劃線隔開
- 細節:
- final修飾的變量是基本類型:那么變量存儲的數據值不能發送改變
- final修飾的變量是引用類型:那么變量存儲的地址值不能發送改變,對象內部可以改變
示例代碼:
public class Test {public static void main(String[] args) {// final修飾的變量是基本類型:記錄的值不能發生改變final double PI = 3.14;// final修飾的變量是引用類型:記錄的地址值不能發生改變,內部的屬性值還是可以改變的final Student S = new Student("小紅",13);// 記錄的地址值不能發生改變// S = new Student(); // 報錯// 內部的屬性值還是可以改變的S.setAge(100);S.setName("小芳");System.out.println(S.getName() + ", " + S.getAge());}
}class Student{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}
7. 權限修飾符
- 權限修飾符:是用來控制一個成員能夠被訪問的范圍的
- 權限修飾符可以修飾:成員變量,方法,構造方法,內部類
- 權限修飾符的分類:有4種
- 權限修飾符四種范圍由大到小:public > protected > default > private。
- public:public 修飾的成員變量和方法可以被任何類訪問。如果一個類是 public 類,那么這個類所在的源文件的文件名必須與類名相同
- protected:protected 修飾的成員變量和方法可以被同一類、同一包內的類以及其他包中的子類
- default:默認的權限修飾符,即不寫任何修飾符。同一包內的類可以訪問 default 修飾的成員變量和方法,不同包內的類不能訪問。
- private:private 修飾的成員變量和方法只能被同一類內的方法訪問,其他類無法直接訪問。
- 權限修飾符四種范圍由大到小:public > protected > default > private。
- 權限修飾符的使用規則:
- 實際開發中,一般只用private和public
- 成員變量私有
- 方法公開
- 特例:如果方法中的代碼是抽取其他方法中共性代碼,這個方法一般也私有
- 實際開發中,一般只用private和public
8. 代碼塊
- 局部代碼塊:
- 構造代碼塊:
- 靜態代碼塊:
- 格式:static {}
- 特點:需要通過static關鍵字修飾,隨著類的加載而加載,并且自動觸發,只執行一次
- 使用場景:在類加載的時候,做一些數據初始化的時候使用
小結:
9. 抽象類與抽象方法
- 抽象方法:將共性的行為(方法)抽取到父類之后,由于每一個子類執行的內容是不一樣的,所以,在父類中不能確定具體的方法體。該方法就可以定義為抽象方法。
- 抽象類:如果一個類中存在抽象方法,那么該類就必須聲明為抽象類
- 抽象類和抽象方法的定義格式:
- ???????抽象方法語法格式:public abstract 返回值類型 方法名(參數列表);
- 抽象類語法格式:public abstract class 類名{}
- 注意事項:
- 抽象類不能創建對象
- 抽象類中不一定有抽象方法,有抽象方法的類一定是抽象類
- 抽象類可以有構造方法
- 抽象類的子類:
- 要么重寫抽象類中的所有抽象方法
- 要么是抽象類
?
練習:???????
public class Test {public static void main(String[] args) {// 創建對象Frog frog = new Frog("小青蛙",1);frog.drink();frog.eat();}
}// 抽象類(父類)
abstract class Animal{private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Animal{name = " + name + ", age = " + age + "}";}public void drink(){System.out.println(getName() + "在喝水");}// 抽象方法public abstract void eat();
}// 青蛙-子類
class Frog extends Animal{public Frog() {}public Frog(String name, int age) {super(name,age);}// 實現父類的抽象方法@Overridepublic void eat() {System.out.println("青蛙吃蟲子");}}// 狗-子類
class Dog extends Animal{public Dog() {}public Dog(String name,int age) {super(name,age);}@Overridepublic void eat() {System.out.println("狗吃屎");}public String toString() {return "Dog{}";}
}// 山羊-子類
class Sheep extends Animal{public Sheep() {}public Sheep(String name,int age) {super(name,age);}@Overridepublic void eat() {System.out.println("山羊吃草");}
}
小結:
10. 接口
接口的定義和使用
- 接口用關鍵字interface來定義:public interface 接口名稱 {}
- 接口不能實例化
- 接口和類之間是實現關系,通過 implements 關鍵字表示:public class 類名 implements 接口名稱 {}
- 接口的子類(實現類)
- 要么重寫接口中的所有抽象方法
- 要么是抽象類
- 注意1:接口和類的實現關系,可以單實現,也可以多實現
- public class 類名 implements 接口1,接口2 {}
- 注意2:實現類還可以在繼承一個類的同時實現多個接口
- public class 類名 extends 父類 implements 接口名1,接口名2 {}
練習:
public class Test {public static void main(String[] args) {// 創建青蛙的對象Frog frog = new Frog("小青蛙",1);frog.eat();frog.swim();}
}/** 接口* */
interface Swim {public abstract void swim();
}/*
* 父類-動物
* */
abstract class Animal{private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name = name;this.age = age;}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}/*** 獲取* @return age*/public int getAge() {return age;}/*** 設置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Animal{name = " + name + ", age = " + age + "}";}// 吃的-行為public abstract void eat();
}/*
* 兔子-子類
* */
class Rabbit extends Animal{public Rabbit() {}public Rabbit(String name,int age) {super(name,age);}@Overridepublic void eat() {System.out.println(getName() + "吃胡蘿卜");}
}/*
* 狗類-子類
* */
class Dog extends Animal implements Swim{public Dog() {}public Dog(String name,int age) {super(name,age);}@Overridepublic void eat() {System.out.println(getName() + "吃骨頭");}// 實現Swim接口的swim方法@Overridepublic void swim() {System.out.println(getName() + "狗刨式游泳");}
}/*
* 青蛙-子類
* */
class Frog extends Animal implements Swim{public Frog() {}public Frog(String name,int age) {super(name,age);}@Overridepublic void swim() {System.out.println(getName() + "蛙泳");}@Overridepublic void eat() {System.out.println(getName() + "吃蟲子");}
}
接口中成員的特點
- 成員變量
- 只能是常量
- 默認修飾符:public static final
- 構造方法
- 接口中沒有構造方法
- 成員方法
- 只能是抽象方法
- 默認修飾符:public abstract?
- jdk7以前:接口中只能定義抽象方法
- jdk8的新特性:接口中可以定義有方法體的方法
- jdk9的新特性:接口中可以定義私有方法
接口和類之間的關系
- 類和類之間的關系
- 繼承關系,只能單繼承,不能多繼承,但是可以多層繼承
- 類和接口的關系
- 實現關系,可以單實現,也可以多實現,還可以在繼承一個類的同時實現多個接口
- 接口和接口的關系
- 繼承關系,可以單繼承,也可以多繼承
11. 內部類
初始內部類
內部類的分類:
- 成員內部類:了解
- 靜態內部類:了解
- 局部內部類:了解
- 匿名內部類:需要掌握
什么是內部類?
- 就是在一個類的里面,在定義一個類。
- 舉例:在A類的內部定義B類,B類就被稱為內部類
- 舉例:在A類的內部定義B類,B類就被稱為內部類
為什么要學習內部類?
- 需求:寫一個javabean類描述汽車
- 屬性:汽車的品牌,車齡,顏色,發動機的品牌,使用年限???????
小結:
匿名內部類
- 匿名內部類本質上就是隱藏了名字的內部類
- 語法格式:new 類名或者接口名(){ 重寫方法; };
示例代碼:
public class Test {public static void main(String[] args) {// 編寫匿名內部類的代碼new Swim() {// 重寫方法@Overridepublic void swim() {System.out.println("重寫了游泳的方法");}};}}interface Swim {public abstract void swim();
}
小結: