#インターフェース(英語: Interface) は、JAVA プログラミング言語の抽象型であり、抽象メソッドの集合です。インターフェースは通常、interface で宣言します。クラスはインターフェイスを継承することで、インターフェイスの抽象メソッドを継承します。 インターフェイスはクラスではありません
. インターフェイスの記述方法はクラスと非常に似ていますが、異なる概念に属します。クラスは、オブジェクトのプロパティとメソッド を記述します。このインターフェイスには、 クラスによって実装されるメソッド が含まれています。 インターフェイスを実装するクラスが抽象クラスでない限り、 それ以外の場合、クラスはインターフェイス内のすべてのメソッド を定義する必要があります。
インターフェイスはインスタンス化できませんが、実装することはできます。インターフェイスを実装するクラスは、インターフェイスに記述されているすべてのメソッド
を実装する必要があります。それ以外の場合は、抽象クラス として宣言する必要があります。さらに、Java では、インターフェイス型を使用して変数を宣言したり、変数をヌル ポインタ にしたり、このインターフェイスによって実装されたオブジェクトにバインドしたりできます。 インターフェースとクラスの類似点
#インターフェイスはオブジェクトのインスタンス化に使用できません
- ファイルは、.Java で終わるファイルに保存されます。ファイル名には、インターフェイス名
- が使用されます。インターフェイスのバイトコード ファイルは、.class で終わるファイルに保存されます。
- インターフェースに対応するバイトコード ファイルは、パッケージ名と一致するディレクトリ構造内に存在する必要があります
インターフェースとクラスの違い
インターフェイス内のすべてのメソッドも暗黙的に継承されます。 abstract であるため、インターフェイス内のメソッドは暗黙的に public abstract として指定されます (public abstract のみにすることができ、他の修飾子はエラーを報告します)インターフェイスにはコンストラクター メソッドがありません
- すべてインターフェイス内のメソッドは抽象メソッドである必要があります。default キーワードで変更されたメソッド、非抽象メソッドは、Java 以降のインターフェイスで使用できます。 8
- インターフェイスには、静的変数と最終変数を除き、メンバー変数を含めることはできません
- インターフェイスがクラスによって継承されるという概念は正確ではありません。正確には、クラスによって実装される必要があります。
- インターフェイスは、いわゆる多重継承を実現できます。
- インターフェイスのいくつかの特徴
抽象クラスのメソッドには、メソッドの特定の機能を実現できる特定の実行可能ステートメント、つまりメソッド本体を持つことができます。ただし、インターフェイス内のメソッドではできません (例:インターフェイスには変数が含まれていますが、変数はインターフェイス内の は、public static Final 変数として暗黙的に指定されます (パブリックであることのみが可能です。プライベートで変更するとコンパイル エラーが報告されます)
- インターフェイス内のメソッドは実装できませんインターフェイス内のメソッドは、インターフェイスを実装するクラスによってのみ実装できます。
- 抽象クラスとインターフェイスの違いBefore JDK1.8 には次のような違いがありました。
System.out.println(“I'm super corn !!”);
)JDK1.9 以降では、メソッドをプライベートとして定義できるようになりました。一部の再利用コードではメソッドが公開されません
抽象クラスのメンバー変数さまざまなタイプを使用できますが、インターフェイス内のメンバー変数は次のタイプのみです
# インターフェイスの ##public static Final タイプには、静的コード ブロックを含めることはできません静的メソッド (静的メソッドで変更されたメソッド) の使用。一方、抽象クラスは静的コード ブロックと静的メソッドを持つことができます。
クラスは抽象クラスを 1 つだけ継承できますが、クラスは実装できます。複数のインターフェース- ここで次の点に注意してください:
JDK1.8 以降、インターフェースには静的メソッドとメソッド本体を含めることが許可されており、特定の実装メソッドを含めます。このメソッドを「デフォルト メソッド」と呼びます。このメソッドはデフォルトのキーワードを使用して変更します
抽象クラスが存在しますこれは、コンパイラがより適切に検証できるようにすることを意味します。一般に、抽象クラスを直接使用することはなく、そのサブクラスを使用します。抽象クラスを介してオブジェクトを取得すると、コンパイラが時間内に通知してくれます。
注: 上記の内容は、ざっくりと一度見ていただくだけで大丈夫です。理解できなくても大丈夫です。以下で一つずつ説明していきますので、大きな夢から目覚めたときの感覚
#では、実際のインターフェースとは何でしょうか。 ?ラップトップの USB ポート、電源ソケットなどが考えられます。これらのインターフェイスは、実装と使用基準の点でも異なります
コンピュータの USB ポートは、U ディスク、マウス、キーボードなど、USB プロトコルに準拠するすべてのデバイスに接続できます
電源ソケット ジャックは、コンピュータ、テレビ、炊飯器など、仕様を満たすすべてのデバイスに接続できます。
上記の例から、 インターフェースは公的動作標準であることがわかり、誰もが実装する場合、標準を満たしている限り、普遍的に使用できます。 Java では、インターフェイスは次のようにみなされます。 複数のクラスの共通の仕様。これは参照データ型です。
インターフェイスの定義形式と定義クラス形式は基本的に同じで、class キーワードをinterface キーワードに置き換えてインターフェイスを定義します。
public interface 接口名称{ //抽象方法 public abstract void method1(); //public abstract是固定搭配,可以不写 public void method2(); abstract void method3(); void method4(); //注意:在接口中上述的写法都是抽象方法,所以method4这样写代码更整洁}
ヒント:
インターフェイスを作成する場合、インターフェイスの名前は通常、大文字の I (アイと発音します) で始まります
インターフェイスの名前は通常、形容詞の品詞を含む単語を使用して付けられます。
Alibaba コーディング標準では、インターフェイスのメソッドとプロパティに修飾子を追加しないことが合意されています。コードをクリーンに保つためのインターフェイス
インターフェイスを直接インスタンス化して使用することはできません。実装するクラスが必要です。これを作成し、インターフェイスにすべての抽象メソッドを実装します。
public class 类名称 implements 接口名称{ //...}
注: サブクラスと親クラスの間には拡張継承関係があり、クラスとインターフェイスの間には実装関係があります。 。
出力:USB マウスおよび USB キーボードのクラスとインターフェイスは、機能を実装するためにラップトップで使用されます。
##
USB インターフェイス: USB インターフェイスの開閉機能が含まれます。デバイス
Laptop クラス: 電源のオン/オフと USB デバイスの使用機能を含む
Mouse クラス: USB インターフェイスを実装し、クリック機能を備えます。
Keyboard クラス: USB インターフェイスを実装し、入力機能を備えています
//USB接口public interface USB{ void openDevice(); void closeDevice();}//鼠标类,实现USB接口public class Mouse implements USB{ @Override public void openDevice(){ System.out.println("打开鼠标"); } @Override public void closeDevice(){ System.out.println("关闭鼠标"); } public void click(){ System.out.println("鼠标点击"); }}//键盘类,实现USB接口public class KeyBoard implements USB { @Override public void openDevice(){ System.out.println("打开键盘"); } @Override public void closeDevice(){ System.out.println("关闭键盘"); } public void inPut(){ System.out.println("键盘输入"); }}//笔记本类:使用USB设备public class Computer { public void powerOn(){ System.out.println("打开笔记本电脑"); } public void powerOff(){ System.out.println("关闭笔记本电脑"); } public void useDevice(USB usb){ usb.openDevice(); if(usb instanceof Mouse){ Mouse mouse = (Mouse)usb; mouse.click(); }else if(usb instanceof KeyBoard){ KeyBoard keyBoard = (KeyBoard)usb; keyBoard.inPut(); } usb.closeDevice(); }}//测试类:public class TestUSB{ public static void main(String[] args){ Computer computer = new Computer(); computer.powerOn(); //使用鼠标设备 computer.useDevice(new Mouse()); //使用键盘设备 computer.useDevice(new KeyBoard()); computer.powerOff(); }}ログイン後にコピー
InstanceofはJavaの予約ですキーワード、左側にオブジェクト、右側にクラスがあり、戻り値の型はブール型です。
その具体的な機能は、左側のオブジェクトが右側のクラスによって作成されたインスタンス化されたオブジェクトであるか、右側のクラスのサブクラスであるかをテストすることです。
そうである場合は true を返し、そうでない場合は false を返します
[instanceof の使用に関する注意事項] 既存の継承関係と、instanceof の使用 (インターフェイスの実装を含む)
#[instanceof アプリケーションのシナリオ] オブジェクト強制を使用する必要がある 型変換の際には、instanceof を使用して判断する必要があります
public class TestUSB { public static void main(String[] args){ USB usb = new USB(); }}//编译会出错:USB是抽象的,无法实例化
public interface USB { //编译出错:此处不允许使用修饰符private //或者是java: 缺少方法主体, 或声明抽象 private void openDevice(); void closeDevice(); //不同JDK版本编译器的标准是不一样的,报错也是不一样的}
#
public interface USB { void openDevice(); //编译失败:因为接口中的方法默认为抽象方法 //Error:接口抽象方法不能带有主体}
#インターフェース内のメソッドをオーバーライドする場合、デフォルトをアクセス許可の変更として使用することはできません
public interface USB {void openDevice();//默认为publicvoid closeDevice();//默认为public}public class Mouse implements USB { @Override void openDevice(){ System.out.println("打开鼠标"); } //...}//这里编译会报错,重写USB中的openDevice方法时,不能使用默认修饰符
インターフェイスには変数を含めることができますが、インターフェイスは次のようになります。コンパイラは自動的かつ暗黙的に
public interface USB {
double brand = 3.0;//默认为:final public static修饰
void openDevice();
void closeDevice();}public class TestUSB {
public static void main(String[] args){
System.out.println(USB.brand);
//可以直接通过接口名访问,说明变量时静态的
//下面写法会报错 Java:无法为最终变量brand分配值
USB.brand = 2.0;
//说明brand具有final属性
}}
を指定します。インターフェイスでは静的であること コード ブロックと構築メソッド
public interface USB { public USB(){ }//编译失败 { }//编译失败 void openDevice(); void closeDevice();}
インターフェイスはクラスではありませんが、サフィックスですインターフェイスがコンパイルされた後のバイトコード ファイルの形式も .class
クラスがインターフェイス内のすべての抽象メソッドを実装していない場合、クラスを抽象クラスに設定する必要があります
JDK8 で指定されているように、インターフェースには上記のデフォルトのメソッドを含めることができます
複数のインターフェースを実装します
を実装できます。次のコードは、 鱼会游泳 而青蛙即会跑又会游泳 注意:一个类实现多个接口的时候,每个接口中的抽象方法都要去实现,除非类用abstract修饰,为抽象类 提示IDEA中使用ctrl + i 可以快速实现接口 还有一种动物水陆空三栖,它是大白鹅 这段代码展现了Java面向对象编程中最常见的用法:一个类继承了一个父类,然后同时实现多个接口 猫是一种动物,具有会跑的特性 有了接口之后,类的使用者就不需要去关注具体的类的属性是否符合,而只需要关心某个类是否具有某个特性/功能,如果有,就可以实现对应的接口 输出结果 在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。 通过接口继承创建一个新的接口IAmphibious表示“两栖的”。 接口之间的继承就相当于把多个接口合并到了一起 我们在之前的数组中讲解过给数组排序,那么我们该如何给对象数组排序呢? 我们再给定一个学生对象数组,根据这个对象数组中的元素进行排序 那么按照我们之前的理解,数组中有一个可以供我们使用的sort方法,我们能否直接使用呢? 我们可以用Student类实现Comparable接口,并实现其中的compareTo方法 那么我们在这里重写了compareTo的方法,自己定义了比较的规则,我们就自己再去写一个sort的方法,去调用这个compareTo方法,真正意义上实现对 对象数组的排序 sort方法写好了,我们写一个main函数来测试一下 运行结果 那么我们如果想要按照名字排序呢?也是可以的 其作用如其名,是用来进行克隆的,Clonable是个很有用的接口。 我们如果只是通过clone,那么就只是拷贝了Person的对象,但是Person中的money对象我们并没有拷贝下来,只是单纯拷贝下来一个地址,那么我们在这里就要进行深拷贝,讲Money类也接受Clonable接口,这样在调用clone方法的时候,money也会进行克隆 以上がJavaインターフェースの使用例分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。public class Animal {
protected String name;
public Animal(String name){
this.name = name;
}}
public interface IFlying {
void fly();}public interface IRunning {
void run();}public interface ISwimming {
void swim();}
那么接下来我们创建几个具体的动物类来接受并实现这些接口
比如,猫会跑public class Cat extends Animal implements IRunning{
public Cat(String name) {
super(name);
}
@Override
public void run() {
System.out.println("小猫"+this.name+"正在跑");
}}
public class Fish extends Animal implements ISwimming{
public Fish(String name){
super(name);
}
@Override
public void swim() {
System.out.println("小鱼"+this.name+"正在游泳");
}}
public class Frog extends Animal implements IRunning,ISwimming{
public Frog(String name){
super(name);
}
@Override
public void run() {
System.out.println("青蛙"+this.name+"正在跑");
}
@Override
public void swim() {
System.out.println("青蛙"+this.name+"正在游泳");
}}
public class Goose extends Animal implements IRunning,ISwimming,IFlying{
public Goose(String name) {
super(name);
}
@Override
public void fly() {
System.out.println(this.name+"正在飞");
}
@Override
public void run() {
System.out.println(this.name+"正在跑");
}
@Override
public void swim() {
System.out.println(this.name+"正在漂在水上");
}}
继承表达的含义是is-a,而接口表达的含义是具有xxx的特性
青蛙是一种动物,即能跑也能有用
大白鹅也是一种动物,技能跑,也能游,还能飞
那么我们现在实现一个走路的方法public class TestDemo1 {
public static void walk(IRunning iRunning){
System.out.println("我带着小伙伴去散步");
iRunning.run();
}
public static void main(String[] args) {
Cat cat = new Cat("小猫");
walk(cat);
Frog frog = new Frog("小青蛙");
walk(frog);
}}
只要是会跑的,带有跑这个属性特征的,都可以接受相应的对象public class Robot implements IRunning{
private String name;
public Robot(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(this.name+"正在用轮子跑");
}
public static void main(String[] args) {
Robot robot = new Robot("机器人");
walk(robot);
}}
故输出结果为接口之间的继承
即:用接口可以达到多继承的目的
接口可以继承一个接口,达到复用的效果。这里使用extends关键字interface IRunning {
void run();}interface ISwimming {
void swim();}//两栖的动物,即能跑,也能游泳interface IAmphibious extends IRunning ISwimming {}class Frog implements IAmphibious {
...}
创建的Frog类就实现了这个两栖的接口接口使用的例子
首先我们定义一个Student的类,然后重写一下String方法public class Student {
private String name;
private int score;
public Student(String name,int score){
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}}
这里我们按照分数降序排序public class Student {
private String name;
private int score;
public Student(String name,int score){
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
public static void main(String[] args) {
Student[] students = new Student[]{
new Student("A",95),
new Student("B",96),
new Student("C",97),
new Student("D",98),
};
}}
Arrays.sort(students);System.out.println(students);//运行结果:Exception in thread "main" java.lang.ClassCastException: class ClassArray.Student cannot be cast to class java.lang.Comparable (ClassArray.Student is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
at java.base/java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
at java.base/java.util.Arrays.sort(Arrays.java:1041)
at ClassArray.Student.main(Student.java:36)
我们可以看到这里程序报错了,这里的意思是Student并没有实现Comparable的接口
那么这里的sort是进行普通数字的比较,大小关系明确,而我们指定的是两个学生对象的引用变量,这样的大小关系的指定是错误的,我们需要额外去人为规定对象中的比较元素
那么怎么实现呢?public class Student implements Comparable<Student>{
private String name;
private int score;
public Student(String name,int score){
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) {
if (this.score>o.score){
return -1;// 如果当前对象应排在参数对象之前,则返回小于0的数字
} else if(this.score<o.score){
return 1;// 如果当前对象应排在参数对象之后,则返回大于0的数字
} else{
return 0;// 如果当前对象和参数对象不分先后,则返回0
}
}}
我们使用冒泡排序法 public static void sort(Comparable[] array){// 这里要注意,虽然接口不能实例化对象,// 但是接口类型的引用变量可以指向它的实现类对象// 这里的实现类对象就是实现了这个接口的对象// 例如Comparable[] comparable = new Student[3];// 所以这里的参数就可以用Comparable[] array来接收
for (int bound = 0;bound<array.length;bound++){
for (int cur = array.length-1;cur>bound;cur--){
if (array[cur-1].compareTo(array[cur])>0){
//这里就说明顺序不符合要求,交换两个变量的位置
Comparable tmp = array[cur-1];
array[cur-1] = array[cur];
array[cur] = tmp;
}
}
}}
public static void main(String[] args) {
Student[] students = new Student[]{
new Student("A",95),
new Student("B",91),
new Student("C",97),
new Student("D",95),
};
System.out.println("sort前:"+Arrays.toString(students));
sort(students);
System.out.println("sort后:"+Arrays.toString(students));
}
E:\develop\Java\jdk-11\bin\java.exe "-javaagent:E:\IDEA\IntelliJ IDEA Community Edition 2021.3.2\lib\idea_rt.jar=65257:E:\IDEA\IntelliJ IDEA Community Edition 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVAcode\gyljava\Interface\out\production\Interface ClassArray.Studentsort前:[Student{name='A', score=95}, Student{name='B', score=91}, Student{name='C', score=97}, Student{name='D', score=95}]sort后:[Student{name='C', score=97}, Student{name='A', score=95}, Student{name='D', score=95}, Student{name='B', score=91}]
import java.util.Arrays;import java.util.Comparator;/**
* Created with IntelliJ IDEA.
* Description: Hello,I would appreciate your comments~
* User:Gremmie
* Date: -04-13
* Destination:利用Comparable的接口实现对 对象数组 选择性排序的功能
*/class Student implements Comparable<Student>{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return this.name.compareTo(o.name);
}}class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}}class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}}public class TestDemo {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("zhangsan",19);
students[1] = new Student("lisi",8);
students[2] = new Student("abc",78);
AgeComparator ageComparator = new AgeComparator();
NameComparator nameComparator = new NameComparator();
//这里的方法sort是Array里面自带的,非常方便,
//只需将我们写好的比较器传过去就好了
System.out.println("排序前:"+Arrays.toString(students));
Arrays.sort(students,nameComparator);
System.out.println("排序后:"+Arrays.toString(students));
Comparable<Student>[] studentComparable =students;
}
public static void main2(String[] args) {
/*Student students1 = new Student("zhangsan",19);
Student students2 = new Student("abc",78);
if(students2.compareTo(students1) > 0) {
System.out.println("fafaa");
}*/
}
public static void main1(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("zhangsan",19);
students[1] = new Student("lisi",8);
students[2] = new Student("abc",78);
System.out.println("排序前:"+Arrays.toString(students));
Arrays.sort(students);
System.out.println("排序后:"+Arrays.toString(students));
}}
Clonable接口以及深拷贝
Object类中存在一个clone方法,调用这个方法可以创建出一个对象,实现“拷贝”。
但是我们想要合法调用clone方法,就要先实现Clonable接口,
否则就会抛出CloneNotSupportedException异常/**
* Created with IntelliJ IDEA.
* Description: Hello,I would appreciate your comments~
* User:Gremmie
* Date: -04-13
* Destination:利用Clonable的接口实现clone方法,克隆含对象的对象
*/class Money implements Cloneable{
public double money = 19.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}}class Person implements Cloneable{
public int id = 1234;
public Money m = new Money();
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person) super.clone();
tmp.m = (Money) this.m.clone();
return tmp;
//return super.clone();
}}public class TestDemo {
public static void main(String[] args) {
Object o = new Person();
Object o2 = new Money();
}
public static void main1(String[] args) throws CloneNotSupportedException {
Person person1 = new Person();
Person person2 = (Person)person1.clone();
System.out.println(person1.m.money);
System.out.println(person2.m.money);
System.out.println("=========================");
person2.m.money = 99.99;
System.out.println(person1.m.money);
System.out.println(person2.m.money);
}}