この記事では、java に関する関連知識を提供します。主に、インターフェイスの概念、いくつかの知識ポイント、文法規則、インターフェイスの使用の概要など、インターフェイスに関連する問題を紹介します。インターフェースの特徴など、以下で見ていきましょう。
推奨学習: 「Java ビデオ チュートリアル 」
1 枚の写真ストリーム
1 つのインターフェースに複数のインターフェースが存在する可能性がありますInterface (英語: インターフェース)、 JAVA プログラミング言語は抽象型、つまり抽象メソッドのコレクションであり、インターフェイスは通常、interface で宣言されます。クラスはインターフェイスを継承することで、インターフェイスの抽象メソッドを継承します。
インターフェイスはクラスではありません. インターフェイスの記述方法はクラスと非常に似ていますが、異なる概念に属します。クラスは、オブジェクトのプロパティとメソッド を記述します。このインターフェイスには、 クラスによって実装されるメソッド が含まれています。 インターフェイスを実装するクラスが抽象クラスでない限り、
それ以外の場合、クラスはインターフェイス内のすべてのメソッド を定義する必要があります。
インターフェイスはインスタンス化できませんが、実装することはできます。インターフェイスを実装するクラスは、インターフェイスに記述されているすべてのメソッド を実装する必要があります。それ以外の場合は、抽象クラス として宣言する必要があります。さらに、Java では、インターフェイス型を使用して変数を宣言したり、変数をヌル ポインタ にしたり、このインターフェイスによって実装されたオブジェクトにバインドしたりできます。 インターフェースとクラスの類似点
インターフェースはオブジェクトのインスタンス化に使用できませんインターフェース ファイルは、 で終わるファイルに保存されます。 Java の場合、ファイル名にはインターフェイス名が使用されます。
- インターフェイスのバイトコード ファイルは、.class で終わるファイルに保存されます。
- インターフェイスに対応するバイトコード ファイルは、一致するディレクトリ構造に存在する必要があります。パッケージ名
- インターフェースとクラスの違い
インターフェースにはコンストラクターがありませんMethod
- インターフェイス内のすべてのメソッドは抽象メソッドである必要があります。Java 8 以降では、default キーワードで変更された非抽象メソッドをインターフェイスで使用できます。
- インターフェイスにはメンバー変数を含めることはできません。 static 変数と Final 変数を除く
- クラスによって継承されるインターフェイスという概念は正確ではありません。正確には、クラスによって実装される必要があります。
- ##インターフェイスは、いわゆるものを実現できます。多重継承
- インターフェースのいくつかの特性
インターフェースには変数が含まれていますが、インターフェース内の変数は暗黙的にパブリック静的最終変数として指定されます (パブリックにのみ指定できます)。プライベート変更を使用するとコンパイル エラーが報告されます)JDK1.8より前では、次のような違いがありました
- インターフェイス内 インターフェイス内にメソッドを実装することはできません。インターフェイス内のメソッドは、インターフェイスを実装するクラスによってのみ実装できます。
- 抽象クラスとインターフェースの違い
抽象クラスのメソッドには特定の実行可能ファイルを含めることができますステートメント、つまりメソッド本体は、メソッドの特定の機能を実現できますが、インターフェイス内のメソッドは実現できません (例:
System.out.println("I'm super corn!!");)JDK1.9 以降では、メソッドをプライベートとして定義できるようになりました。一部の再利用コードではメソッドが公開されません
- 抽象クラスのメンバー変数は さまざまな型 にすることができますが、インターフェイスのメンバー変数は
public staticfinal- ## 型のみにすることができます##インターフェイスには静的コード ブロックと静的メソッド (静的メソッドで変更されたメソッド) を含めることはできません。また、抽象クラスは静的コード ブロックと静的メソッドを持つことができますクラスは 1 つの抽象クラスのみを継承できますが、クラスは複数のインターフェイスを実装できます
- したがって、ここで注意する必要があります。 さらに:
- JDK1.8 以降、インターフェイスには静的メソッドとメソッド本体を含めることができます。特定の実装メソッドを含めることができます。このメソッドを「デフォルト メソッド」と呼びます。このメソッドは、default キーワードを使用します。修正
抽象クラスの存在の意味は、コンパイラーがより適切に検証できるようにするため、通常、抽象クラスを直接使用せず、そのサブクラスを使用します。誤って抽象クラスを通じてオブジェクトを作成した場合は、コンパイラーが時間内に通知します。
注: 上記の内容は、ざっくりと一度見ていただくだけで大丈夫です。理解できなくても大丈夫です。以下で一つずつ説明していきますので、そうすれば、振り返ったときにこれらの知識のポイントがよりよく理解できるようになります。
では、実際の生活では、インターフェイスとは何でしょうか?ラップトップの 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 接口名称{ //...}
注: サブクラスと親クラスの間には、extends の間には継承関係があり、クラスとインターフェイスの間には実装関係があります。
USB マウスおよび USB キーボードのクラスとインターフェイスは、機能を実装するためにラップトップで使用されます
USB インターフェイス: デバイスの開閉機能を含むNotebook クラス: 電源オン/オフ機能と 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
上記のコード例では、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 static Final
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();}
在Java中,类和类之间是单继承的,一个类只能由一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。下面用代码来演示
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+"正在游泳"); }}
注意:一个类实现多个接口的时候,每个接口中的抽象方法都要去实现,除非类用abstract修饰,为抽象类
提示IDEA中使用ctrl + i 可以快速实现接口
还有一种动物水陆空三栖,它是大白鹅
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+"正在漂在水上"); }}
这段代码展现了Java面向对象编程中最常见的用法:一个类继承了一个父类,然后同时实现多个接口
继承表达的含义是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); }}
故输出结果为
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。
即:用接口可以达到多继承的目的
接口可以继承一个接口,达到复用的效果。这里使用extends关键字
interface IRunning { void run();}interface ISwimming { void swim();}//两栖的动物,即能跑,也能游泳interface IAmphibious extends IRunning ISwimming {}class Frog implements IAmphibious { ...}
通过接口继承创建一个新的接口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), }; }}
那么按照我们之前的理解,数组中有一个可以供我们使用的sort方法,我们能否直接使用呢?
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是进行普通数字的比较,大小关系明确,而我们指定的是两个学生对象的引用变量,这样的大小关系的指定是错误的,我们需要额外去人为规定对象中的比较元素
那么怎么实现呢?
我们可以用Student类实现Comparable接口,并实现其中的compareTo方法
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><p>那么我们在这里重写了compareTo的方法,自己定义了比较的规则,我们就自己再去写一个sort的方法,去调用这个compareTo方法,真正意义上实现对 对象数组的排序<br>我们使用冒泡排序法</p> <pre class="brush:php;toolbar:false"> public static void sort(Comparable[] array){// 这里要注意,虽然接口不能实例化对象,// 但是接口类型的引用变量可以指向它的实现类对象// 这里的实现类对象就是实现了这个接口的对象// 例如Comparable[] comparable = new Student[3];// 所以这里的参数就可以用Comparable[] array来接收 for (int bound = 0;bound<array.length>bound;cur--){ if (array[cur-1].compareTo(array[cur])>0){ //这里就说明顺序不符合要求,交换两个变量的位置 Comparable tmp = array[cur-1]; array[cur-1] = array[cur]; array[cur] = tmp; } } }}</array.length>
sort方法写好了,我们写一个main函数来测试一下
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)); }}</student></student></student></student>
其作用如其名,是用来进行克隆的,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); }}
我们如果只是通过clone,那么就只是拷贝了Person的对象,但是Person中的money对象我们并没有拷贝下来,只是单纯拷贝下来一个地址,那么我们在这里就要进行深拷贝,讲Money类也接受Clonable接口,这样在调用clone方法的时候,money也会进行克隆
推荐学习:《java视频教程》
以上がJava インターフェースを理解できるようにする (詳細な例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。