Heim > Java > javaLernprogramm > Hauptteil

Welche Rolle spielen Schnittstellen in Java?

WBOY
Freigeben: 2023-04-26 14:28:07
nach vorne
2400 Leute haben es durchsucht

1. Was ist eine abstrakte Klasse? Bevor wir die Schnittstelle erklären, ist die abstrakte Klasse ein Konzept, das nicht umgangen werden kann. Die Schnittstelle kann als eine Klasse betrachtet werden, die abstrakter ist als die abstrakte Klasse.

Was ist eine abstrakte Klasse?

„Eine Klasse, die eine oder mehrere abstrakte Methoden enthält, ist eine abstrakte Klasse, und eine abstrakte Methode ist eine Methode ohne Methodenkörper.“

Sowohl abstrakte Methoden als auch abstrakte Klassen müssen als abstrakt deklariert werden. Zum Beispiel:

<code>// 抽象类<br>public abstract class Person {<br>    // 抽象方法<br> public abstract String getDescription();<br>}</code>
Nach dem Login kopieren
Denken Sie daran! abstract。例如:

<code>public abstract class Person{<br>    private String name;<br>    public Person(String name){<br>     this.name = name ;<br>    }<br>    public abstract String getDescription();<br>    public String getName(){<br>     return name;<br>    }<br>}</code>
Nach dem Login kopieren

切记!「除了抽象方法之外,抽象类还可以包含具体数据和具体方法」。例如, 抽象类 Person 还保存着姓名和一个返回姓名的具体方法:

<code>new Person("Jack"); // Error</code>
Nach dem Login kopieren
❝  

许多程序员都会「错误」的认为,在抽象类中不能包含具体方法。其实这也是接口和抽象类的不同之处,接口中是不能包含具体方法的。

❞  

「抽象类不能被实例化」。也就是说,如果将一个类声明为 abstract, 就不能创建这个类的对象。

<code>Person p = new Student("Jack"); // Right</code>
Nach dem Login kopieren

可以定义一个抽象类的对象变量, 但是它只能引用非抽象子类的对象。假设 Student 类是 Person 的非抽象子类:

<code>public class Student extends Person { <br>    private String major; <br>    public Student(String name, String major) { <br>        super(name); <br>        this.major = major; <br>    } <br>    @Override<br>    public String getDescription(){ // 实现父类抽象方法<br>     return "a student majoring in " + major; <br>    } <br>} </code>
Nach dem Login kopieren

所谓非抽象子类就是说,如果创建一个继承抽象类的子类并为之创建对象,那么就「必须为父类的所有抽象方法提供方法定义」。如果不这么做(可以选择不做),子类仍然是一个抽象类,编译器会强制我们为新类加上 abstract 关键字。

下面定义扩展抽象类 Person 的具体子类 Student

<code>Person p = new Student("Jack","Computer Science");<br>p.getDescription();<br></code>
Nach dem Login kopieren

在 Student 类中实现了父类中的抽象方法 getDescription 。因此,「在 Student类中的全部方法都是非抽象的, 这个类不再是抽象类」

???? 调用如下:

<code>public interface Concept {<br>    void idea1();<br>    void idea2();<br>}</code> 
Nach dem Login kopieren
 

由于不能构造抽象类 Person的对象, 所以变量 p 永远不会引用 Person 对象, 而是引用诸如 Student这样的具体子类对象, 而这些对象中都重写了 getDescription方法。 

2. 什么是接口

接口的本质其实也是一个类,而且是一个比抽象类还要抽象的类。怎么说呢?抽象类是能够包含具体方法的,而接口杜绝了这个可能性,「在 Java 8 之前,接口非常纯粹,只能包含抽象方法,也就是没有方法体的方法」。而 Java 8 中接口出现了些许的变化,开始允许接口包含默认方法和静态方法,这个下文会讲解。

Java 使用关键字 interface 而不是 class 来创建接口。和类一样,通常我们会在关键字 interface 前加上 public 关键字,否则接口只有包访问权限,只能在接口相同的包下才能使用它。

<code>class Implementation implements Concept {<br>    @Override<br>    public void idea1() {<br>        System.out.println("idea1");<br>    }<br>    <br>    @Override<br>    public void idea2() {<br>        System.out.println("idea2");<br>    }<br>}<br></code>
Nach dem Login kopieren

同样的,接口中既然存在抽象方法,那么他就需要被扩展(继承)。使用 implements 关键字使一个类扩展某个特定接口(或一组接口),通俗来说:接口只是外形,现在这个扩展子类要说明它是如何工作的。

<code>public interface Concept {<br> void idea1(); // public void idea1();<br>    // 静态属性<br> double item = 95; // a public static final constant<br>}</code> 
Nach dem Login kopieren
 

这里需要注意的是,你可以选择显式地声明接口中的方法为 public,但是「即使你不这么做,它们也是 public 的」。所以当实现一个接口时,来自接口中的方法必须被定义为 public。否则,它们只有包访问权限,这样在被继承时,它们的可访问权限就被降低了,这是 Java 编译器所不允许的。

另外,接口中是允许出现常量的,与接口中的方法都自动地被设置为 public—样,「接口中的域将被自动被设置为 public static final 类型」,例如:

<code>x = new Concept(. . .); // ERROR</code> 
Nach dem Login kopieren
❝  

可以将接口方法标记为 public,将域标记为 public static final。有些程序员出于习惯或提高清晰度的考虑, 愿意这样做。但 Java 语言规范却「建议不要书写这些多余的关键字」

❞  

3. 接口的特性

接口和类其中不同的一点就是,我们「无法像类一样使用 new"Abstrakte Klassen können neben abstrakten Methoden auch konkrete Daten und konkrete Methoden enthalten". Beispielsweise speichert die abstrakte Klasse Person auch den Namen und eine konkrete Methode, die den Namen zurückgibt:

<code>Concept x; // OK</code> 
Nach dem Login kopieren
Nach dem Login kopieren

Viele Programmierer werden

„irrtümlicherweise“

glauben, dass Konkret nicht in eine einbezogen werden kann abstrakte Klassenmethode. Tatsächlich ist dies auch der Unterschied zwischen Schnittstellen und abstrakten Klassen. Schnittstellen können keine spezifischen Methoden enthalten.

🎜🎜"Abstrakte Klassen können nicht instanziiert werden"🎜. Mit anderen Worten: Wenn eine Klasse als abstract deklariert ist, können keine Objekte dieser Klasse erstellt werden. 🎜
<code>x = new Implementation(. . .); // OK provided Implementation implements Concept</code> 
Nach dem Login kopieren
Nach dem Login kopieren
🎜 kann eine Objektvariable einer abstrakten Klasse definieren, aber nur auf Objekte nicht abstrakter Unterklassen verweisen. Nehmen Sie an, dass die Klasse Student eine nicht-abstrakte Unterklasse von Person ist: 🎜
<code>if(x instanceof Concept){<br> ...<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren
🎜Die sogenannte nicht-abstrakte Unterklasse bedeutet, dass Sie eine Unterklasse erstellen, die die Zusammenfassung erbt Klasse und erstellt ein Objekt dafür, dann 🎜 „Methodendefinitionen müssen für alle abstrakten Methoden der übergeordneten Klasse bereitgestellt werden“ 🎜. Wenn Sie dies nicht tun (Sie können dies auch nicht tun), bleibt die Unterklasse weiterhin eine abstrakte Klasse und der Compiler zwingt uns, das Schlüsselwort abstract zur neuen Klasse hinzuzufügen. 🎜🎜Im Folgenden wird die spezifische Unterklasse Student der erweiterten abstrakten Klasse Person definiert: 🎜
<code>public interface Concept1 {<br>    void idea1();<br>    void idea2();<br>}<br><br>-------------------------------------------<br>    <br>public interface Concept2 extends Concept1{<br> double idea3();<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren
🎜implementiert die abstrakte Methode in der übergeordneten Klasse im Student Klasse getDescription. Daher 🎜 „Alle Methoden in der Klasse Student sind nicht abstrakt, und diese Klasse ist keine abstrakte Klasse mehr“ 🎜. 🎜🎜???? Der Aufruf lautet wie folgt: 🎜
<code>class Implementation implements Concept1, Concept2 // OK</code> 
Nach dem Login kopieren
Nach dem Login kopieren
🎜Da das Objekt der abstrakten Klasse Person nicht konstruiert werden kann, wird die Variable p niemals auf Person-Objekt, bezieht sich jedoch auf bestimmte Unterklassenobjekte wie Student, und die Methode getDescription wird in diesen Objekten überschrieben. 🎜

2. Was ist eine Schnittstelle? 🎜🎜Die Essenz einer Schnittstelle ist eigentlich eine Klasse, und es ist eine Klasse, die abstrakter ist als eine abstrakte Klasse. Wie sagt man es? Abstrakte Klassen können bestimmte Methoden enthalten, aber Schnittstellen schließen diese Möglichkeit aus 🎜 „Vor Java 8 waren Schnittstellen sehr rein und konnten nur abstrakte Methoden enthalten, also Methoden ohne Methodenkörper 🎜 In Java 8 gab es einige Änderungen an der Schnittstelle, und die Schnittstelle darf nun Standardmethoden und statische Methoden enthalten, was im Folgenden erläutert wird. 🎜🎜Java verwendet das Schlüsselwort interface anstelle von class, um Schnittstellen zu erstellen. Wie bei Klassen fügen wir normalerweise das Schlüsselwort public vor dem Schlüsselwort interface hinzu. Andernfalls verfügt die Schnittstelle nur über Paketzugriffsrechte und kann nur unter dem Paket mit derselben Schnittstelle verwendet werden. . 🎜
<code>public interface Concept {<br>    // 静态方法<br> public static void get(String name){<br>     System.out.println("hello " + name);<br>    }<br>    // 默认方法<br>    default void idea1(){<br>        System.out.println("this is idea1");<br>    };<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren
🎜Da es in der Schnittstelle eine abstrakte Methode gibt, muss diese ebenfalls erweitert (vererbt) werden. Verwenden Sie das Schlüsselwort implements, um eine bestimmte Schnittstelle (oder eine Gruppe von Schnittstellen) zu erweitern: Die Schnittstelle ist nur das Erscheinungsbild. Nun muss diese erweiterte Unterklasse erklärt werden. 🎜
<code>interface A {<br> default void idea(){<br>  System.out.println("this is A");<br> }<br>}<br><br>interface B {<br> default void idea(){<br>  System.out.println("this is B");<br> }<br>}<br><br>// 需要在 D 类中覆盖 idea 方法<br>class D implements A, B{<br>    public void getName(){<br>     System.out.println("this is D");<br>    }<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren
🎜Hier ist zu beachten, dass Sie die Methoden in der Schnittstelle explizit als public deklarieren können, aber 🎜„Selbst wenn Sie dies nicht tun, sind sie immer noch public<.> "🎜. Bei der Implementierung einer Schnittstelle müssen daher Methoden der Schnittstelle als <code>public definiert werden. Andernfalls haben sie nur Zugriff auf das Paket. Wenn sie vererbt werden, ist ihre Zugänglichkeit eingeschränkt, was der Java-Compiler nicht zulässt. 🎜🎜Darüber hinaus sind Konstanten in der Schnittstelle zulässig. Genauso wie die Methoden in der Schnittstelle automatisch auf public gesetzt werden, 🎜„Die Felder in der Schnittstelle werden automatisch auf public static final gesetzt Typ"🎜, zum Beispiel: 🎜
<code>interface B {<br> void idea();<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren
❝ 🎜Sie können die Schnittstellenmethode als public und das Feld als public static final markieren. Einige Programmierer sind bereit, dies aus Gewohnheit oder zur Verbesserung der Übersichtlichkeit zu tun, aber die Java-Sprachspezifikation „empfiehlt, diese redundanten Schlüsselwörter nicht zu schreiben“. 🎜❞

3. Eigenschaften von Schnittstellen 🎜🎜Der Unterschied zwischen Schnittstellen und Klassen besteht darin, dass wir 🎜 den new-Operator nicht wie eine Klasse verwenden können eine Schnittstelle“🎜:🎜rrreee🎜Der Grund ist auch sehr einfach. Die Schnittstelle hat nicht einmal eine bestimmte Konstruktionsmethode, daher darf sie nicht instanziiert werden. 🎜🎜Obwohl Schnittstellenobjekte nicht erstellt werden können, ist es natürlich dennoch möglich, Schnittstellenvariablen zu deklarieren: 🎜
<code>Concept x; // OK</code> 
Nach dem Login kopieren
Nach dem Login kopieren

接口变量必须引用实现了接口的类对象:

<code>x = new Implementation(. . .); // OK provided Implementation implements Concept</code> 
Nach dem Login kopieren
Nach dem Login kopieren

接下来, 如同使用 instanceof 检查一个对象是否属于某个特定类一样, 也可以使用 instanceof检查一个对象是否实现了某个特定的接口:

<code>if(x instanceof Concept){<br> ...<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren

另外,与可以建立类的继承关系一样,「接口也可以被继承」

<code>public interface Concept1 {<br>    void idea1();<br>    void idea2();<br>}<br><br>-------------------------------------------<br>    <br>public interface Concept2 extends Concept1{<br> double idea3();<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren

当然,读到这里大家可能依然无法理解,既然有了抽象类,为什么 Java 程序设计语言还要不辞辛苦地引入接口这个概念?

很重磅!因为「一个类可以实现多个接口,但是一个类只能继承一个父类」。正是接口的出现打破了 Java 这种单继承的局限,为定义类的行为提供了极大的灵活性。

<code>class Implementation implements Concept1, Concept2 // OK</code> 
Nach dem Login kopieren
Nach dem Login kopieren

有一条实际经验:在合理的范围内尽可能地抽象。显然,接口比抽象类还要抽象。因此,一般更倾向使用接口而不是抽象类。

4. Java 8 接口新特性

上文提过一嘴,「在 Java 8 中,允许在接口中增加静态方法和默认方法」。理论上讲,没有任何理由认为这是不合法的,只是这有违于将接口作为抽象规范的初衷。举个例子:

<code>public interface Concept {<br>    // 静态方法<br> public static void get(String name){<br>     System.out.println("hello " + name);<br>    }<br>    // 默认方法<br>    default void idea1(){<br>        System.out.println("this is idea1");<br>    };<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren

用 default 修饰符标记的方法就是默认方法,这样子类就不需要去实现这个方法了。

不过,引入默认方法后,就出现了一个「默认方法冲突」的问题。如果先在一个接口 A 中将一个方法 idea 定义为默认方法, 然后又在另一个接口 B 或者超类 C 中定义了同样的方法  idea,然后类 D 实现了这两个接口 A 和 B(或超类 C)。于是类 D 中就有了方法 idea 的两个默认实现,出现了冲突,为此,Java 制定了一套规则来解决这个二义性问题:

1 )  「超类优先」。如果超类提供了一个具体方法,接口中的同名且有相同参数类型的默认方法会被忽略。

2 )  「接口冲突」。如果一个父类接口提供了一个默认方法,另一个父类接口也提供了一个同名而且参数类型相同的方法,子类必须覆盖这个方法来解决冲突。例如:

<code>interface A {<br> default void idea(){<br>  System.out.println("this is A");<br> }<br>}<br><br>interface B {<br> default void idea(){<br>  System.out.println("this is B");<br> }<br>}<br><br>// 需要在 D 类中覆盖 idea 方法<br>class D implements A, B{<br>    public void getName(){<br>     System.out.println("this is D");<br>    }<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren

现在假设 B接口没有为 idea 提供默认实现:

<code>interface B {<br> void idea();<br>}</code> 
Nach dem Login kopieren
Nach dem Login kopieren

那么 D 类会直接从 A 接口继承默认方法吗?这好像挺有道理, 不过,Java 设计者更强调一致性。两个接口如何冲突并不重要,「只要有一个接口提供了一个默认实现,编译器就会报告错误, 我们就必须解决这个二义性」

当然,如果两个接口都没有为共享方法提供默认实现, 那么就与 Java 8 之前的情况一样,这里不存在冲突。

5. 接口存在的意义

在我自己早期学习编程的时候,对接口存在的意义实在困惑,我自己乱写代码的时候基本上不可能意识到需要去写接口,不知道接口到底有什么用,为什么要定义接口,感觉定义接口只是提前做了个多余的工作。

其实不是,定义接口并非多余,「接口是用来提供公用的方法,规定子类的行为的」。举个例子,让大家直观的感受下接口的作用:

比如有个网站, 需要保存不同客户的信息, 有些客户从 Web 网站来, 有些客户从手机客户端来, 有些客户直接从后台管理系统录入。假设不同来源的客户有不同的处理业务流程, 这个时候我们定义接口来提供一个保存客户信息的方法,然后不同的平台实现我们这个保存客户信息的接口,以后保存客户信息的话, 我们只需要知道这个接口就可以了,具体调用的方法被封装成了黑盒子,这也就是 Java 的多态的体现,「接口帮助我们对这些有相同功能的方法做了统一管理」

Das obige ist der detaillierte Inhalt vonWelche Rolle spielen Schnittstellen in Java?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage