Java學習_面向物件程式設計
阿新 • • 發佈:2020-12-24
- 抽象類
- 一個
class
定義了方法,但沒有具體執行程式碼,這個方法就是抽象方法,抽象方法用abstract
修飾。因為抽象類本身被設計成只能用於被繼承,因此,抽象類可以強迫子類實現其定義的抽象方法,否則編譯會報錯。因此,抽象方法實際上相當於定義了“規範”。 - 抽象方法的類都是抽象類,抽象類不全是抽象方法。
-
面向抽象程式設計的本質就是:
-
上層程式碼只定義規範(例如:
abstract class Person
); -
不需要子類就可以實現業務邏輯(正常編譯);
-
具體的業務邏輯由不同的子類實現,呼叫者並不關心。
- 一個
- 介面
- 如果一個抽象類沒有欄位,且所有方法全部都是抽象方法,就可以把該抽象類改寫為介面:
interface
- 介面中屬性預設public static final 修飾 方法預設public abstract修飾
- 一個具體的
class
去實現一個interface
時,需要使用implements
關鍵字。 - 一個類可以實現多個
interface。
- 一個
interface
可以繼承自另一個interface
。interface
繼承自interface
使用extends
,它相當於擴充套件了介面的方法。1 interface Hello { 2 void hello(); 3 } 4 5 interface Person extends Hello { 6 void run(); 7 String getName();
View Code
- 如果一個抽象類沒有欄位,且所有方法全部都是抽象方法,就可以把該抽象類改寫為介面:
- 包
- 在Java虛擬機器執行的時候,JVM只看完整類名,因此,只要包名不同,類就不同。
- 包沒有父子關係。java.util和java.util.zip是不同的包,兩者沒有任何繼承關係。
- 位於同一個包的類,可以訪問包作用域的欄位和方法。不用
public
、protected
、private
修飾的欄位和方法就是包作用域。 -
import
- 直接寫出完整類名 mr.jun.Arrays arrays = new mr.jun.Arrays();
- 用
import
語句,匯入Arrays,然後寫簡單類名。
1 // Person.java 2 package ming;
-
import static 包名
,它可以匯入一個類的靜態欄位和靜態方法。1 package main; 2 3 // 匯入System類的所有靜態欄位和靜態方法: 4 import static java.lang.System.*; 5 6 public class Main { 7 public static void main(String[] args) { 8 // 相當於呼叫System.out.println(…) 9 out.println("Hello, world!"); 10 } 11 }
-
如果是簡單類名,按下面的順序依次查詢:
-
查詢當前
package
是否存在這個class
; -
查詢
import
的包是否包含這個class
; -
查詢
java.lang
包是否包含這個class
。
-
- 因此,編寫class的時候,編譯器會自動幫我們做兩個import動作:
-
預設自動
import
當前package
的其他class
; -
預設自動
import java.lang.*
。 - 自動匯入的是java.lang包,但類似java.lang.reflect這些包仍需要手動匯入。
- 如果有兩個
class
名稱相同,例如,mr.jun.Arrays
和java.util.Arrays
,那麼只能import
其中一個,另一個必須寫完整類名。
-
- 內部類
- 普通類有個最大的不同,就是Inner Class的例項不能單獨存在,必須依附於一個Outer Class的例項。
1 public class Main { 2 public static void main(String[] args) { 3 Outer outer = new Outer("Nested"); // 例項化一個Outer 4 Outer.Inner inner = outer.new Inner(); // 例項化一個Inner 5 inner.hello(); 6 } 7 } 8 9 class Outer { 10 private String name; 11 12 Outer(String name) { 13 this.name = name; 14 } 15 16 class Inner { 17 void hello() { 18 System.out.println("Hello, " + Outer.this.name); 19 } 20 } 21 }
- Inner Class和普通Class相比,除了能引用Outer例項外,還有一個額外的“特權”,就是可以修改Outer Class的
private
欄位,因為Inner Class的作用域在Outer Class內部,所以能訪問Outer Class的private
欄位和方法。(Inner Class除了有一個this
指向它自己,還隱含地持有一個Outer Class例項,可以用Outer.this
訪問這個例項。) - 匿名內部類
- 不需要在Outer Class中明確地定義這個Class,而是在方法內部,通過匿名類(Anonymous Class)來定義。
1 public class Main { 2 public static void main(String[] args) { 3 Outer outer = new Outer("Nested"); 4 outer.asyncHello(); 5 } 6 } 7 8 class Outer { 9 private String name; 10 11 Outer(String name) { 12 this.name = name; 13 } 14 15 void asyncHello() { 16 Runnable r = new Runnable() { //重寫父類或者介面的方法 17 @Override 18 public void run() { 19 System.out.println("Hello, " + Outer.this.name); 20 } 21 }; 22 new Thread(r).start(); 23 } 24 }
- 不需要在Outer Class中明確地定義這個Class,而是在方法內部,通過匿名類(Anonymous Class)來定義。
- 靜態內部類
-
1 public class Main { 2 public static void main(String[] args) { 3 Outer.StaticNested sn = new Outer.StaticNested(); //外部類無需例項化 4 sn.hello(); 5 } 6 } 7 8 class Outer { 9 private static String NAME = "OUTER"; 10 11 private String name; 12 13 Outer(String name) { 14 this.name = name; 15 } 16 17 static class StaticNested { 18 void hello() { 19 System.out.println("Hello, " + Outer.NAME); 20 } 21 } 22 }
- 用
static
修飾的內部類和Inner Class有很大的不同,它不再依附於Outer
的例項,而是一個完全獨立的類,因此無法引用Outer.this
,但它可以訪問Outer
的private
靜態欄位和靜態方法。如果把StaticNested
移到Outer
之外,就失去了訪問private
的許可權。
-
- 普通類有個最大的不同,就是Inner Class的例項不能單獨存在,必須依附於一個Outer Class的例項。
-
classpath和jar
- classpath和jar
-
- 圖1
- 圖2
- 模組
- 多型
- 在繼承關係中,子類如果定義了一個與父類方法簽名完全相同的方法,被稱為覆寫(Override)。
- Java的例項方法呼叫是基於執行時的實際型別的動態呼叫,而非變數的宣告型別。(多型)
-
public void runTwice(Person p) { p.run(); p.run(); }
它傳入的引數型別是
Person
,我們是無法知道傳入的引數實際型別究竟是Person
,還是Student
,還是Person
的其他子類,因此,也無法確定呼叫的是不是Person
類定義的run()
方法。
-
覆寫Object方法
toString()
:把instance輸出為String
;equals()
:判斷兩個instance是否邏輯相等;Java equals方法學習hashCode()
:計算一個instance的雜湊值。
- 在子類的覆寫方法中,如果要呼叫父類的被覆寫的方法,可以通過
super
來呼叫。class Person { protected String name; public String hello() { return "Hello, " + name; } } Student extends Person { @Override public String hello() { // 呼叫父類的hello()方法: return super.hello() + "!"; } }
- 方法標記為
final
。用final
修飾的方法不能被Override
: - 類本身標記為
final
。用final
修飾的類不能被繼承: - 用
final
修飾的欄位(包括區域性變數)在初始化後不能被修改。- 可以在構造方法中初始化final欄位123
1 class Person { 2 public final String name; 3 public Person(String name) { 4 this.name = name; 5 } 6 }
- 可以在構造方法中初始化final欄位123
- 抽象類
- 一個
class
定義了方法,但沒有具體執行程式碼,這個方法就是抽象方法,抽象方法用abstract
修飾。因為抽象類本身被設計成只能用於被繼承,因此,抽象類可以強迫子類實現其定義的抽象方法,否則編譯會報錯。因此,抽象方法實際上相當於定義了“規範”。 - 抽象方法的類都是抽象類,抽象類不全是抽象方法。
-
面向抽象程式設計的本質就是:
-
上層程式碼只定義規範(例如:
abstract class Person
); -
不需要子類就可以實現業務邏輯(正常編譯);
-
具體的業務邏輯由不同的子類實現,呼叫者並不關心。
-
- 一個
- 介面
-
- 如果一個抽象類沒有欄位,且所有方法全部都是抽象方法,就可以把該抽象類改寫為介面:
interface
。 - 介面中屬性預設public static final 修飾 方法預設public abstract修飾
- 一個具體的
class
去實現一個interface
時,需要使用implements
關鍵字。 - 一個類可以實現多個
interface。
- 一個
interface
可以繼承自另一個interface
。interface
繼承自interface
使用extends
,它相當於擴充套件了介面的方法。 View Code
- 如果一個抽象類沒有欄位,且所有方法全部都是抽象方法,就可以把該抽象類改寫為介面:
-
- 包
-
- 在Java虛擬機器執行的時候,JVM只看完整類名,因此,只要包名不同,類就不同。
- 包沒有父子關係。java.util和java.util.zip是不同的包,兩者沒有任何繼承關係。
- 位於同一個包的類,可以訪問包作用域的欄位和方法。不用
public
、protected
、private
修飾的欄位和方法就是包作用域。 -
import
- 直接寫出完整類名 mr.jun.Arrays arrays =new mr.jun.Arrays();
- 用
import
語句,匯入Arrays,然後寫簡單類名。
1 // Person.java 2 package ming; 3 4 // 匯入完整類名: 5 import mr.jun.Arrays; 6 7 public class Person { 8 public void run() { 9 Arrays arrays = new Arrays(); 10 } 11 }
-
import static 包名
,它可以匯入一個類的靜態欄位和靜態方法。1 package main; 2 3 // 匯入System類的所有靜態欄位和靜態方法: 4 import static java.lang.System.*; 5 6 public class Main { 7 public static void main(String[] args) { 8 // 相當於呼叫System.out.println(…) 9 out.println("Hello, world!"); 10 } 11 }
-
如果是簡單類名,按下面的順序依次查詢:
-
查詢當前
package
是否存在這個class
; -
查詢
import
的包是否包含這個class
; -
查詢
java.lang
包是否包含這個class
。
-
- 因此,編寫class的時候,編譯器會自動幫我們做兩個import動作:
-
預設自動
import
當前package
的其他class
; -
預設自動
import java.lang.*
。 - 自動匯入的是java.lang包,但類似java.lang.reflect這些包仍需要手動匯入。
- 如果有兩個
class
名稱相同,例如,mr.jun.Arrays
和java.util.Arrays
,那麼只能import
其中一個,另一個必須寫完整類名。
-
-
內部類
-
-
- 普通類有個最大的不同,就是Inner Class的例項不能單獨存在,必須依附於一個Outer Class的例項。
1 public class Main { 2 public static void main(String[] args) { 3 Outer outer = new Outer("Nested"); // 例項化一個Outer 4 Outer.Inner inner = outer.new Inner(); // 例項化一個Inner 5 inner.hello(); 6 } 7 } 8 9 class Outer { 10 private String name; 11 12 Outer(String name) { 13 this.name = name; 14 } 15 16 class Inner { 17 void hello() { 18 System.out.println("Hello, " + Outer.this.name); 19 } 20 } 21 }
- Inner Class和普通Class相比,除了能引用Outer例項外,還有一個額外的“特權”,就是可以修改Outer Class的
private
欄位,因為Inner Class的作用域在Outer Class內部,所以能訪問Outer Class的private
欄位和方法。(Inner Class除了有一個this
指向它自己,還隱含地持有一個Outer Class例項,可以用Outer.this
訪問這個例項。) - 匿名內部類
- 不需要在Outer Class中明確地定義這個Class,而是在方法內部,通過匿名類(Anonymous Class)來定義。
1 public class Main { 2 public static void main(String[] args) { 3 Outer outer = new Outer("Nested"); 4 outer.asyncHello(); 5 } 6 } 7 8 class Outer { 9 private String name; 10 11 Outer(String name) { 12 this.name = name; 13 } 14 15 void asyncHello() { 16 Runnable r = new Runnable() { //重寫父類或者介面的方法 17 @Override 18 public void run() { 19 System.out.println("Hello, " + Outer.this.name); 20 } 21 }; 22 new Thread(r).start(); 23 } 24 }
- 不需要在Outer Class中明確地定義這個Class,而是在方法內部,通過匿名類(Anonymous Class)來定義。
- 靜態內部類
-
1 public class Main { 2 public static void main(String[] args) { 3 Outer.StaticNested sn = new Outer.StaticNested(); //外部類無需例項化 4 sn.hello(); 5 } 6 } 7 8 class Outer { 9 private static String NAME = "OUTER"; 10 11 private String name; 12 13 Outer(String name) { 14 this.name = name; 15 } 16 17 static class StaticNested { 18 void hello() { 19 System.out.println("Hello, " + Outer.NAME); 20 } 21 } 22 }
- 用
static
修飾的內部類和Inner Class有很大的不同,它不再依附於Outer
的例項,而是一個完全獨立的類,因此無法引用Outer.this
,但它可以訪問Outer
的private
靜態欄位和靜態方法。如果把StaticNested
移到Outer
之外,就失去了訪問private
的許可權。
-
- 普通類有個最大的不同,就是Inner Class的例項不能單獨存在,必須依附於一個Outer Class的例項。
-
-
classpath和jarclasspath和jar
-
-
- 圖1
- 圖2
-
- 模組