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

歡迎訪問 生活随笔!

生活随笔

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

java

java构造函数重载继承_Java基础-继承 - 写代码换盆的个人空间 - OSCHINA - 中文开源技术交流社区...

發布時間:2023/12/2 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java构造函数重载继承_Java基础-继承 - 写代码换盆的个人空间 - OSCHINA - 中文开源技术交流社区... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

訪問權限

Java 中有三個訪問權限修飾符:private、protected 以及 public,如果不加訪問修飾符,表示包級可見。

可以對類或類中的成員(字段和方法)加上訪問修飾符。

類可見表示其它類可以用這個類創建實例對象。

成員可見表示其它類可以用這個類的實例對象訪問到該成員;

protected 用于修飾成員,表示在繼承體系中成員對于子類可見,但是這個訪問修飾符對于類沒有意義。

設計良好的模塊會隱藏所有的實現細節,把它的 API 與它的實現清晰地隔離開來。模塊之間只通過它們的 API 進行通信,一個模塊不需要知道其他模塊的內部工作情況,這個概念被稱為信息隱藏或封裝。因此訪問權限應當盡可能地使每個類或者成員不被外界訪問。

如果子類的方法重寫了父類的方法,那么子類中該方法的訪問級別不允許低于父類的訪問級別。這是為了確保可以使用父類實例的地方都可以使用子類實例去代替,也就是確保滿足里氏替換原則。

字段決不能是公有的,因為這么做的話就失去了對這個字段修改行為的控制,客戶端可以對其隨意修改。例如下面的例子中,AccessExample 擁有 id 公有字段,如果在某個時刻,我們想要使用 int 存儲 id 字段,那么就需要修改所有的客戶端代碼。

public class AccessExample {

public String id;

}

可以使用公有的 getter 和 setter 方法來替換公有字段,這樣的話就可以控制對字段的修改行為。

public class AccessExample {

private int id;

public String getId() {

return id + "";

}

public void setId(String id) {

this.id = Integer.valueOf(id);

}

}

但是也有例外,如果是包級私有的類或者私有的嵌套類,那么直接暴露成員不會有特別大的影響。

public class AccessWithInnerClassExample {

private class InnerClass {

int x;

}

private InnerClass innerClass;

public AccessWithInnerClassExample() {

innerClass = new InnerClass();

}

public int getValue() {

return innerClass.x; // 直接訪問

}

}

抽象類與接口

1. 抽象類

抽象類和抽象方法都使用 abstract 關鍵字進行聲明。如果一個類中包含抽象方法,那么這個類必須聲明為抽象類。

抽象類和普通類最大的區別是,抽象類不能被實例化,只能被繼承。

public abstract class AbstractClassExample {

protected int x;

private int y;

public abstract void func1();

public void func2() {

System.out.println("func2");

}

}

public class AbstractExtendClassExample extends AbstractClassExample {

@Override

public void func1() {

System.out.println("func1");

}

}

// AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated

AbstractClassExample ac2 = new AbstractExtendClassExample();

ac2.func1();

2. 接口

接口是抽象類的延伸,在 Java 8 之前,它可以看成是一個完全抽象的類,也就是說它不能有任何的方法實現。

從 Java 8 開始,接口也可以擁有默認的方法實現,這是因為不支持默認方法的接口的維護成本太高了。在 Java 8 之前,如果一個接口想要添加新的方法,那么要修改所有實現了該接口的類,讓它們都實現新增的方法。

接口的成員(字段 + 方法)默認都是 public 的,并且不允許定義為 private 或者 protected。從 Java 9 開始,允許將方法定義為 private,這樣就能定義某些復用的代碼又不會把方法暴露出去。

接口的字段默認都是 static 和 final 的。

public interface InterfaceExample {

void func1();

default void func2(){

System.out.println("func2");

}

int x = 123;

// int y; // Variable 'y' might not have been initialized

public int z = 0; // Modifier 'public' is redundant for interface fields

// private int k = 0; // Modifier 'private' not allowed here

// protected int l = 0; // Modifier 'protected' not allowed here

// private void fun3(); // Modifier 'private' not allowed here

}

public class InterfaceImplementExample implements InterfaceExample {

@Override

public void func1() {

System.out.println("func1");

}

}

// InterfaceExample ie1 = new InterfaceExample(); // 'InterfaceExample' is abstract; cannot be instantiated

InterfaceExample ie2 = new InterfaceImplementExample();

ie2.func1();

System.out.println(InterfaceExample.x);

3. 比較

從設計層面上看,抽象類提供了一種 IS-A 關系,需要滿足里式替換原則,即子類對象必須能夠替換掉所有父類對象。而接口更像是一種 LIKE-A 關系,它只是提供一種方法實現契約,并不要求接口和實現接口的類具有 IS-A 關系。

從使用上來看,一個類可以實現多個接口,但是不能繼承多個抽象類。

接口的字段只能是 static 和 final 類型的,而抽象類的字段沒有這種限制。

接口的成員只能是 public 的,而抽象類的成員可以有多種訪問權限。

4. 使用選擇

使用接口:

需要讓不相關的類都實現一個方法,例如不相關的類都可以實現 Comparable 接口中的 compareTo() 方法;

需要使用多重繼承。

使用抽象類:

需要在幾個相關的類中共享代碼。

需要能控制繼承來的成員的訪問權限,而不是都為 public。

需要繼承非靜態和非常量字段。

在很多情況下,接口優先于抽象類。因為接口沒有抽象類嚴格的類層次結構要求,可以靈活地為一個類添加行為。并且從 Java 8 開始,接口也可以有默認的方法實現,使得修改接口的成本也變的很低。

super

訪問父類的構造函數:可以使用 super() 函數訪問父類的構造函數,從而委托父類完成一些初始化的工作。應該注意到,子類一定會調用父類的構造函數來完成初始化工作,一般是調用父類的默認構造函數,如果子類需要調用父類其它構造函數,那么就可以使用 super() 函數。

訪問父類的成員:如果子類重寫了父類的某個方法,可以通過使用 super 關鍵字來引用父類的方法實現。

public class SuperExample {

protected int x;

protected int y;

public SuperExample(int x, int y) {

this.x = x;

this.y = y;

}

public void func() {

System.out.println("SuperExample.func()");

}

}

public class SuperExtendExample extends SuperExample {

private int z;

public SuperExtendExample(int x, int y, int z) {

super(x, y);

this.z = z;

}

@Override

public void func() {

super.func();

System.out.println("SuperExtendExample.func()");

}

}

SuperExample e = new SuperExtendExample(1, 2, 3);

e.func();

SuperExample.func()

SuperExtendExample.func()

重寫與重載

1. 重寫(Override)

存在于繼承體系中,指子類實現了一個與父類在方法聲明上完全相同的一個方法。

為了滿足里式替換原則,重寫有以下三個限制:

子類方法的訪問權限必須大于等于父類方法;

子類方法的返回類型必須是父類方法返回類型或為其子類型。

子類方法拋出的異常類型必須是父類拋出異常類型或為其子類型。

使用 @Override 注解,可以讓編譯器幫忙檢查是否滿足上面的三個限制條件。

下面的示例中,SubClass 為 SuperClass 的子類,SubClass 重寫了 SuperClass 的 func() 方法。其中:

子類方法訪問權限為 public,大于父類的 protected。

子類的返回類型為 ArrayList,是父類返回類型 List 的子類。

子類拋出的異常類型為 Exception,是父類拋出異常 Throwable 的子類。

子類重寫方法使用 @Override 注解,從而讓編譯器自動檢查是否滿足限制條件。

class SuperClass {

protected List func() throws Throwable {

return new ArrayList<>();

}

}

class SubClass extends SuperClass {

@Override

public ArrayList func() throws Exception {

return new ArrayList<>();

}

}

在調用一個方法時,先從本類中查找看是否有對應的方法,如果沒有再到父類中查看,看是否從父類繼承來。否則就要對參數進行轉型,轉成父類之后看是否有對應的方法。總的來說,方法調用的優先級為:

this.func(this)

super.func(this)

this.func(super)

super.func(super)

/*

A

|

B

|

C

|

D

*/

class A {

public void show(A obj) {

System.out.println("A.show(A)");

}

public void show(C obj) {

System.out.println("A.show(C)");

}

}

class B extends A {

@Override

public void show(A obj) {

System.out.println("B.show(A)");

}

}

class C extends B {

}

class D extends C {

}

public static void main(String[] args) {

A a = new A();

B b = new B();

C c = new C();

D d = new D();

// 在 A 中存在 show(A obj),直接調用

a.show(a); // A.show(A)

// 在 A 中不存在 show(B obj),將 B 轉型成其父類 A

a.show(b); // A.show(A)

// 在 B 中存在從 A 繼承來的 show(C obj),直接調用

b.show(c); // A.show(C)

// 在 B 中不存在 show(D obj),但是存在從 A 繼承來的 show(C obj),將 D 轉型成其父類 C

b.show(d); // A.show(C)

// 引用的還是 B 對象,所以 ba 和 b 的調用結果一樣

A ba = new B();

ba.show(c); // A.show(C)

ba.show(d); // A.show(C)

}

2. 重載(Overload)

存在于同一個類中,指一個方法與已經存在的方法名稱上相同,但是參數類型、個數、順序至少有一個不同。

應該注意的是,返回值不同,其它都相同不算是重載。

class OverloadingExample {

public void show(int x) {

System.out.println(x);

}

public void show(int x, String y) {

System.out.println(x + " " + y);

}

}

public static void main(String[] args) {

OverloadingExample example = new OverloadingExample();

example.show(1);

example.show(1, "2");

}

總結

以上是生活随笔為你收集整理的java构造函数重载继承_Java基础-继承 - 写代码换盆的个人空间 - OSCHINA - 中文开源技术交流社区...的全部內容,希望文章能夠幫你解決所遇到的問題。

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