一、程式設計原則:
設計模式;
别人問你設計模式是啥玩意?為了顯得很專業,你可以淡淡的說道:“它是一套被反複使用,被多數人知曉的,經過分類編目的,代碼設計經驗的總結”(心道:尼瑪,還好有度娘!)
想要學設計模式,程式設計的6大原則,怎麼可以會不清楚?
開-閉原則(政治家,隻開放不改革):對修改關閉,對擴充開放。
對原有的功能(代碼)的修改是關閉(修改的越少越好)
還可以很友善的對原有功能進行擴充。
注:目測為黑社會大哥屬性,其他小弟都要圍着它轉;它更像是其他五個原則的總綱,前五個原則就是圍着它轉的,隻要我們盡量的遵守前五個原則,那麼設計出來的系統應該就比較符合開閉原則了,相反,如果你違背了太多,那麼你的系統或許也不太遵循開閉原則。
單一原則(大工匠,做事專一):每個類都隻負責單一的功能,并盡量把這一個功能做到極緻!
依賴倒置原則(藝術家,愛抽象派):高層子產品不該依賴于低層子產品,二者都應該依賴于抽象,抽象不應該依賴于細節,細節應該依賴于抽象。
接口最小化原則/接口隔離原則(大齡剩女,挑三揀四):強調的是一個接口擁有的行為應該盡可能的小。
注:最小接口原則一般我們是要盡量滿足的,如果實在有多餘的方法,這時候就輪到預設擴充卡上場了。
裡氏替換原則(大孝子,父命不敢違):一個子類應該可以替換掉父類并且可以正常工作。隐含說,子類一般不該重寫父類的方法, 防止子類不能實作和父類一樣的功能;
注:很多情況下,我們不必太理會它,比如模闆方法模式,預設擴充卡,裝飾器模式等一些設計模式,就完全不搭理它。
迪米特原則/最小知道原則(奇葩少年,夢想是患上自閉症):一個類應當不要讓外部的類知道自己太多,也不要知道外部類太多;(高内聚,低耦合)
二、多态polymorphism
多态的概念:多态是一種能力,一種可以父類引用指向子類對象,并可以在運作期根據對象實際的類型執行對應類型的方法的功能。
多态形成的必要的條件:
1:繼承。
2:父類引用指向子類對象。
3:子類重寫父類的方法。父類引用調用被重寫的方法。
1:使用父類類型作為方法的參數,傳遞的是子類對象。
2:使用父類類型作為方法的傳回值,傳回的是子類對象。
例1:
public class TestAnimal {
public static void main(String[] args) {
Animal animal = new Animal();
animal.sound();
Tiger tiger = new Tiger();
tiger.sound();
Animal ani = new Tiger();
ani.sound();
}
class Animal{
void sound(){
System.out.println("小動物 吱哇亂叫!");
class Tiger extends Animal{
@Override
void sound() {
System.out.println("老虎 ヾ(≧O≦)〃嗷~ 的一聲~~~");
例2:
//各個國家的人在餐廳吃飯
public class TestRestaurant {
Restaurant restaurant = new Restaurant("盧旺達飯店");
restaurant.showEat(new Chinese("偉大的炎黃子孫"));
restaurant.showEat(new America("美利堅合衆國"));
restaurant.showEat(new Japanese("小日本"));
restaurant.showEat(new Indian("阿三"));
restaurant.showEat(new Italian("意大利"));
System.out.println(restaurant);
//在一定程度上違背了開閉原則,隻要添加一個新的Person 的子類,那麼就需要在 Restaurant 重載添加一個 showEat 的方法。
// Person 引用指向 具體的其他的子類的對象。
// 多個國家的人繼承了Person
// 多個國家的類 重寫 了Person 類的eat 方法。
class Restaurant {
private String name;
Restaurant(String name) {
this.name = name;
// void showEat(Chinese chinese){
// chinese.eat();
// }
//
// void showEat(America america){
// america.eat();
// void showEat(Japanese japanese){
// japanese.eat();
// void showEat(Indian indian){
// indian.eat();
void showEat(Person person){
person.eat();
public String toString() {
return "Restaurant [name=" + name + "]";
class Person {
//國家的名字
private String countryName;
Person(String countryName) {
this.countryName = countryName;
void eat(){
System.out.println(countryName + " 的人 在吃飯!");
public String getCountryName() {
return countryName;
class Chinese extends Person{
public Chinese(String countryName) {
super(countryName);
void eat() {
System.out.println(getCountryName() + "\t 使用 筷子 吃飯!可好吃了!");
class America extends Person{
public America(String countryName) {
System.out.println(getCountryName() + "\t 使用刀叉 吃 四頓飯");
class Japanese extends Person{
public Japanese(String countryName) {
System.out.println(getCountryName() + "\t 喜歡殺戮大海中的鲨魚寶寶,然後吃掉他們的魚鳍!真殘忍啊!");
class Indian extends Person{
public Indian(String countryName) {
System.out.println(getCountryName() + "\t 用腳揉面,然後用抓着吃!");
class Italian extends Person{
public Italian(String countryName) {
System.out.println(getCountryName() + "\t 吃意大利面!味道馬馬虎虎吧!");
例3:
package com.bjsxt.polymorphism.oop0524;
//人演奏樂器(大鼓Drum,吉他Guitar,鋼琴Piano,小号Trumpet,三弦Trichord)
public class TestInstrument {
People people = new People();
people.play(new Drum(10000, "大鼓"));
people.play(new Guitar(5000, "吉他"));
people.play(new Trichord(20000, "三弦"));
people.play(new Trumpet(1000, "小号"));
people.play(new Piano(200000, "鋼琴"));
//所有的樂器的父類
class Instrument{
private int price;
public Instrument() {
Instrument(int price, String name) {
super();
this.price = price;
public int getPrice() {
return price;
public void setPrice(int price) {
public String getName() {
return name;
public void setName(String name) {
return "Instrument [price=" + price + ", name=" + name + "]";
//這個父類的方法的實作沒有太大的意義,空實作,該方法存在的意義在于被子類重寫。
class Drum extends Instrument{
Drum(int price, String name) {
super(price, name);
System.out.println(getName() + "\t被用力的敲打,發出了。。咚咚咚。。。的聲音");
class Guitar extends Instrument{
Guitar(int price, String name) {
System.out.println(getName() + "\t 撥弄了幾下,發出了,叮叮叮的聲音!");
class Trichord extends Instrument{
Trichord(int price, String name) {
System.out.println(getName() + "\t 撥弄了幾下,發出了,當~當~當~的聲音!");
class People{
// void play(Trichord trichord){
// trichord.sound();
// void play(Drum drum){
// drum.sound();
// void play(Guitar guitar){
// guitar.sound();
// void play(Trumpet trumpet){
// trumpet.sound();
void play(Instrument instrument){
instrument.sound();
class Trumpet extends Instrument{
Trumpet(int price, String name) {
System.out.println(getName() + "\t 被吹了幾下,發出了 嘟嘟嘟的聲音");
class Piano extends Instrument{
Piano(int price, String name) {
System.out.println(getName() + "\t 被彈了幾下,發出了,叮當叮當的聲音!!!");
三、使用多态解釋方法重寫
1:子類的重寫方法通路權限必須大于等于父類的?
在編譯期對象無法确定在運作期具體調用執行的哪個方法。
如果子類降低了被通路的權限,那麼如果在運作期執行的是子類重寫方法,那麼可以造成被重寫的方法通路不到。
2:傳回類型:
可以是父類的方法的傳回類型的子類型。
因為這樣做是安全的,子類對象的具有的功能是大于等于父類的。父類對象可以執行的功能,子類對象肯定沒問題。
3:子類重寫的方法可能産生的問題要小于等于父類的。
如果一個方法編譯、運作的時候可能會有一些問題,那麼我們必須通過代碼加以處理。
如果子類的方法産生的問題更多,那麼處理父類方法的代碼可能解決不掉因為多态而調用的子類的方法産生的問題。
四、多态轉型
//自動向上類型轉換(小類型向大類型自動轉換)
//因為這樣做是安全的。老虎當動物來用了。因為動物能做的,老虎都能做。
//強制向下(大類型向小類型轉換) 可不可以将一個動物 當老虎來用。 不能将将一個當動物用的兔子,當老虎用。
//不安全。
Animal rabbit = new Rabbit();
//強制向下類型轉換的文法 ,隻有當一個對象的實際類型是強制轉換的類型的類型的時候,那麼這種向下強轉才可以成功。
Tiger tiger = (Tiger)ani;
tiger.eatRabbit();
1:自動向上是 多态的基礎。
2:強制向下,隻有當我們需要使用子類的特有的方法的時候,才有必要将父類類型的對象強制轉換為子類類型。
//通過什麼樣的方式可以避免向下強轉的意外。
//instanceof 的主要用途,用于判斷一個對象是否可以強制轉換為指定類型的對象。
if(rabbit instanceof Tiger){
Tiger tiger1 = (Tiger)rabbit;
五、多态和重載
public class A{
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
//a2調用的方法必須是A中存在的方法,show(A obj) 方法又被子類重寫,是以執行的是子類中重寫的方法
System.out.println(a2.show(b)); //B and A ???
//a2調用的是A中存在的方法。 B沒有重寫show(D obj) 是以調用的就是A 中的show(D obj)
System.out.println(a2.show(d)); //A and D ???
//b調用的是B 中有的方法 show(D obj) 是從A中繼承下來的。直接調用即可。
System.out.println(b.show(d)); //A and D ???
System.out.println(a1.show(b)); //A and A
System.out.println(a1.show(c)); //A and A
System.out.println(a1.show(d)); //A and D
System.out.println(a2.show(c)); //B and A
System.out.println(b.show(b)); //B and B
System.out.println(b.show(c)); //B and B
public String show(D obj){
return ("A and D");
}
public String show(A obj){
return ("A and A");
class B extends A{
//B自定義的方法
public String show(B obj){
return ("B and B");
//重寫
public String show(A obj){
return ("B and A");
//繼承下來的方法
public String show(D obj){
}
class C extends B{
class D extends B{
六、簡單工廠模式
java 中 有 23 種設計模式。
設計類的要求:高内聚、低耦合。
高内聚:類的内部的成員之間的關系是非常緊密的。
低耦合:類和類之間的耦合度要盡量小。
簡單工廠模式的作用:降低類和類之間的耦合度的。
/**
* 簡單工廠模式,用來建立對象的
*
*/
public class MyFactory {
//寫一個工廠方法,通過傳入的字元串的值,建立對應的類的對象并傳回。
public static Person createPerson(String className){
Person person = null;
//根據類名,給person 指派不同的子類對象
switch(className){
case "Chinese":
person = new Chinese("炎黃子孫中國人");
break;
case "America":
person = new America("美國佬");
case "Japanese":
person = new Japanese();
case "Indian":
person = new Indian("阿三");
case "Italian":
person = new Italian("意大利");
return person;
七、單例設計模式
23 種設計模式中的很重要的一種。
作用:如果某一個類在一工程中隻希望建立該類的唯一的一個對象。那麼就可以使用單例設計模式,保證該類隻被執行個體化一次。
單例設計模式:SingleTon。
如何去設計一個單例類。
public class TestSingleTon {
MySingltTon mySingltTon = MySingltTon.getInstance();
System.out.println(mySingltTon.getData());//0
mySingltTon.setData(10);
System.out.println(mySingltTon.getData());//10
MySingltTon mySingltTon2 = MySingltTon.getInstance();
System.out.println(mySingltTon2.getData());//10
////需要隻能被執行個體化一次的那個單例類。
//class MySingltTon{
// //隻執行一次的代碼,在類加載的時候執行
// //餓漢模式 可能會導緻 啟動延遲
// private final static MySingltTon singltTon = new MySingltTon();
// //私有化構造方法
// private MySingltTon() {
// //寫一個建立本類對象的方法。
// //寫一個得到唯一執行個體的方法
// public static MySingltTon getInstance(){
// return singltTon;
//}
//懶漢模式
class MySingltTon{
private int data;
public int getData() {
return data;
public void setData(int data) {
this.data = data;
private static MySingltTon singltTon;
private MySingltTon() {
//懶漢模式 第一使用該唯一執行個體 的時候進行對象的初始化
//寫一個得到唯一執行個體的方法
public static MySingltTon getInstance(){
if(singltTon == null){
singltTon = new MySingltTon();
return singltTon;
八、final
final:可以用來修飾變量,讓變量具有了不可被修改的屬性。 不可變的變量。
final 還可以修飾什麼内容?
1:修飾變量: 終态變量。
2:修飾方法: 終态方法,不能被子類重寫。
3:修飾類: 終态類,不能有子類。不能被其他的類繼承。
九、抽象類
概念:如果一個類被關鍵字abstract 修飾 那麼該類就是抽象類。
抽象類特點:
1:抽象類是不允許被執行個體化的。
2:抽象類隻能作為類繼承層次上層類,作為父類出現。
作用:作為父類,被其他的類繼承。
注意:如果一個抽象類中包含了抽象方法,那麼它的子類要麼聲明成抽象的,要麼實作所有的父類的抽象方法。
抽象類出現的意義:如果在做類的設計的時候,不希望設計的類被執行個體化,隻作為父類出現,那麼就可以将該類聲明成抽象的類。使用abstract 修飾一下。
1:抽象類中一定有抽象的方法?
答:不一定的。
2:有抽象方法的類,一定是抽象類?
答:對的。
3:抽象類是否可以用final 修飾?
答:不可以,abstract 和 final 是互斥的。
4:靜态方法是否可以聲明成抽象方法?
答:不可以的。靜态的方法可以被繼承,不能被重寫。抽象方法需要被子類實作。語義有沖突,static abstract 互斥存在。
5:抽象類中定義的抽象方法,每一個抽象的方法都是定義了一個規則!!
答:父類在定義抽象方法的時候,對于子類實作抽象方法的功能是有要求的。但是對于實作的細節沒有要求。
子類在實作的時候,必須按照父類的規則要求去實作功能,不然最終可能無法達到預期效果。
6:類的執行個體成員變量是否可以實作多态?
答:不可以實作多态。變量的值取決于對象中的變量的聲明的類型,而不是對象中的變量的實際所在的類型。
7:靜态的成員方法是否可以實作多态?
答:不可以。不能重寫何來多态。
總結:多态是對象的多态,隻針對于對象的執行個體方法。
多态的簡單實作:
十、抽象類和非抽象類的異同:
相同點:
1:都是類,都是用來描述對象的。都是作為模版來使用。
2:非抽象類包含的類中的成員類型,,抽象類中都可以存在。
不同點:
1:抽象類不能被執行個體化,非抽象的可以被執行個體化。
2:抽象類隻能作為父類使用,非抽象的既可以作為父類(沒有final 修飾的)也可以不作為父類使用。
3:抽象類中可以包含抽象方法,非抽象不可以。
4:定義的方式不同,抽象類用abstract 修飾,非抽象不允許用abstract。
十一、equals
equals:Object 類的方法:
public boolean equals(Object obj)訓示其他某個對象是否與此對象“相等”。
equals 方法在非空對象引用上實作相等關系:
自反性:對于任何非空引用值x,x.equals(x) 都應傳回 true。
對稱性:對于任何非空引用值x 和 y,當且僅當 y.equals(x) 傳回 true 時,x.equals(y) 才應傳回 true。
傳遞性:對于任何非空引用值x、y 和 z,如果 x.equals(y) 傳回 true,并且 y.equals(z) 傳回 true,那麼 x.equals(z) 應傳回 true。
一緻性:對于任何非空引用值x 和 y,多次調用 x.equals(y) 始終傳回 true 或始終傳回 false,前提是對象上 equals 比較中所用的資訊沒有被修改。
對于任何非空引用值x,x.equals(null) 都應傳回 false。
Object 類的 equals 方法實作對象上差别可能性最大的相等關系;即,對于任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象時,此方法才傳回 true(x == y 具有值 true)。
注意:當此方法被重寫時,通常有必要重寫hashCode 方法,以維護 hashCode 方法的正常協定,該協定聲明相等對象必須具有相等的哈希碼。
參數:
obj - 要與之比較的引用對象。
傳回:
如果此對象與obj 參數相同,則傳回 true;否則傳回 false。
==:判斷等号
1:如果比較的兩個變量的類型是基本資料類型,那麼比較的值是否相等。
2:如果比較的是引用資料類型。比較的是對象的引用,首位址。
對于引用資料類型來說,如果想比較兩個對象的内容,不能使用== 隻能通過方法來實作。
Object 類的equals 方法就是做這個的。
但是Object 類的 equals 的預設實作比較的也是位址。
是以,子類需要重寫equals 方法。
例:
public class TestEquals {
Student s1 = new Student(12, "小剛", "男");
Student s2 = new Student(12, "小剛", "男");
System.out.println(s1 == s2);//false
// System.out.println(s1.equals(s2));//Object類的比較 也是false。
System.out.println(s1.equals(s1));//true
System.out.println(s1.equals(null));//false
System.out.println(s1.equals("123"));//false
System.out.println(s1.equals(s2));//true
class Student{
private int age;
private String gender;
public Student() {
Student(int age, String name, String gender) {
this.age = age;
this.gender = gender;
public int getAge() {
return age;
public void setAge(int age) {
public String getGender() {
return gender;
public void setGender(String gender) {
return "Student [age=" + age + ", name=" + name + ", gender=" + gender + "]";
// @Override
public boolean equals(Object obj) {
// obj 是否為null
if(obj == null){
return false;
//obj 和目前對象一樣
if(obj == this){
return true;
if(!(obj instanceof Student)){
//比較屬性
Student s = (Student)obj;
if(s.age != this.age)
if(!s.name.equals(this.name))
if(!s.gender.equals(this.gender))