日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java_面向对象编程(高级篇)(非常详细整理总结)总

發布時間:2023/12/16 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java_面向对象编程(高级篇)(非常详细整理总结)总 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、類變量/靜態變量

1. 類變量引入

  • 提出一個問題:
  • 有一群小孩在玩堆雪人,不時有新的小孩加入,請問如何知道現在共有多少人在玩?,編寫程序解決。
  • 用傳統的方法解決:(創建一個 Child 類)
  • 思考:count 變量是一個獨立于小孩對象存在的變量,在main 方法中定義該變量,如果想要在其他類中訪問時,很麻煩。因此我們引出了類變量/靜態變量的概念。

2. 類變量快速入門

  • 思考: 在上題中,如果能在Child 類中設計一個變量 count 表示總人數,我們每次新建一個小孩對象時,就把 count 加 1,并且 count 是所有小孩對象共享的就可以了,所以我們可以使用類變量來解決。
  • 代碼實現:
public class ChildGame {public static void main(String[] args) {Child child1 = new Child("白骨精");child1.join();child1.count++;// 通過對象名來訪問類變量Child child2 = new Child("狐貍精");child2.join();child2.count++;Child child3 = new Child("老鼠精");child3.join();child3.count++;//類變量,可以通過類名來直接訪問,也可以通過對象名來訪問;System.out.println("共有" + Child.count + " 小孩加入了游戲...");//下面的輸出相同,因為所有對象都共用了類變量。System.out.println("child1.count=" + child1.count);//3System.out.println("child2.count=" + child2.count);//3System.out.println("child3.count=" + child3.count);//3} }class Child { //類private String name;//定義一個變量 count ,是一個類變量(靜態變量),static:靜態//該變量最大的特點就是會被Child 類的所有的對象實例共享public static int count = 0;public Child(String name) {this.name = name;}public void join() {System.out.println(name + " 加入了游戲..");} }
  • 顯而易見,將 count 設置為類變量后,解決了傳統方法出現的問題,類變量可以通過類名被直接訪問,在其他類中也可以方便地訪問該變量了。

3. 類變量的內存布局

  • 類對象的創建過程:
    • 在第一次創建一個類的對象時,在內存的方法區中會加載該類的信息(只會加載一次),與此同時伴隨著類的加載在堆內存中會生成一個類對象 (類對象不是類的一個具體對象,而是類的一個映射);
    • 類變量也伴隨著類的加載而生成,并存儲在類對象的尾部;
  • 只需記住兩點:

(1)類變量是同一個類的所有對象共享的變量;
(2)類變量在類加載的時候就已經產生了,因此只需要通過類名便可以直接訪問類變量。

4. 類變量基本概念

  • 類變量:也叫靜態變量/靜態屬性,是該類的所有對象共享的變量,任何一個該類的對象去訪問它時,取到的都是相同的值;同樣,任何一個該類的對象去修改它時,修改的也是同一個變量。
  • 基本語法:
  • 訪問類變量:
  • 注意:在訪問類變量時,需要滿足遵守修飾符的相關權限控制規則;類變量是隨著類的加載而創建,因此即使沒有創建對象實例也可以直接通過類名訪問。
  • 代碼實現:
public class VisitStatic {public static void main(String[] args) {//類名.類變量名//說明:類變量是隨著類的加載而創建,所以即使沒有創建對象實例也可以訪問;System.out.println(A.name);A a = new A();//通過對象名.類變量名System.out.println("a.name=" + a.name);} }class A {// 類變量/靜態成員變量/靜態屬性public static String name = "韓順平教育";// 普通屬性/普通成員變量/非靜態屬性/非靜態成員變量/實例變量private int num = 10; }
  • 補充:

變量的稱謂:(稱謂不同,但本質就是同一個東西)

  • 類變量 = 靜態成員變量 = 靜態屬性;
  • 普通成員變量 = 普通屬性 = 非靜態屬性 = 非靜態成員變量 = 實例變量;
  • 5. 類變量使用注意事項和細節

    • 細節如下:

    二、類方法/靜態方法

    1. 類方法基本概念

    • 類方法:也叫靜態方法,當一個普通的成員方法使用了 static 關鍵字修飾后,該方法就變成了靜態方法。
    • 基本語法:
    • 類方法的使用:

    (1) 推薦使用類名.類方法名來調用類方法。
    (2) 如果我們希望不創建對象,也可以調用某個方法(即僅把該方法當做一個工具來使用),那就把該方法定義為一個靜態方法。把這些工具方法都放進一個類,這個類可以當做我們的工具類來使用。

    • 類方法經典的使用場景:

    2. 類方法使用注意事項和細節

    • 細節如下:
    • 代碼實現:
    public class StaticMethodDetail {public static void main(String[] args) {D.hi();// 靜態方法,可以直接通過類名調用//非靜態方法,不能通過類名調用//D.say();, 錯誤,需要先創建對象,再調用new D().say();// 通過對象調用} }class D {private int n1 = 100;private static int n2 = 200;public void say() {// 非靜態方法,普通方法}public static void hi() {// 靜態方法,類方法// 類方法中不允許使用和對象有關的關鍵字,// 比如this和super。// System.out.println(this.n1); 錯誤}// 類方法(靜態方法)中 只能訪問 靜態變量 或靜態方法// 口訣:靜態方法只能訪問靜態成員。public static void hello() {System.out.println(n2);System.out.println(D.n2);//System.out.println(this.n2); 錯誤,不能使用this關鍵字hi();// 靜態方法中可以訪問靜態方法//say(); 錯誤,靜態方法中不能訪問非靜態方法和成員}// 普通成員方法,既可以訪問 非靜態成員,也可以訪問靜態成員;// 小結: 非靜態方法可以訪問 靜態成員和非靜態成員;public void ok() {//非靜態成員System.out.println(n1);say();//靜態成員System.out.println(n2);hello();} }
    • 注意:一切成員的訪問前提是,要遵守訪問修飾符限定的權限規則。

    三、main 方法

    1. 深入理解 main 方法

    • main 方法是一種特殊的靜態方法,它由Java虛擬機調用。
    • 解釋main 方法的形式:

    2. 注意事項和細節

    1) 在 main()方法中,我們可以直接調用 main 方法所在類的靜態方法或靜態屬性。
    2) 但是,不能直接訪問該類中的非靜態成員,必須創建該類的一個實例對象后,才能通過這個對象去訪問類中的非靜態成員。

    • 代碼舉例:
    public class Main01 {// 靜態的變量/屬性private static String name = "韓順平教育";// 非靜態的變量/屬性private int n1 = 10000;// 靜態方法public static void hi() {System.out.println("Main01的 hi 方法");}// 非靜態方法public void cry() {System.out.println("Main01的 cry 方法");}public static void main(String[] args) {// 1. 靜態方法main 可以訪問本類的靜態成員// 可以直接使用 name,和 hi 方法; System.out.println("name=" + name);hi();// 2. 靜態方法main 不可以訪問本類的非靜態成員// System.out.println("n1=" + n1); 錯誤// cry(); 錯誤//3. 靜態方法 main 要訪問本類的非靜態成員,需要先創建對象 , 再用對象調用Main01 main01 = new Main01();// 可以使用非靜態成員了;System.out.println(main01.n1);main01.cry();} }

    四、代碼塊

    1. 代碼塊基本概念

    • 代碼塊:又稱為初始化塊,屬于類中的成員【即是類的一部分】,類似于方法,將邏輯語句封裝在方法體中,用 {} 包圍起來。
    • 基本用法:
    • 代碼塊的理解:

    (1)相當于另外一種形式的構造器(是對構造器的補充機制),可以做初始化操作;
    (2)使用場景,如果多個構造器中都有重復的語句,可以抽取到代碼塊中,提高代碼的復用性,相當于對構造器的重載;
    (3)代碼塊調用的順序優先于構造器。

    二、代碼塊使用注意事項和細節

    • 注意事項:

    1. 類什么時候被加載

    (1)創建類的對象實例時(new),類會被加載。
    (2)存在繼承關系,當創建子類對象實例時,其所有上級父類也會被加載;并且父類先被加載,越上級的父類,越先被加載。
    (3)當使用類的靜態成員時(靜態屬性,靜態方法),類會被加載。
    (4)注意,類的加載是在內存的方法區中。

    2. 什么是代碼塊

    (1)static 關鍵字修飾的代碼塊也叫靜態代碼塊,它的作用就是對類進行初始化;它伴隨著類的加載而執行,并且只會執行一次。
    (2)沒有關鍵字修飾的代碼塊也叫普通代碼塊,它相當于是構造器的補充機制;每當我們創建一個類的對象時,普通代碼塊就會被調用一次;如果只是直接使用類的靜態成員,沒有創建對象,它不會被調用;注意,普通代碼塊的調用與類的加載沒有關系。

    3. 創建一個對象時,在一個類中各屬性和方法被虛擬機調用的順序

    (1)首先是調用靜態代碼塊和進行靜態屬性初始化 (注意,調用靜態代碼塊和靜態屬性初始化的優先級一樣,若有多個靜態代碼塊和靜態屬性初始化同時存在,則按他們定義的順序使用),這一步是在類的加載時進行的。
    (2)其次是正式在堆內存中創建一個對象空間,并調用普通代碼塊和進行普通屬性的初始化 (注意,調用普通代碼塊和普通屬性初始化的優先級一樣,若有多個普通代碼塊和普通屬性初始化同時存在,則按他們定義的順序使用)。
    (3)最后是調用類中的構造方法。
    (4)補充:對于普通的靜態方法,不會被虛擬機自動執行,啥時候被調用,啥時候執行。

    • 代碼舉例說明:
    public class CodeBlockDetail02 {public static void main(String[] args) {A a = new A();// 輸出如下:// (1) A 靜態代碼塊01 (2) getN1被調用...// (3) A 普通代碼塊01 (4) getN2被調用...// (5) A() 構造器被調用} }class A {// 普通代碼塊{ System.out.println("A 普通代碼塊01");}// 普通屬性的初始化private int n2 = getN2();// 靜態代碼塊static { System.out.println("A 靜態代碼塊01");}// 靜態屬性的初始化private static int n1 = getN1();// 靜態方法public static int getN1() {System.out.println("getN1被調用...");return 100;}// 普通方法/非靜態方法public int getN2() { System.out.println("getN2被調用...");return 200;}// 無參構造器public A() {System.out.println("A() 構造器被調用");} }

    4. 存在繼承關系時,調用普通代碼塊和普通屬性初始化的說明

    (1)在構造器/構造方法的最前面其實隱含了 super()語句,還有調用普通代碼塊和普通屬性的初始化的語句,最后才是構造器自己的語句。
    (2)我們這里所說的普通屬性的初始化,指的是屬性在默認初始化后進行的,在構造器內的初始化(這一部分的概念是在面對對象基礎部分學習的)。

    • 代碼舉例說明:
    public class CodeBlockDetail03 {public static void main(String[] args) {new BBB();//(1) AAA的普通代碼塊 (2) AAA() 構造器被調用//(3) BBB的普通代碼塊 (4) BBB() 構造器被調用} }// 父類 class AAA { // 普通代碼塊{System.out.println("AAA的普通代碼塊");}// 構造器public AAA() {//(1) super()//(2) 調用本類的普通代碼塊和普通屬性的初始化System.out.println("AAA() 構造器被調用....");} }// 子類 class BBB extends AAA {// 普通代碼塊{System.out.println("BBB的普通代碼塊...");}public BBB() {// (1)super()// (2)調用本類的普通代碼塊和普通屬性的初始化System.out.println("BBB() 構造器被調用....");} }

    5. 存在繼承關系時,創建一個子類對象,各個方法和屬性被虛擬機調用的順序

    • 首先是在類加載時,調用靜態代碼塊和靜態屬性的初始化。
      (1)父類的靜態代碼塊和靜態屬性(優先級一樣,按定義順序執行)。
      (2)子類的靜態代碼塊和靜態屬性(優先級一樣,按定義順序執行)。
    • 其次是在堆內存中創建對象空間,調用普通代碼塊和普通屬性的初始化,調用構造方法。
      (3)在構造器中調用父類的普通代碼塊和普通屬性的初始化(優先級一樣,按定義順序執行)。
      (4)執行父類的構造器其余的方法。
      (5)在構造器中調用子類的普通代碼塊和普通屬性的初始化(優先級一樣,按定義順序執行)。
      (6)執行子類的構造器其余的方法。
    • 代碼舉例說明:
    public class CodeBlockDetail04 {public static void main(String[] args) {// 說明// (1) 進行類的加載// 1.1 先加載 父類 A02 ;1.2 再加載子類 B02// (2) 創建對象空間// 2.1 從子類的構造器開始new B02();// 創建對象} }//父類 class A02 { static {System.out.println("A02的一個靜態代碼塊..");//(2)}{System.out.println("A02的第一個普通代碼塊..");//(5)}public int n3 = getVal02();//普通屬性的初始化public static int getVal01() {System.out.println("getVal01");//(1)return 10;}public int getVal02() {System.out.println("getVal02");//(6)return 10;}//構造器public A02() {//隱藏//super()//普通代碼和普通屬性的初始化System.out.println("A02的構造器");//(7)}}//子類 class B02 extends A02 { //static {System.out.println("B02的一個靜態代碼塊..");//(4)}public int n5 = getVal04();{System.out.println("B02的第一個普通代碼塊..");//(9)}public static int getVal03() {System.out.println("getVal03");//(3)return 10;}public int getVal04() {System.out.println("getVal04");//(8)return 10;}// 構造器public B02() {//隱藏了//super()//普通代碼塊和普通屬性的初始化System.out.println("B02的構造器");//(10)} }

    五、單例設計模式

    1. 什么是設計模式

    • 設計模式是靜態方法和靜態屬性的經典使用。
    • 設計模式是在大量的實踐中總結和理論化之后優選的代碼結構、編程風格、以及解決問題的思考方式。設計模式就像是經典的棋譜,不同的棋局,我們可以使用不同的棋譜,免去了我們自己的摸索。

    2. 什么是單例模式

    • 單例(單個的示例)
  • 所謂類的單例設計模式,就是采取一定的方法保證在整個的團軟件系統中,對某個類的只能存在一個對象實例,并且該類只提供一個取得其對象實例的方法。
  • 單例模式有兩種方式:(1)餓漢式;(2)懶漢式。
  • 3. 餓漢式單例模式的實現

    • 具體步驟:

    (1)將類的構造器私有化,防止其他類直接創建該類對象。
    (2)在類的內部創建一個 static 對象。
    (3)該類向外提供一個靜態的公共方法,返回 static 對象。

    • 代碼實現:
    public class SingleTon01 {public static void main(String[] args) {//通過靜態方法可以直接獲取對象,GirlFriend instance = GirlFriend.getInstance();System.out.println(instance);GirlFriend instance2 = GirlFriend.getInstance();System.out.println(instance2);// instance和instance2 其實是同一個對象System.out.println(instance == instance2);// true}}// GirlFriend 類 // 要求只能有一個女朋友 class GirlFriend {private String name;//為了能夠在靜態方法中,返回 gf 對象,需要將其修飾為 static//對象,通常是重量級的對象, 餓漢式可能造成創建了對象,但是沒有使用,造成資源的浪費private static GirlFriend gf = new GirlFriend("小紅紅");//如何保障我們只能創建一個 GirlFriend 對象//步驟[單例模式-餓漢式]//1. 將構造器私有化,防止其他類直接創建該類對象//2. 在類的內部直接創建對象(該對象是static)//3. 提供一個公共的static方法,返回 gf 對象private GirlFriend(String name) {System.out.println("構造器被調用...");this.name = name;}public static GirlFriend getInstance() {return gf;}@Overridepublic String toString() {return "GirlFriend{" +"name='" + name + '\'' +'}';} }
    • 思考:

    (1)為什么要將公共的訪問對象的方法 getInstance() 設置成靜態方法,去掉static 可以嗎?

    • 不可以,我們想要在其他類中不創建該類的對象就可以調用該方法,因此只能將其設置為靜態方法。

    (2)為什么要類中創建 static 的對象,去掉static 修飾符可以嗎?

    • 不可以,在類中訪問對象的方法 getInstance() 是靜態方法,其只能返回靜態的屬性,因此只能將對象設置成 靜態對象。

    (3)餓漢式的弊端是什么?

    • 弊端在于:在類加載時,該對象就會被自動創建了,無論有無使用該對象,它都存在,會造成資源的浪費。

    4. 懶漢式單例模式的實現

    • 具體步驟:

    (1)將類的構造器私有化,防止其他類直接創建該類對象。
    (2)在類的內部聲明一個 static 對象,但沒有真正創建對象空間。
    (3)該類向外提供一個靜態的公共方法,返回 static 對象。
    (4)只有當用戶第一次使用公共方法時,才創建對象空間;后面再次使用時,返回上次創建的對象。

    • 代碼實現:
    public class SingleTon02 {public static void main(String[] args) {Cat instance = Cat.getInstance();System.out.println(instance);//再次調用 getInstanceCat instance2 = Cat.getInstance();System.out.println(instance2);System.out.println(instance == instance2);// True} }//希望在程序運行過程中,只能創建一個Cat對象 //Cat 類 class Cat {private String name;private static Cat cat; // 默認是null,并未真正創建對象空間// 步驟//(1)將類的構造器私有化,防止其他類直接創建該類對象。//(2)在類的內部聲明一個 static 對象,但沒有真正創建對象空間。//(3)該類向外提供一個靜態的公共方法,返回 static 對象。//(4)只有當用戶第一次使用公共方法時,才創建對象空間;后面再次使用時,返回上次創建的對象。// 從而保證了單例private Cat(String name) {System.out.println("構造器調用...");this.name = name;}public static Cat getInstance() {if(cat == null) {//如果還沒有創建cat對象cat = new Cat("小可愛");}return cat;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +'}';} }

    5. 餓漢式和懶漢式的比較

    • 如下圖:

    六、final 關鍵字

    1. final 的基本概念

    • 基本介紹:
    • 代碼演示:
    public class Final01 {public static void main(String[] args) {E e = new E();//e.TAX_RATE = 0.09; 錯誤,屬性TAX_RATE 不能被修改} }// (1)如果我們要求A類不能被其他類繼承,可以使用final修飾 A類 final class A { }//class B extends A {} 錯誤,A類不能被繼承;class C {//如果我們要求 hi 方法不能被子類重寫,可以使用 final修飾 hi方法public final void hi() {} }class D extends C {/* 錯誤,hi 方法不能被重寫@Overridepublic void hi() {System.out.println("重寫了C類的hi方法..");}*/ }//當不希望類的的某個屬性的值被修改,可以用final 修飾 class E {// TAX_RATE 屬性也被稱為常量;public final double TAX_RATE = 0.08; }//當不希望某個局部變量被修改,可以使用final修飾 class F {public void cry() {// 這時,NUM 也稱為 局部常量;final double NUM = 0.01;// NUM = 0.9; 錯誤,NUM 不能被修改System.out.println("NUM=" + NUM);} }

    2. final 使用注意事項和細節

    • 注意事項和細節:

    (1)final 修飾的屬性又叫常量,一般用 XX_XX_XX 來命名。

    (2)final 修飾的屬性在定義時,必須賦初值,并且賦值后不能更改,賦值操作可以在以下位置(選擇一個就行)。

    • 在定義屬性時:如 public final double TAX_RATE = 0.08;
    • 在構造器中;
    • 在代碼塊中(靜態代碼塊或者普通代碼塊);

    (3)若 final 修飾的屬性同時被 static 修飾,則初始化的位置只能是以下位置(選擇一個就行)。

    • 在定義屬性時:如 public final static double TAX_RATE = 0.08;
    • 在靜態代碼塊中(不能在普通代碼塊和構造器中賦值);

    (4)final 類不能被繼承,但是可以創建該類的對象。

    (5)如果類沒有被 final 修飾,但是含有 final 方法,則雖然該方法不能被子類重寫,但是可以被子類繼承。

    • 代碼演示:
    public class FinalDetail01 {public static void main(String[] args) {CC cc = new CC();// 創建 final 修飾的CC類的對象new EE().cal();// EE類可以使用 DD類中的 fanal 方法} }class AA {/*(1)在定義屬性時:如 public final double TAX_RATE = 0.08;(2)在構造器中;(3)在代碼塊中(靜態代碼塊或者普通代碼塊);*/public final double TAX_RATE = 0.08;//1.定義時賦值public final double TAX_RATE2 ;public final double TAX_RATE3 ;// 在構造器中賦值public AA() {TAX_RATE2 = 1.1;}// 在代碼塊中賦值{TAX_RATE3 = 8.8;} }class BB {/*如果final修飾的屬性是靜態的,則初始化的位置只能是(1)在定義屬性時;(2)在靜態代碼塊中(不能在普通代碼塊和構造器中賦值);*/public static final double TAX_RATE = 99.9;//1.定義時賦值public static final double TAX_RATE2 ;// 在靜態代碼塊中賦值static {TAX_RATE2 = 3.3;} }//final類不能繼承,但是可以實例化對象 final class CC {}//如果類不是final類,但是含有final方法,則該方法雖然不能重寫,但是可以被繼承 //即,仍然遵守繼承的機制. class DD {public final void cal() {System.out.println("cal()方法");} }class EE extends DD {}

    (6)一般來說,如果一個類已經是 final 類了,就沒有必要再將該類的方法修飾成 final 方法;因為final 類不能被繼承,自然該類中的方法就不會被重寫。

    (7)final 類不能修飾構造器。

    (8)final 和 static 往往一起搭配使用,效率更高;底層的編譯器做了優化,使用兩者結一起修飾的屬性,在使用時不會導致類的加載,節約了資源。

    (9)包裝類(Integer、Double、Float…)和String 類都是 final 類,不能被繼承。

    • 代碼演示:
    public class FinalDetail02 {public static void main(String[] args) {// 不會輸出靜態代碼塊的內容,因為BBB 類沒有被加載System.out.println(BBB.num);//包裝類、String 都是 final 類,不能被繼承;} }// final 和 static 往往一起搭配使用,效率更高; // 底層的編譯器做了優化,使用兩者結一起修飾的屬性,在使用時不會導致類的加載,節約了資源。 class BBB {// 在調用靜態屬性 num時,若是只有static 修飾,則會加載整個BBB 類,// 但加上 final一起修飾后,則不會加載BBB 類public final static int num = 10000;static {System.out.println("BBB 靜態代碼塊被執行");} }final class AAA{// 一般來說,如果一個類已經是final類了,就沒有必要再將方法修飾成final方法// public final void cry() {} }

    七、抽象類

    1. 抽象類和抽象方法的基本概念

    (1)用 abstract 關鍵字來修飾一個類時,這個類就叫抽象類?;菊Z法:

    • 訪問修飾符 abstract 類名 {
      }

    (2)用 abstract 關鍵字來修飾一個方法時,這個方法就叫抽象方法。基本語法:

    • 訪問修飾符 abstract 返回類型 方法名 (形參列表);
    • 當父類的一些方法不確定時,我們可以用 abstract 關鍵字來修飾該方法,這個方法就是抽象方法;抽象方法不需要具體實現,所謂沒有具體實現就是該方法沒有方法體;
    • 而當一個類中存在抽象方法時,需要將該類聲明為抽象類。一般來說,抽象類會被其子類繼承,由其子類來實現抽象方法。

    2. 抽象類使用事項和細節

    (1)抽象類不能被直接實例化,即不能(new)創建抽象類的對象。(但是可以通過子類間接地實例化)
    (2)抽象類不一定要包含抽象方法,也就是說,抽象類中可以沒有 abstract 方法;但是存在 abstract 方法的類一定要聲明為 抽象類(abstract)。
    (3)abstract 關鍵字只能修飾類和方法。

    • 代碼舉例:
    public class AbstractDetail01 {public static void main(String[] args) {//抽象類,不能被實例化//new A(); 錯誤} }// 抽象類不一定要包含abstract方法。 // 也就是說,抽象類可以沒有abstract方法 abstract class A {public void hi() {System.out.println("hi");} }// 一旦類存在abstract方法,則這個類必須聲明為abstract abstract class B {public abstract void hi(); }//abstract 只能修飾類和方法,不能修飾屬性和其它的 class C {// public abstract int n1 = 1; 錯誤 }

    (4)抽象類中可以包含任意成員,比如:非抽象方法、靜態屬性、構造器等等;抽象類本質上還是類,只能由 public 或者 默認 訪問修飾符修飾。
    (5)抽象方法中不能有方法體,即不能被實現,抽象以(;)號結束。

    (6)如果一個類繼承了抽象類,則它必須實現(重寫)抽象類的所有抽象方法;除非它自己也聲明為抽象類,這樣就不用重寫父類的抽象方法。

    (7)抽象方法不能使用 private、final 和 static 關鍵字來修飾,因為這3個關鍵字都是與方法重寫相違背的。

    • private 修飾方法,將方法私有化,子類根本訪問不了該方法,所以自然不能重寫該方法。
    • final 修飾方法,將方法直接設置為不能重寫。
    • static 修飾方法,將方法靜態化,并與類綁定,所以子類是不能重寫 static 方法的。

    2. 抽象類的實踐—模板設計模式

    • 抽象類體現的就是一種模板模式的設計,抽象類作為多個子類的通用模板,子類在抽象類的基礎上進行擴展和改造,但子類總體上會保留抽象類的行為方式。
    • 模板設計模式能解決的問題:
    • 案例要求:

    有多個類,各自完成不同的任務job,要求統計各個類完成任務的時間。

    • 代碼實現:
    // 抽象父類-模板設計模式 abstract public class Template { public abstract void job(); //抽象方法//實現方法,調用 job方法public void calculateTime() {//得到開始的時間long start = System.currentTimeMillis();job(); // 動態綁定機制//得的結束的時間long end = System.currentTimeMillis();System.out.println("任務執行時間 " + (end - start));} } // 子類 public class AA extends Template {//實現Template的抽象方法job@Overridepublic void job() { long num = 0;for (long i = 1; i <= 800000; i++) {num += i;}} } // 子類 public class BB extends Template{//這里也去,重寫了Template的job方法public void job() {long num = 0;for (long i = 1; i <= 80000; i++) {num *= i;}} } // 測試類 public class TestTemplate {public static void main(String[] args) {AA aa = new AA();aa.calculateTime(); BB bb = new BB();bb.calculateTime();} }

    八、接口

    1. 接口的基本概念

    • 接口:將一些抽象方法封裝到一起,便形成了一個接口;當某個類需要使用這些方法時,便可以實現該接口,然后便可以使用這些方法了。
    • 定義接口的基本語法:
    interface 接口名 {靜態屬性;抽象方法; }
    • 類實現接口的基本語法:
    class 類名 implements 接口名 {重寫接口的抽象方法; }
    • 總結:接口就是更加抽象的抽象類;接口實現了程序設計的多態和高內聚低耦合的設計思想。
    • 特別說明:在jdk 8.0 之后,接口中可以有靜態方法和默認方法(default 修飾)的存在,且只允許添加這兩種。
      *對接口的理解:
    • 接口可以看做是父類的補充機制,可以對特定子類的功能進行擴展;接口也可以對某個需求設計進行規范。
    • 舉例來說,接口就像是一個包含了多個知識點(抽象方法)的技能,當某個人(某個子類)想要掌握這個技能的時候,就要把該技能的所有知識點都學會(重寫抽象方法);同時,該技能可以對其知識點進行規范(比如知識點的名稱、知識點的個數等等)。

    2. 接口的注意事項和細節

    (1)接口不能被實例化。
    (2)接口中的所有的方法默認用 public 修飾符修飾(可以省略);接口中的抽象方法的abstract 關鍵字可以省略。

    • void 方法名()== public abstract void 方法名()

    (3)一個普通類實現接口,則必須重寫接口中的所有抽象方法;抽象類實現一個接口,可以不用重寫接口的抽象方法。
    (4)一個類可以同時實現多個接口。
    (5)接口中的屬性,必須是 public static final 三者一起修飾的。

    • int a = 1 == public static final int a = 1

    (6)可以直接使用 接口名.屬性 來訪問接口中的屬性。
    (7)接口不可以繼承類,但是可以繼承多個其他的接口。

    (8)接口的修飾符只能是 public 和 默認,和類的修飾符一樣。
    (9)若一個子類同時繼承了父類和實現了一個接口,且父類和接口中存在同名的屬性,則子類在調用該屬性時,用 接口名.屬性 表示調用接口,用 super.屬性 表示調用父類。

    3. 實現接口和繼承關系的比較

    (1)繼承的價值主要在于:解決代碼的復用性和可維護性。
    (2)接口的價值主要在于:設計好各種規范(方法),讓實現接口的類去具體實現這些規范(方法)。
    (3)接口在一定程度上實現代碼解耦:即接口規范性 + 動態綁定機制。

    4. 接口的多態特性

    • 接口的引用可以指向實現了接口的類的對象(并不是接口的實例化)。語法如下:
      • 接口名 接口的引用 = new 類名();

    4.1 接口的多態參數

    • 可以將所有實現了接口的類的對象劃分為同一組接口的引用(類比于繼承的多態,可以將繼承了同一個父類的所有子類的對象當做同一組父類的引用),然后將該引用作為方法的形參。
    • 當傳遞給方法具體的類的對象作為實參時,根據動態綁定機制,可以調用正確的對象方法。

    請比較接口的多態使用和繼承的多態使用。

    • 代碼實現:
    public class InterfacePolyParameter {public static void main(String[] args) {//接口的多態體現//接口的引用 if01 可以指向 實現了IF接口的類的對象IF if01 = new Monster();if01 = new Car();//繼承體現的多態//父類類型的變量 a 可以指向 繼承AAA的子類的對象實例AAA a = new BBB();a = new CCC();} }// 接口 interface IF {}class Monster implements IF{}class Car implements IF{}// 父類 class AAA {}class BBB extends AAA {}class CCC extends AAA {}

    4.2 接口的多態數組

    • 可以將所有實現了接口的類的對象劃分為同一組接口的引用(類比與類的多態,可以將繼承了同一個父類的所有子類的對象當做同一組父類的引用)。
    • 然后將該引用作為數組類型,創建一個數組,數組中的元素則可以是所有實現了接口的類的對象。

    案例:給USB 數組中,存放 Phone 和 Camera 對象,Phone 類還有一個特有的方法 call(),請遍歷USB 數組,如果是 Phone 對象,除了調用 USB 接口定義的方法外,還需要調用 Phone 特有的方法。

    • 代碼實現:
    public class InterfacePolyArr {public static void main(String[] args) {//多態數組 -> 接口類型數組Usb[] usbs = new Usb[2];usbs[0] = new Phone_();usbs[1] = new Camera_();/*給Usb數組中,存放 Phone 和 相機對象,Phone類還有一個特有的方法call(),請遍歷Usb數組,如果是Phone對象,除了調用Usb 接口定義的方法外,還需要調用Phone 特有方法 call*/for(int i = 0; i < usbs.length; i++) {usbs[i].work();// 動態綁定機制// 需要進行類型的向下轉型if(usbs[i] instanceof Phone_) {// 判斷他的運行類型是 Phone_((Phone_) usbs[i]).call();}}} }interface Usb {void work(); }class Phone_ implements Usb {public void call() {System.out.println("手機可以打電話...");}@Overridepublic void work() {System.out.println("手機工作中...");} }class Camera_ implements Usb {@Overridepublic void work() {System.out.println("相機工作中...");} }

    4.3 接口的多態傳遞

    • 如果A 接口繼承了B 接口,而C 類實現了A 類,那么實際上相當于C 類也實現了B類。

    • 代碼實現:

    public class InterfacePolyPass {public static void main(String[] args) {//接口類型的變量可以指向,實現了該接口的類的對象實例IG ig = new Teacher();//如果IG 繼承了 IH 接口,而Teacher 類實現了 IG接口//那么,實際上就相當于 Teacher 類也實現了 IH接口.//這就是所謂的 接口多態傳遞現象.IH ih = new Teacher();} }// IH 接口 interface IH {void hi(); }// IG 接口繼承了IH接口 interface IG extends IH{}// 實現了IG 的類 class Teacher implements IG {@Overridepublic void hi() {} }

    九、內部類概述

    1. 內部類的基本概念

    • 內部類:一個類的內部又完整地嵌套了另一個類結構,則被嵌套的類成為內部類(inner class),嵌套其他類的類稱為外部類(outer class)。
    • 一個類中有五大成員:屬性、方法、構造器、代碼塊、內部類。
    • 內部類最大的特點就是可以直接訪問外部類的私有屬性,并且可以體現類與類之間的包含關系。
    • 內部類是面向對象學習的重難點,底層源碼中包含大量的內部類。

    2. 基本語法

    class Outer { // 外部類class Inner { // 內部類} }class Other { // 外部其他類 }

    3. 內部類的分類

    (1)定義在外部類的成員位置上:

    • 成員內部類(沒有 static 修飾)
    • 靜態內部類(使用 static 修飾)

    (2)定義在外部類的局部位置上(方法和代碼塊中):

    • 局部內部類(有類名)
    • 匿名內部類(無類名)重點!!!

    十、局部內部類

    • 局部內部類定義在外部類的局部位置(即方法和代碼塊中),并且具有類名。

    1. 局部內部類的用法與細節

    (1)局部內部類本質上還是類;但同時又相當一個局部變量,因此不能用任何訪問修飾符和 static 來修飾局部內部類,可以使用 final 修飾。

    (2)局部內部類的作用域只在定義它的方法或者代碼塊中。

    (3)局部內部類可以直接訪問外部類的所有成員,包括私有的(不需要創建外部類對象)。

    (4)外部類的其他成員不能直接訪問局部內部類的成員,只能通過在定義了局部內部類的方法中用局部內部類的對象調用其成員,然后再調用該方法,實現間接使用局部內部類的成員。

    (5)外部其他類不能訪問局部內部類。

    • 把局部內部類看做是一個方法中的局部變量,便容易理解了。

    (6)如果外部類中的成員和局部內部類中的成員重名時,內部類訪問該成員默認遵循就近原則;在局部內部類中想訪問外部類的同名成員,使用 外部類名.this.成員 訪問(外部類名.this 就相當于外部類的對象)。

    2. 細節代碼演示

    public class LocalInnerClass {//public static void main(String[] args) {Outer02 outer02 = new Outer02();outer02.m1();System.out.println("outer02的hashcode=" + outer02);} }class Outer02 { // 外部類private int n1 = 100;// 外部類的屬性// 外部類私有方法private void m2() {System.out.println("Outer02 m2()");}// 外部類普通方法public void m1() {// 局部內部類是定義在外部類的局部位置,方法和代碼塊中;// 不能添加訪問修飾符和 static ,但是可以使用 final 修飾;// 作用域 : 僅僅在定義它的方法或代碼塊中;class Inner02 { // 局部內部類(本質仍然是一個類,同時也是方法的局部變量)private int n1 = 800;// 局部內部類的私有屬性(與外部類的同名)public void f1() {// 局部內部類可以直接訪問外部類的所有成員,比如下面 外部類n1 和 m2();// 如果外部類和局部內部類的成員重名時,默認遵循就近原則,如果想訪問外部類的成員,使用 外部類名.this.成員 去訪問;// Outer02.this 本質就是外部類的對象, 即哪個對象調用了m1, Outer02.this就是哪個對象;System.out.println("n1=" + n1 + " 外部類的n1=" + Outer02.this.n1);// 打印Outer02.this 的哈希值,與main 方法中的對象 outer02比較,兩者相同;System.out.println("Outer02.this hashcode=" + Outer02.this);m2(); // 直接訪問外部類的私有方法;}} // 局部內部類結束// 外部類在m1方法中,可以創建一個Inner02 對象,// 這樣就可以調用m1 方法,自動創建Inner02 對象,使用其成員了;// 注意:不能在外部類的其他方法中創建m1 方法中的局部內部類對象;// 因為局部內部類的作用域只在定義它的方法或者代碼塊中。Inner02 inner02 = new Inner02();inner02.f1();} }

    十一、匿名內部類(重要!!!)

    • 匿名內部類定義在外部類的局部位置(即方法和代碼塊中),并且不具有類名。

    1. 匿名內部類的用法和細節

    • 基本語法
    // 第一種:實現接口的匿名內部類 接口名 接口的引用 = new 接口名() {重寫接口的抽象方法; };// 第二種:繼承父類的匿名內部類(父類可以是抽象類或普通類) 父類類型 父類的引用 = new 父類(形參列表) {重寫父類的抽象方法/方法; };

    (1)匿名內部類本質上還是類,但同時它本身還是一個對象。

    (2)匿名內部類就是實現了接口的一個類,或者是繼承了父類的一個子類;匿名內部類只會被創建一次,之后便被銷毀;其對象也只會被創建一次,但是該對象可以被一直使用。

    • 代碼解釋:
    // 實現接口的匿名內部類 public class AnonymousInnerClass {public static void main(String[] args) {Outer outer = new Outer();outer.method();} }class Outer { //外部類// 外部類的普通方法public void method() {// 實現接口的匿名內部類IA tiger = new IA() {@Overridepublic void cry() {System.out.println("老虎叫喚...");}}; // 內部類創建完畢// 查看匿名內部類的類名是否為 Outer$1System.out.println("tiger的運行類型=" + tiger.getClass());tiger.cry();// tiger對象 可以一直使用tiger.cry();tiger.cry();} }// 接口 interface IA {public void cry(); }分析:1.需求: 想實現IA接口,并創建對象2.傳統方式,是寫一個實現接口的類,實現該接口,并創建該類對象3.可要求是:該類只是使用一次,后面再不使用;4. 可以使用匿名內部類來簡化開發5. tiger的編譯類型是: IA接口6. tiger的運行類型是: 就是匿名內部類 Outer$1 (jdk分配的類名,不能使用)我們看底層分配 類名 Outer$1 ,如下:class Outer$1 implements IA {@Overridepublic void cry() {System.out.println("老虎叫喚...");}}7. jdk底層在創建匿名內部類 Outer$1,并立即就創建了 Outer$1 實例對象,并且把對象地址返回給 tiger;8. 匿名內部類 Outer$1 使用一次后,就不能再使用,但其對象 tiger可以一直使用。 // 繼承父類的匿名內部類 public class AnonymousInnerClass {public static void main(String[] args) {Outer outer = new Outer();outer.method();} }class Outer { //外部類// 外部類的普通方法public void method() {// 繼承父類的匿名內部類Father father = new Father("jack"){@Overridepublic void test() {System.out.println("匿名內部類重寫了test方法");}};System.out.println("father對象的運行類型=" + father.getClass()); // 輸出 Outer$2father.test();// 繼承抽象類的匿名內部類Animal animal = new Animal(){@Overridevoid eat() {System.out.println("小狗吃骨頭...");}};animal.eat();} }// 父類 class Father {// 構造器public Father(String name) {System.out.println("接收到name=" + name);}//方法public void test() {} }// 抽象類 abstract class Animal { abstract void eat(); }分析:1. father編譯類型 Father2. father運行類型 Outer$23. 底層會創建匿名內部類,如下class Outer$2 extends Father{@Overridepublic void test() {System.out.println("匿名內部類重寫了test方法");}}4. 同時也直接返回了 匿名內部類 Outer$2的對象5. 注意("jack") 參數列表會傳遞給 構造器。

    (3)匿名內部類既是一個類的定義,同時本身也是一個對象,又是一個局部變量。因此它可以不返回對象地址,通過自身直接調用其內部的成員;但這樣該匿名內部類的對象便只能使用一次。

    (4)匿名內部類的作用域只在定義它的方法或者代碼塊中;匿名內部類不能添加訪問修飾符 和 static,可以用 final 修飾,因為它的地位就是一個局部變量。

    (5)匿名內部類可以直接訪問外部類的所有成員,包括私有的(不需要創建外部類對象)。

    (6)外部類的其他成員不能直接訪問匿名內部類的成員,只能通過在定義了匿名內部類的方法中用匿名內部類的對象調用其成員,然后再調用該方法,實現間接使用匿名內部類的成員。

    (7)外部其他類不能訪問匿名內部類及其成員。

    (8)如果外部類中和成員和匿名內部類中的成員重名時,內部類訪問該成員默認遵循就近原則;在匿名內部類中想訪問外部類的同名成員,使用 外部類名.this.成員 訪問。

    • 代碼解釋:
    public class AnonymousInnerClassDetail {public static void main(String[] args) {Outer05 outer05 = new Outer05();outer05.f1();System.out.println("main outer05 hashcode=" + outer05);} }class Outer05 {private int n1 = 99;// 外部類的屬性public void f1() {// 創建一個基于類的匿名內部類;// 不能添加訪問修飾符,因為它的地位就是一個局部變量;// 作用域 : 僅僅在定義它的方法或代碼塊中Person p = new Person() {private int n1 = 88;// 匿名內部類的屬性,與外部類的同名@Overridepublic void hi() {// 匿名內部類可以直接訪問外部類的所有成員,包含私有的;// 如果外部類和匿名內部類的成員重名時,匿名內部類訪問的話,默認遵循就近原則;// 如果想訪問外部類的成員,則可以使用(外部類名.this.成員)去訪問;System.out.println("匿名內部類重寫了 hi方法 n1=" + n1 +" 外部內的n1=" + Outer05.this.n1 );// Outer05.this 就是調用 f1的 對象;System.out.println("Outer05.this hashcode=" + Outer05.this);}};// 匿名內部類定義結束p.hi();// 動態綁定, 運行類型是 Outer05$1// 匿名內部類也可以直接調用其成員, 匿名內部類本身也是一個對象new Person() {@Overridepublic void hi() {System.out.println("匿名內部類重寫了 hi方法,哈哈...");}@Overridepublic void ok(String str) {super.ok(str);}}.ok("jack");} }// 父類 class Person {public void hi() {System.out.println("Person hi()");}public void ok(String str) {System.out.println("Person ok() " + str);} }

    2. 匿名內部類的最佳實踐

    • 匿名內部類可以當做實參直接傳遞給方法,簡潔高效。

    案例如下:

    public class InnerClassExercise01 {public static void main(String[] args) {// 傳統方法:傳入一個實現接口的對象,浪費資源;f1(new Picture());// 新方法:把匿名內部類當做實參直接傳遞,簡潔高效。f1(new IL() {@Overridepublic void show() {System.out.println("這是一副名畫~~...");}});}// 靜態方法,形參是接口類型public static void f1(IL il) {il.show();} }//接口 interface IL {void show(); }//類->實現IL => 編程領域 (硬編碼) class Picture implements IL {@Overridepublic void show() {System.out.println("這是一副名畫XX...");} }

    十二、成員內部類

    • 成員內部類是定義在外部類成員位置的類,并且沒有 static 關鍵字修飾。

    成員內部類的用法與細節

    (1)成員內部類實質上就是一個類;同時它也是一個成員變量,因此它可以用任意的訪問修飾符來修飾(public、protected、默認、private),也可以用 final 來修飾,但不用 static 修飾(用 static 修飾的成員內部類叫做靜態內部類)。

    (2)成員內部類的作用域是整個類體;它可以直接訪問外部類的所有成員,包含私有的、靜態的(不需要創建外部類對象);注意:成員內部類中不能定義靜態成員。

    (3)外部類的其他成員想訪問成員內部類中的非靜態成員,需要先創建成員內部類的對象,再通過該對象來訪問(成員內部類中沒有靜態成員)。

    (4)外部其他類的成員訪問成員內部類的成員(前提是滿足訪問權限),有兩種方式,如下:

    // 首先需要先創建一個外部類的對象; Outer08 outer08 = new Outer08();// 第一種方式: 直接在外部其他類中創建成員內部類對象; // 這就是一個語法,不要特別的糾結 Outer08.Inner08 inner08 = outer08.new Inner08(); // outer08.new Inner08(); 相當于把 new Inner08() 作為整體當做是 outer08 成員 inner08.say(); // 這時便可以使用成員內部類的成員了// 第二方式: 在外部類中,編寫一個方法,可以返回 Inner08 對象; // public Inner08 getInner08Instance(){ return new Inner08(); } Outer08.Inner08 inner08Instance = outer08.getInner08Instance(); inner08Instance.say();// 這時便可以使用成員內部類的成員了

    (5)如果外部類中的成員和成員內部類中的成員重名時,內部類訪問該成員默認遵循就近原則;在成員內部類中想訪問外部類的同名成員,使用 外部類名.this.成員 訪問。

    十三、靜態內部類的用法與細節

    • 靜態內部類是定義在外部類成員位置的類,并且使用 static 關鍵字修飾。

    靜態內部類的用法與細節

    (1)靜態內部類實質上就是一個類;同時它也是一個成員變量,因此它可以用任意的訪問修飾符來修飾(public、protected、默認、private),也可以用 final 來修飾,而必須使用 static 修飾。

    (2)靜態內部類的作用域是整個類體;它可以直接訪問外部類的所有靜態成員,包含私有的(不需要創建外部類對象);注意:靜態內部類中可以定義非靜態成員和靜態成員(自己嘗試)。

    (3)外部類的其他成員想訪問靜態內部類中的非靜態成員,需要先創建靜態內部類的對象,再通過該對象來訪問;外部類的其他成員想訪問靜態內部類中的靜態成員,則只需要使用靜態內部類名.成員 便可直接訪問。

    (4)外部其他類的成員訪問成員內部類的成員(前提是滿足訪問權限),有兩種方式,如下:

    // 首先需要先創建一個外部類的對象; Outer outer = new Outer();// 第一種方式: 直接在外部其他類中創建靜態內部類對象; // 這就是一個語法,不要特別的糾結 Outer.Inner inner = new Outer.Inner(); // 因為靜態內部類,是可以通過類名直接訪問(前提是滿足訪問權限) inner.say(); // 這時便可以使用靜態內部類的成員了// 第二方式: 在外部類中,編寫一個方法,可以返回 Inner 對象; // public Inner getInnerInstance(){ return new Inner(); } Outer.Inner innerInstance = outer.getInnerInstance(); innerInstance.say();// 這時便可以使用靜態內部類的成員了

    (5)如果外部類中的成員和靜態內部類中的成員重名時,內部類訪問該成員默認遵循就近原則;在靜態內部類中想訪問外部類的同名成員,使用 外部類名.成員 訪問(靜態內部類中不能使用 this 關鍵字)。

    總結

    • 本文詳細總結講解了面向對象編程高級部分的知識,并深入解釋了每個知識點的注意事項和細節。面向對象編程高級部分的內容時基礎和中級的結合提示,同時又加入了新的概念,是Java基礎的重難點,也是一道分水嶺,理解并掌握這一部分的知識,需要有較好的面向對象的基礎,如果文中出現的所有未仔細講解的知識都在博主的面向對象編程基礎和中級篇講解過,小伙伴們有興趣可以去看看。小白博主已經盡力整理了,希望小伙伴們看后能有所收獲!
    • 最后,如果本文有什么錯漏的地方,歡迎大家批評指正!一起加油!!我們下一篇博文見吧!

    總結

    以上是生活随笔為你收集整理的Java_面向对象编程(高级篇)(非常详细整理总结)总的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 五月婷婷免费视频 | 黄wwwww| 奇米影视盒 | 无码人妻aⅴ一区二区三区玉蒲团 | 91精品国产高清一区二区三蜜臀 | 成人中文网 | 久久无毛| 内射一区二区三区 | 免费成人在线看 | 欧美乱大交xxxxx春色视频 | 成年人性生活免费视频 | 一区二区三区四区在线视频 | 日本女优黄色 | 欧美午夜网站 | 另类第一页 | 久久久久高清 | 日批免费观看视频 | 日韩欧美亚洲天堂 | 日韩作爱视频 | 亚洲爱情岛论坛永久 | 国产又粗又长视频 | 国产精品高清无码在线观看 | 欧美影院一区二区 | 亚洲精品一二三四区 | 欧美极品一区二区 | 日日干夜夜爽 | 91网站免费看 | 国产精品亚洲无码 | 久久在线视频 | 久久理论视频 | 99精品在线观看视频 | h在线网站| 浪潮av色 | 亚洲国产日韩一区无码精品久久久 | 五月婷婷激情小说 | 91亚洲精华 | 天天看天天操 | 永久免费看黄 | 高跟肉丝丝袜呻吟啪啪网站av | 公妇借种乱htp109cc | 日本福利一区二区 | 欧美日韩精品一区二区三区蜜桃 | 久久午夜无码鲁丝片 | 国产激情综合五月久久 | 麻豆影视免费观看 | 青青草伊人久久 | 国产永久免费 | 熟妇高潮喷沈阳45熟妇高潮喷 | 国产精品成人午夜视频 | jizz中国少妇 | 欧美黄色大片免费观看 | 日韩一区二区三区在线 | 大度亲吻原声视频在线观看 | 日韩久久久久久久久久 | 真实人妻互换毛片视频 | 欧美情趣视频 | 久久国产二区 | 在线视频日本 | 奇米色777| 黄色综合网 | 日日干天天射 | 亚洲天堂美女 | 看免费的毛片 | 日本三级视频网站 | 色乱码一区二区三区网站 | 飘花影院伦理片 | xxxx999| 三级网站在线免费观看 | av在线一 | 91禁在线动漫| www.精品视频| 91精品人妻一区二区三区 | 国产精品四虎 | 欧美成人三级在线视频 | 亚洲va中文字幕 | 久久欧美精品 | 青青草激情视频 | 一区二区国产精品视频 | 欧美一区高清 | www.玖玖玖 | 一本大道熟女人妻中文字幕在线 | 综合激情网 | 一本—道久久a久久精品蜜桃 | 四虎永久免费影院 | 成人黄色在线 | 丝袜诱惑一区二区 | 伊人久久大香 | 国产美女黄色片 | 黑白配在线观看免费观看 | 谁有毛片网址 | 日韩电影一区二区三区 | 国产精品视频入口 | 国产高清在线免费 | 夜夜看av | 肉丝袜脚交视频一区二区 | 日本色悠悠 | 国产极品一区二区 | 97人人人| 国产suv精品一区二区四 |