Java介面,抽象類,內部類
介面的概念 在Java中介面是一個全部由抽象方法組成的集合,介面需要用interface定義,裡面只能有抽象的方法和常量。
介面體現的是事物擴充套件的功能,在Java中,類定義了一個實體,包括實體的屬性,實體的行為。而介面定義了一個實體可能發生的動作,只有一個宣告,沒有具體的行為。
當一個方法在很多類中有不同的體現是時候這個時候就可以將這個方法抽象出來做成一個介面。
接口裡面只能有不可修改的全域性常量,只能有抽象的方法,介面沒有構造方法。
定義一個介面:
interface Inter { public static final int i=10; //全域性常量字首public static final public abstract void eat(); //抽象的方法 } 介面的特點 定義介面時使用interface定義,區別於抽象類,不需要加class。 介面不能被例項化,不能直接建立物件,因為接口裡面只有抽象的方法,沒有具體的功能。 介面可以繼承介面,介面要實現具體的功能必須有實現他的子類,實現介面的子類中必須重寫介面全部的抽象方法。 介面和介面之間可以多繼承。 介面的子類可以是抽象類,但是沒有實際的意義。 一個子類可以實現多個介面,通過implements關鍵字去實現。 介面需要通過多型才能建立物件。 如下:
interface A { public static final int i = 10; //介面只能定義全域性常量需要加public static final如果不加系統預設給出,推薦加。 public abstract void eat(); } interface B extends A { // 介面可以繼承介面 public abstract void sleep(); } interface C { public abstract void look(); } abstract class D { //定義一個抽象類 public void run() { System.out.println("跑起來"); } public abstract void learn(); } public class Text extends D implements B, C { //一個子類可以繼承一個抽象類同時實現多個介面 //子類如果不是抽象類就必須實現所有的抽象方法 public void eat() { //實現介面A中的抽象方法 System.out.println("吃東西"); } public void look() { //實現介面C中的抽象方法 System.out.println("看風景"); } public void sleep() { //實現介面B中的抽象方法 System.out.println("睡懶覺"); } @Override public void learn() { //重寫抽象類D中的抽象方法 System.out.println("學Java"); } public static void main(String[] args) { B b=new Text(); //多型,介面的引用指向子類的物件 b.eat(); b.sleep(); System.out.println(B.i); //靜態常量通過介面名去訪問,不推薦用物件去呼叫 C c=new Text(); c.look(); D d=new Text(); d.learn(); } } /** * 輸出為: 吃東西 睡懶覺 10 看風景 學Java */ 介面作為形式引數 如果一個方法的形式引數為介面如下:
interface Inter{ public abstract void learn(); } class B{ public void student(Inter a) { //形式引數為介面 a.learn(); } } public class Text{ public static void main(String[] args) { } } 此時我們想呼叫B類中的student方法怎麼做?我們有兩種方法
因為介面不能建立物件所以我們需要給出他的子實現類建立子實現類的物件去呼叫其中的方法。 可以通過內部類的方式,不需要提供子實現類。 建立子實現類的方式:
interface Inter{ public abstract void learn(); } class B{ public void student(Inter a) { a.learn(); } } class InterImpl implements Inter{ //建立Inter的子實現類 public void learn() { System.out.println("學習"); } } public class Text{ public static void main(String[] args) { Inter i=new InterImpl(); //通過多型建立介面的物件 B b=new B(); //建立B類的物件 b.student(i); //傳遞物件到Student方法內去呼叫learn方法 } } /** * 輸出為: 學習 */ 內部類 如果一個類被定義到了另一個類的裡面或者方法裡面這個類就叫做內部類,內部類包括成員內部類、區域性內部類、匿名內部類和靜態內部類四種。
成員內部類 成員內部類在外部類的成員位置,成員內部類可以無條件訪問外部類的所有內容包括static靜態的和private私有的。
public class Outside { int a = 10; private int b = 20; class inside { // inside就是成員內部類 public void show() { // 內部類的方法 System.out.println(a); System.out.println(b); } } } 注意:
當內部類定義了和外部類相同的成員變數和方法時,就近原則優先訪問內部類的變數和方法,如果需要使用外部類的成員和方法需要使用this關鍵字
外部類.this.成員變數 外部類.this.成員方法 外部類不能直接訪問內部類的變數和方法,需要通過建立內部類的物件來訪問:
public class Outside { int a = 10; private int b = 20; class Inside { // inside就是成員內部類 public void show() { // 內部類的方法 System.out.println(a); System.out.println(b); } } public void show2() { Inside i=new Inside(); i.show(); } } 成員內部類是依附於外部類而存在的,也就是說如果想要建立一個內部類的物件前提需要有一個外部類的物件,其他類中需要訪問成員內部類的方法或者變數需要通過:
外部類名.內部類名 物件名 = 外部類物件.內部類物件
來建立成員內部類的物件:
class Outside { int a = 10; private int b = 20; class Inside { // inside就是成員內部類 public void show() { // 內部類的方法 System.out.println(a); System.out.println(b); } } } public class Text2 { public static void main(String[] args) { Outside.Inside i=new Outside().new Inside(); //建立內部類的物件的格式 i.show(); } } /** 輸出為: 10 20 */ 如果成員內部類的訪問許可權是private,那麼這個內部類只能在外部類中訪問,其他類中不能通過上面的方法來建立私有內部類的物件。
class Outside { int a = 10; private class Inside { // 私有的成員內部類,只在外部類中可以使用。 public void show() { // 內部類的方法 System.out.println(a); } } } public class Text2 { public static void main(String[] args) { // Outside.Inside i=new Outside().new Inside(); // i.show(); // 出錯,無法訪問私有的內部類 } }
區域性內部類 區域性內部類是定義在一個方法裡的類,區域性內部類的訪問僅限於方法內或者該作用域內。
區域性內部類訪問區域性變數時候需要給區域性變數新增final
因為區域性變數是在方法中定義的變數,噹噹前方法執行完畢後區域性變數會被Java回收,此時如果區域性內部類的物件對區域性變數還存在引用的話就會出現物件指向了一個不存在的變數,因此區域性內部類只能訪問被final修飾的區域性變數。
class Outside { public void show() { final int a=1; class Inside{ public void show2() { System.out.println(a); //區域性內部類訪問區域性變數時候需要給區域性變數新增final //在jdk7以後如果不加會自動給出,但是會警告 } } } } 區域性內部類是不能有public,private,static這樣的修飾詞的。 靜態內部類 格式上就是成員內部類前面加了static,他的特點是隻能訪問外部類中被static修飾的成員。
class Outside { static int a = 10; static class Inside { // 靜態內部類 public void show() { System.out.println(a); // 只能訪問外部的靜態成員 } } } public class Text2 { public static void main(String[] args) { Outside.Inside i = new Outside.Inside(); // 靜態內部類建立物件的方式 i.show(); } } /** * 輸出為: 10 */ 匿名內部類 匿名內部類在實際開發中用的最多,匿名內部類的前提條件是存在一個類或者介面,這個類可以為抽象類。
匿名內部類的格式為:
new 類名或介面名{ 重寫的方法; } 匿名內部類本質上是繼承了該類或實現了介面中的方法。
比如我們上面提到的形式引數是介面的問題就可以通過匿名內部類的方式來重寫介面中抽象的方法而不需要通過建立子實現類。
interface Inter { public abstract void learn(); } class B { public void student(Inter a) { a.learn(); } } public class Text { public static void main(String[] args) { Inter a=new Inter() { //匿名內部類 public void learn() { //直接在匿名內部類中重寫介面中抽象的方法不需要建立介面的子實現類 System.out.println("學習"); } }; a.learn(); //呼叫learn方法 } } /** * 輸出為: 學習 */ 例題分析: 補齊程式碼 interface Inter { void show(); } class Outer { //補齊程式碼 } class OuterDemo { public static void main(String[] args) { Outer.method().show(); } } 要求在控制檯輸出”HelloWorld” 這道題中先看主方法,主方法中 Outer.method() 這句話可以成立說明method方法是靜態的,只有靜態的方法才能直接被類名呼叫。繼續看
Outer.method().show(); 這句話可以成立說明method方法返回了個Inter的匿名物件,只有物件才能通過 .方法名來呼叫方法。
因為這裡沒有Inter介面的子實現類,所以我們要返回一個實現Inter介面的匿名內部類,在匿名內部類中去實現介面的抽象方法。
所以補齊之後的程式碼為:
interface Inter { void show(); } class Outer { // 補齊程式碼 public static Inter method() { return new Inter() { //返回的是實現介面的匿名內部類 public void show() { /匿名內部類中實現show方法 System.out.println("Hello word"); } }; } } class OuterDemo { public static void main(String[] args) { Outer.method().show(); } } /** Hello word * */ 形式引數為抽象類中的問題 abstract class A{ public void sleep() { System.out.println("睡覺"); } } class B{ public void cat(A a) { a.sleep(); } } public class Text { public static void main(String[] args) { } } 如果我們需要呼叫B類中的cat方法,因為A類是個抽象類,不能直接建立A類的物件,我們需要先給A類建立一個子類,然後用多型的方式建立A類的物件傳入cat方法的形式引數部分。
abstract class A{ public void sleep() { System.out.println("睡覺"); } } class B{ public void cat(A a) { a.sleep(); } } class C extends A{ } public class Text { public static void main(String[] args) { A a=new C(); a.sleep(); } } /** * 輸出為: 睡覺 */ 也可以用匿名內部類的方式,好處是不需要額外給出A類的子類
abstract class A{ public void sleep() { System.out.println("睡覺"); } } class B{ public void cat(A a) { a.sleep(); } } public class Text { public static void main(String[] args) { A a=new A() { //匿名內部類,因為Sleep方法不是抽象方法,所以不需要重寫。 }; a.sleep(); } } /** * 輸出為: 睡覺 */ 什麼時候使用介面和抽象類 抽象類是對事物本身的抽象,比如教師類,學生類就可以抽象為人類。
介面是對行為的抽象,比如教師要學英語,學生也要學英語,學英語就可以抽象為介面。
抽象類表示的是這個物件是什麼,介面是表示這個物件能幹什麼。
所以抽象類只能有一個子類,就比如教師和學生只能是人類不能是非人類。
而教師或者學生可以實現多個介面。他們既可以學英語也可以學數學。 --------------------- 原文:https://blog.csdn.net/liuchonghua/article/details/80013079