java的接口是經過interface來實現java
爲何要有接口?面試
java沒有多繼承 能夠用接口來實現多繼承的功能 由於類是兩個相同事物的共性抽取出來的,接口能夠 看作是兩個不一樣事物的某一個特性抽取出來. eg: 小東和牧羊犬都會吃飯,難道他們倆是同一類事物嗎? 確定不是的.那麼他們都會吃飯的這個特性就能夠抽取成一個接口來使用 接口說白了也便是 完成類所不合理的一些特徵而存在的 彌補類的短板
接口的特徵服務器
接口的方法不能有方法體
* * 1:接口的使用 * interface 來定義 * * 2: java中 接口和類是並列的兩個結構 * * 3 : 定義接口中的成員 * jdk7 以及之前 : 接口中只能定義全局常量和抽象方法 * > 全局常量: public static final :可是書寫是經常省略 public static fianl * > 抽象方法: public abstract * * jdk8: 除了定義全局常量和抽象方法以外,還能夠定義靜態方法, 默認方法 * * * 4 : 接口中不能定義構造器,也就是不能被實例化 * * 5: 在java開發中幾口經過讓類去實現(implements)的方式來使用, * 若是實現類 覆蓋了接口中的全部抽象方法,則此實現類就能夠實例化 * 若是實現類沒有重寫完全部的抽象方法,則此實現類仍是一個抽象類 * * * * 6: java類實現多個接口 -----> 彌補了java單繼承性的侷限性 * 格式 : class AA implements BB, CC, DD, EE * * * 7: 接口與接口之間能夠繼承,並且能夠多繼承 * * 8: 接口的具體使用: 體現了多態 * * 9: 接口實際上能夠看作是一種規範
面試題:網絡
排錯ide
interface A { int x = 0; } class B { int x = 1; } class C extends B implements A { public void pX() { System.out.println(x); } public static void main(String[] args) { new C().pX(); } }
pX() 方法的x沒有聲明形參,因此此處有問題
interface Playable { void play(); } interface Bounceable { void play(); } interface Rollable extends Playable, Bounceable { Ball ball = new Ball("PingPang"); } class Ball implements Rollable { private String name; public String getName() { return name; } public Ball(String name) { this.name = name; } public void play() { ball = new Ball("Football"); System.out.println(ball.getName()); } }
Rollable接口中沒有重寫 繼承來的接口中的方法,
Ball 中的ball屬性是不能重寫定義的 由於此變量是在Rollable 接口中定義的 ,
接口中的變量時常量是不能夠被改變的
練習題測試
定義一個接口用來實現兩個對象的比較。 interface CompareObject{
public int compareTo(Object o); //若返回值是 0 , 表明相等; 若爲正數,表明當前對象大;負數表明當前對象小
}
定義一個Circle類,聲明redius屬性,提供getter和setter方法 定義一個ComparableCircle類,繼承Circle類而且實現CompareObject接口。在 ComparableCircle類中給出接口中方法compareTo的實現體,用來比較兩個圓的半 徑大小。 定義一個測試類InterfaceTest,建立兩個ComparableCircle對象,調用compareTo 方法比較兩個類的半徑大小。 思考:參照上述作法定義矩形類Rectangle和ComparableRectangle類,在 ComparableRectangle類中給出compareTo方法的實現,比較兩個矩形的面積大小
import java.util.Date; public class XiTest { public static void main(String[] args) { ComparableCir c1 = new ComparableCir(3.4); ComparableCir c2 = new ComparableCir(3.6); int compareValue = c1.compareTo(c2); if(compareValue >0){ System.out.println("c1比c2大"); }else if (compareValue < 0){ System.out.println("c2對象大"); }else{ System.out.println("同樣大"); } } } interface CompareTest{ public int compareTo(Object o); } class Cir{ double redius; public Cir(double redius){ this.redius = redius; } public double getRedius() { return redius; } public void setRedius(double redius) { this.redius = redius; } } class ComparableCir extends Cir implements CompareTest{ public ComparableCir(double redius){ super(redius); } @Override public int compareTo(Object o){ if(this.getRedius() == 0){ return 0; } if(o instanceof ComparableCir){ ComparableCir comparableCir = (ComparableCir) o; if(this.getRedius() > comparableCir.getRedius()){ return 1; }else if(this.getRedius() < comparableCir.getRedius()){ return -1; }else{ return 0; } }else{ return 0; } } }
接口的代理模式:this
/** * 接口的應用: 代理模式 */ // 雖然是經過代理類對象去掉方法可是 實際把被代理類對象傳遞進去 包含了 被代理類對象 public class NetWorkTest { public static void main(String[] args) { ServerTest serverTest = new ServerTest(); ProxyServerTest proxyServerTest = new ProxyServerTest(serverTest); proxyServerTest.browse(); // 聯網實現的一些檢查工做 , 真實的服務器訪問網絡 } } interface NetWork{ public void browse(); } // 被代理類 class ServerTest implements NetWork{ @Override public void browse(){ System.out.println("真實的服務器訪問網絡"); } } // 代理類 class ProxyServerTest implements NetWork{ private NetWork work; public ProxyServerTest(NetWork work){ this.work = work; } public void check(){ System.out.println("聯網實現的一些檢查工做"); } public void browse(){ check(); work.browse(); } }
java8中接口的特性spa
java8中能夠書寫:
靜態方法帶方法體,
默認方法
* java8中接口除了定義全局常量和靜態方法中 * * > 接口中定義的靜態方法只能接口去調用 * > 若是子類(或者實現類)繼承的父類和實現的接口中有同名同參數的方法,那麼子類在沒有重寫此方法的狀況下調用的是父類中同名同參數的方法---->類優先原則
若是實現類實現了多個接口,而多個接口中定義了同名同參數的默認方法,那麼在實現類沒有重寫此方法的時候就會報錯,---->接口衝突
* 那麼咱們就必須在實現類中重寫此方法
eg:代理
public class J8 { public static void main(String[] args) { CompareA compareA = new CompareA(); // compareA.method1() 報錯 java8中接口中的靜態方法只能接口本身調用 其餘的實現類不能夠去調用 //經過實現類的對象能夠調用默認方法, 若是重寫後接口中的方法 那麼調用的是實現類內的重寫方法 Java8.method1(); compareA.method2(); compareA.method3(); // 繼承的父類也有 實現的接口中也有此方法那麼調用的是父類中的方法 TestB testB = new TestB(); // testB.method1(); 靜態方法只能夠本身調用不能夠實現類去調用 } } /** * java8中接口除了定義全局常量和靜態方法中 * * > 接口中定義的靜態方法只能接口去調用 * > 若是子類(或者實現類)繼承的父類和實現的接口中有同名同參數的方法,那麼子類在沒有重寫此方法的狀況下調用的是父類中同名同參數的方法---->類優先原則 */ interface Java8{ // 靜態方法 public static void method1(){ System.out.println("java8的新特性接口中的方法是能夠有方法體的"); } // 默認方法 public default void method2(){ System.out.println("java8接口新特性"); } //默認方法 default void method3(){ System.out.println("java8接口新特性"); } } class CompareA extends SuperClass implements Java8 { } class SuperClass { public void method3(){ System.out.println("我是父類中的method3"); } }
在調用是接口中的靜態方法只能接口自己本身去調用,以下 實現類只能夠調用默認方法code
若是實現類實現了多個接口,而多個接口中定義了同名同參數的默認方法,那麼在實現類沒有重寫此方法的時候就會報錯,---->接口衝突
* 那麼咱們就必須在實現類中重寫此方法
由於上面定義了 TestB接口定義了method3()方法 而實現類實現了TestB和TestA接口 又沒有重寫method3方法就會報錯
在實現類中調用接口中的被重寫的方法
接口.super.方法()
eg:
class TestB extends TestD implements TestA, TestC{ public void method3(){ //重寫的時候權限必須大於上一級 System.out.println("TestB 重寫方法");
TestA.super.method3(); //調用接口中的默認方法 }
總結:
若一個接口中定義了一個默認方法,而另一個接口中也定義了一個同名同 參數的方法(無論此方法是不是默認方法),在實現類同時實現了這兩個接 口時,會出現:接口衝突。
解決辦法:實現類必須覆蓋接口中同名同參數的方法,來解決衝突。
若一個接口中定義了一個默認方法,而父類中也定義了一個同名同參數的非 抽象方法,則不會出現衝突問題。由於此時遵照:類優先原則。接口中具備 相同名稱和參數的默認方法會被忽略。
解決接口衝突
interface Filial{ //孝順的 default void help(){ System.out.println("老媽我來救你"); } } interface Spoony{ //癡情的 default void help(){ System.out.println("媳婦別怕 我來了"); } } class father{ public void help(){ System.out.println("先救你媽媽"); } } class man extends father implements Filial, Spoony { @Override public void help(){ System.out.println("我該怎麼辦"); super.help(); Filial.super.help(); Spoony.super.help(); } }