Java——接口与实现类
目录
- 接口
- 实现接口
- 常用接口:java.util.Comparator
- Arrays.sort(Object[] arr, Comparator c)
- 常用接口:java.lang.Comparable
- Arrays.sort(Object[] arr)
- JDK1.8关于接口的新特性
- 接口的回调与多态
- 接口参数
- abstract类与接口的比较
- 总结
接口
使用关键字interface来定义一个接口。定义接口包含接口声明和接口体
接口体:只有两种成员
(1)全局的静态的常量:public static final,而且这三个单词可以省略
(2)公共的抽象的方法(没有方法体):public abstract,而且这两个单词可以省略
(没有变量,没有普通方法)
interface Printable{public static final int MAX=100;//等价写法:int MAX=100; 可以省略修饰符
public abstract void add(); //等价写法:void add();
}
接口的思想在于它可以要求某些类有相同名称的方法,但是方法的具体内容(方法体的内容)可以不同,即要求这些类实现接口,以保证这些类一定有接口中声明的方法(方法绑定)。除此之外,接口在要求一些类有相同名称的方法的同时,并不强迫这些类具有相同的父类。
(限定某些类,这些类不是同一个父类派生出来的,但是又希望他们有相同的行为特征)
实现接口
类实现接口:
在java语言中,接口由类通过关键字implements来实现,以便使用接口中的方法。实现多个接口用逗号隔开。
class A implements Printable,Addable
class A extends B implements Printable, Sleepable
重写接口中的方法:
1、一个非抽象类实现某个接口,那么这个类必须重写这个接口中的所有方法。
由于接口中的方法是public abstract ,所以类在重写接口方法时不仅要去掉abstract修饰符,而且方法的访问权限一定要显示地用public来修饰。
2、一个抽象类实现某个接口,既可以重写接口中的方法,也可以直接拥有接口中的方法。(抽象类不必重写接口中所有方法)
interface Computable{final int MAX=100;void speak(String s);int f(int x);float g(float x,float y);
}abstract class A implements Computable{public int f(int x){int sum =0;for(int i=1;i<=x;i++){sum=sum+i;}return sum;}
}
接口的细节说明
程序可以用接口名访问接口中的常量,但是如果一个类实现了接口,那么该类可以直接在类体中使用该接口中的常量。
如果父类实现了某个接口,那么子类也就自然实现了该接口,子类不必在显式地使用关键字implements声明实现这个接口。
接口也可以通过关键字extends继承另一个接口,子接口将继承父接口中的全部方法和常量。
常用接口:java.util.Comparator
这个接口是代表Java中比较两个对象的大小标准,而且是一种“定制”比较的标准。
抽象方法:int compare(Object o1, Object o2)
这个接口中没有规定如何比较两个对象的大小,但是规定了:
如果你认为o1 大于 o2,就返回正整数表示
如果你认为o1 小于 o2,就返回负整数表示
如果你认为o1 等于 o2,就返回0表示
演示代码:
public class TestComparator {public static void main(String[] args) {Student s1 = new Student("杨洪强", 24, 89);Student s2 = new Student("苏海波", 23, 100); //比较s1和s2的大小/*if(s1 > s2){//错误的 < >只用于基本数据类型System.out.println("s1 > s2");}*/AgeComparator c = new AgeComparator();if(c.compare(s1, s2) > 0){//如果比较s1,s2的结果是正整数,说明s1>s2System.out.println("s1 > s2的年龄");}else if(c.compare(s1, s2) <0){System.out.println("s1 < s2的年龄");}else{System.out.println("s1 = s2的年龄");}ScoreComparator s = new ScoreComparator();if(s.compare(s1, s2) > 0){//如果比较s1,s2的结果是正整数,说明s1>s2System.out.println("s1 > s2的成绩");}else if(s.compare(s1, s2) <0){System.out.println("s1 < s2的成绩");}else{System.out.println("s1 = s2的成绩");} }
}
//实现Comparator接口,来定制两个学生比较的具体实现方式
//例如:按照年龄比较
class AgeComparator implements Comparator{@Overridepublic int compare(Object o1, Object o2) {//(1)向下转型Student s1 = (Student) o1;Student s2 = (Student) o2;//(2)开始比较if(s1.getAge() > s2.getAge()){return 1;}else if(s1.getAge() < s2.getAge()){return -1;}return 0;}}
//实现Comparator接口,来定制两个学生比较的具体实现方式
//例如:按照成绩比较
class ScoreComparator implements Comparator{@Overridepublic int compare(Object o1, Object o2) {//(1)向下转型Student s1 = (Student) o1;Student s2 = (Student) o2;//(2)开始比较if(s1.getScore() > s2.getScore()){return 1;}else if(s1.getScore() < s2.getScore()){return -1;}return 0;}
}
class Student{private String name;private int age;private int score;public Student(String name, int age, int score) {super();this.name = name;this.age = age;this.score = score;}public Student() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";}
}
Arrays.sort(Object[] arr, Comparator c)
根据“指定比较器”产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过“指定比较器”可相互比较的
public static void sort(Object[] a, Comparator c)
第一个形参:需要排序的数组,Object[]说明可以是任意类型的对象数组
第二个形参:比较器对象 Comparator接口不能创建对象,只能传入实现类对象
Student[] all = new Student[5];all[0] = s1;all[1] = s2;all[2] = new Student("张三",23,88);all[3] = new Student("李四",24,44);all[4] = new Student("王五",25,45);//按年龄比较Arrays.sort(all, new AgeComparator());//按照成绩比较Arrays.sort(all, new ScoreComparator()); for (int i = 0; i < all.length; i++) {System.out.println(all[i]);}
常用接口:java.lang.Comparable
使比较类重写comparable接口,对象就可以调用比较方法进行大小比较。
java.util.Comparator:定制比较,定制顺序
int compare(Object o1, Object o2):
o1与o2比较,o1>o2,返回正整数
o1与o2比较,o1<o2,返回负整数
o1与o2比较,o1=o2,返回0
java.lang.Comparable:自然比较,自然顺序
int compareTo(Object obj)
this与obj对象比较,this > obj,返回正整数
this与obj对象比较,this < obj,返回负整数
this与obj对象比较,this = obj,返回0
演示代码:
public class TestComparable {public static void main(String[] args) {Student s1 = new Student("杨洪强", 24, 89);Student s2 = new Student("苏海波", 23, 100);//按成绩比较if(s1.compareTo(s2)>0){System.out.println("s1 > s2成绩");}else if(s1.compareTo(s2)<0){System.out.println("s1 < s2成绩");}else{System.out.println("s1 = s2成绩");}//按年龄比较,只能再用定制比较,补充完成这个功能}
}
class Student implements Comparable{private String name;private int age;private int score;public Student(String name, int age, int score) {super();this.name = name;this.age = age;this.score = score;}public Student() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";}@Overridepublic int compareTo(Object obj) {//this与obj比较,this和obj都是学生对象Student other = (Student) obj;//例如:对于学生对象来说,最常用的是按成绩排名,那么我就可以把自然顺序定位成绩升序if(this.score > other.score){return 1;}else if(this.score < other.score){return -1;}return 0; return this.score - other.score;}
}
Arrays.sort(Object[] arr)
根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。
public class TestArrays {public static void main(String[] args) {Student[] all = new Student[5];all[0] = new Student("杨洪强", 24, 89);all[1] = new Student("苏海波", 23, 100);all[2] = new Student("张三",23,88);all[3] = new Student("李四",24,44);all[4] = new Student("王五",25,45);Arrays.sort(all);//这里面排序过程中,调用了元素本身的compareTo()方法//因为元素本身是Student类型,它实现了java.lang.Comparable接口//本身就具备比较大小的能力,即拥有compareTo()方法 for (int i = 0; i < all.length; i++) {System.out.println(all[i]);}}
}
JDK1.8关于接口的新特性
1、Java8对接口进行了修改:
Java8之前,接口中的成员只有两种:
(1)全局的静态的常量:public static final,可以省略
(2)公共的抽象的方法:public abstract,可以省略Java8之后,接口又增加了两种新成员:(可以有方法体)
(3)静态方法:public static,不可以省略
调用方式:接口名.静态方法(实参列表)
(4)默认方法:public default,不可以省略
接口中权限修饰符都是public ,且都可以省略不写
2、为什么Java8要允许接口中定义静态方法?
是因为JDK发展了一段时间后,发现类库中,多了很多这样的成组的API:
(1)Path接口和Paths工具类
(2)Collection接口和Collections工具类…
一般工具类中都是静态方法,这些静态方法,基本上都是为前面这个对应接口服务的。 这样的话,就会出现很多API,使得程序员的学习成本增加了,使用成本也增加了。
于是把这样的静态方法,直接挪到接口中定义就好了。减少了这样的工具类的出现。
3、为什么么Java8要允许接口中定义默认方法?
是因为有的时候,一个接口它的大多数实现类对接口的抽象方法的实现代码是一样,那么我们写好几次就太麻烦了。
即相当于,默认方法是原来的抽象方法有了一个默认实现。如果实现类的实现和接口一样,就不需要重写,如果不一样就重写即可。
4、冲突问题
(1)当一个类同时实现了两个甚至更多个接口时,这些个接口中出现了方法签名相同的默认方法时,
那么我们必须在这个实现类中,做出选择。
选择一:保留其中一个,放弃另一个
选择二:两者都不用,完全重写一个
(2)当一个类同时继承了父类,又实现了接口,那么当父类中出现了和接口中方法签名一样的方法时,怎么办?
那么我们怎么选择?
选择一:默认选择,编译器默认选择父类
选择二:改选保留接口的
选择三:完全自己重写
public class TestInterface18 {public static void main(String[] args) {MyInter.test(); Son s = new Son();s.test();}
}
interface MyInter{public static void test(){System.out.println("接口中的静态方法");} void fun(); public default void method(){System.out.println("接口中的默认方法");}
}
class InterImpl1 implements MyInter{@Overridepublic void fun() {System.out.println("aaaa");}
}
class InterImpl2 implements MyInter{@Overridepublic void fun() {System.out.println("aaaa");}
}
class InterImpl3 implements MyInter{@Overridepublic void fun() {System.out.println("bbbb");}//在类中,重写接口的默认方法是,default要去掉@Overridepublic void method() {System.out.println("重写接口的默认方法");}
}
interface A{public default void test(){System.out.println("aaa");}
}
interface B{public default void test(){System.out.println("bbb");}
}
class C implements A,B{//选择一:保留其中一个,放弃另一个//在类中,重写接口的默认方法是,default要去掉
/* public void test(){
// A.super.test();//保留A接口的实现B.super.test();//保留B接口的实现}*/public void test(){System.out.println("ccc");}
}
class Father{public void test(){System.out.println("ffff");}
}
interface D{public default void test(){System.out.println("dddd");}
}
class Son extends Father implements D{//选择一:默认选择,保留父类的//选择二:该选,保留干爹的
// public void test(){// D.super.test();
// } //选择三:完全自己重写public void test(){System.out.println("ssss");}
}
接口的回调与多态
接口回调:可以把实现某一接口的类创建的对象的引用赋值给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法。(实际上,当接口变量调用被类实现的接口方法时,就是通知相应的对象调用这个方法,但这个接口变量是无法调用类中其他的非接口方法的,终点强调了这个接口的方法特性——体现类根据接口里的行为标准给出的具体行为)
接口回调类似于向上转型对象调用子类的重写方法。
接口的思想在于它可以要求某些类有相同名称的方法,但方法的具体内容可以不同,即要求这些类实现接口,以保证这些类一定有接口中所声明的方法;接口在要求一些类有相同名称的方法的同时,并不强迫这些类具有相同的父类
接口多态:不同的类在实现同一个接口时可能具有不同的实现方式,那么接口变量在回调接口方法时就可能具有多种形态
interface ShowMessage {void 显示商标(String s);
}
class TV implements ShowMessage {public void 显示商标(String s) {System.out.println(s);}
}
class PC implements ShowMessage {public void 显示商标(String s) { System.out.println(s);}
}
public class Example6_2 {public static void main(String args[]) {ShowMessage sm; //声明接口变量sm=new TV(); //接口变量中存放对象的引用sm.显示商标("长城牌电视机"); //接口回调。sm=new PC(); //接口变量中存放对象的引用sm.显示商标("联想奔月5008PC机"); //接口回调}
}
接口参数
如果一个方法的参数是接口类型,可以将任何实现该接口的类的实例引用传递给该接口参数,那么接口参数就可以回调类实现的接口方法。(和向上转型一样,不用重载多个方法)
interface SpeakHello {void speakHello();
}
class Chinese implements SpeakHello {public void speakHello() {System.out.println("中国人习惯问候语:你好,吃饭了吗? ");}
}
class English implements SpeakHello {public void speakHello() {System.out.println("英国人习惯问候语:你好,天气不错 ");}
}
class KindHello {public void lookHello(SpeakHello hello) { //接口类型参数hello.speakHello(); //接口回调}
}
public class Example6_5 {public static void main(String args[]) {KindHello kindHello=new KindHello();kindHello.lookHello(new Chinese());kindHello.lookHello(new English());}
}
abstract类与接口的比较
1、abstract类和接口都可以有abstract方法。
2、接口中只可以有常量,不能有变量;而abstract类中既可以有常量,也可以有变量。
3、abstract类中也可以有非abstract方法,接口不可以。
abstract类除了提供重要的需要子类重写的abstract方法,也提供了子类可以继承的变量和非abstract方法。
如果某个问题需要使用继承才能更好地解决,例如,子类除了需要重写父类的abstract方法,还需要从父类继承一些变量或一些重要的非abstract方法,就可以考虑使用abstract类。如果不需要继承,只需要若干个类给出某些重要的abstract方法的实现细节,就可以考虑使用接口。
总结
可以将接口理解为类的继承(一种特殊的父类),无论是从形式上,还是使用方法上。
子类重写父类方法近似实现类“重写”接口的抽象方法。
子类向上转型近似实现类回调接口方法。
Java——接口与实现类相关推荐
- java 接口初始化_Java类的初始化 | 学步园
类的初始化时机1.创建类的实例 2.访问类或接口的静态变量(static final常量除外,static final变量可以)3.调用类的静态方法 4.反射(Class.forName(packag ...
- Java接口、基类、抽象类详解(图解接口、继承和实现、基类和抽象类的区别等)——Java基础系列
文章目录 前言 总览(必看) 一.接口是"契约" 二.接口实例--Servlet接口 三.抽象标识符abstract和抽象类 四.基类作为"辅助" 求支持 前言 ...
- java 接口初始化_Java类和接口的初始化
类的初始化由执行类中静态代码块的初始化和类中声明的静态域的初始化两部分组成 接口的初始化由接口中声明的域(常量)的初始化组成 初始化的时机 类或接口T在以下任意情况发生之前会立即进行初始化:T是一个类 ...
- java接口匿名实现类的匿名对象和java类匿名子类的匿名对象相关提点
package com.atguigu09._inner;/*** @Description* @authr CodePerWorld Email:* @date*/ public class Out ...
- java接口请求工具类
Maven添加第三方类库 在这里我传的参数是Json格式的. 下面是java代码: /** * 招标接口输入参数,post请求 * * @param json ...
- Java接口四个类四则运算_用JAVA设计一个接口,声明有关算术运行的方法,并创建四个应用该接口的类,分别进行+-*/四则运算...
满意答案 接口: public interface Operator { public double operation(double a, double b); } 加法: public class ...
- Java接口四个类四则运算_java 实现四则运算小程序
题目地址:http://www.cnblogs.com/HQL0301/p/7502315.html 1.需求分析: (1) 按照用户输入来控制题目生成个数以及随机数的值域: (2)生成题目与答案的T ...
- java 接口编程_JAVA面向接口编程
一.什么是面向接口编程 要正确地使用Java语言进行面向对象的编程,从而提高程序的复用性,增加程序的可维护性.可扩展性,就必须是面向接口的编程.面向接口的编程就意味着:开发系统时,主体构架使用接口,接 ...
- java接口有非抽象方法_Java接口、抽象方法
1)Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能) ...
最新文章
- 为指针分配的内存太小
- sql2005收集作业相关历史记录
- junit测试报告生成_这是东西:jUnit:动态测试生成
- 文档对象模型dom_什么是文档对象模型,以及为什么应该知道如何使用它。
- node环境变量_实际使用Node环境变量的方法如下
- script链接标签前置无法读取的解决
- 服务中没有telnet_win7 服务中没有 prints pooler
- 35岁以上还没结婚的男女们,过的如何?
- 利用ObjectMapper进行对象与JSON互相转化
- win8计算机触摸板怎么设置,win8.1笔记本电脑怎么关闭键盘触摸板
- 三步解决error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build Tools“
- 封装pc端获取经纬度 百度地图
- 解决360浏览器自带翻译不能使用的问题
- Learning Conditioned Graph Structures for Interpretable Visual Question Answering论文解读
- 传统大华海康宇视安防摄像头RTSP流如何转webrtc直播低延时无插件浏览器视频播放
- APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
- 【机器学习基础】理解为什么机器可以学习1——PAC学习模型
- [渝粤教育] 商丘职业技术学院 Java Web应用程序开发 参考 资料
- 计算机网络TCP的全称,tcp/ip全称是什么
- 如何在目录下创建文件linux,linux在目录下创建文件