接口的理解
一.与抽象类的区别
public class TestBasicInterface{
public static void main(String[] args){
}
}
//抽象类
abstract class MuClass{
//1.不能new对象(对象不能独立存在)
//2.有抽象方法(子类必须覆盖)
// public abstract void m1();
public static final String NAME = "胡琦";
}
- 接口相当于特殊的抽象类,定义方式,组成部分与抽象类类似
- 接口没有构造方法,不能创建对象
- 接口是抽象的(前面加不加abstract都是一样的)
只能定义:
- 公开静态常量
- 公开抽象方法
interface MyInterface{
//1.公开静态常量
public static final String FiELD = "hello";
//2.公开抽象方法
public abstract void method();
}
与抽象类的相同点
- 可以编译成字节码文件
- 不能创建对象
- 可以作为引用类型
- 具备Object类中所定义的方法
与抽象类的不同点
-
所有的属性都是公开静态常量,隐式使用public static final修饰
-
所有的方法都是公开抽象方法,隐式使用public abstract修饰
-
没有构造方法,动态代码块,静态代码块
二.接口基础
- 接口是一种能力和约定
- 接口的定义:代表了某种能力
- 方法的定义: 能力的具体要求
- JAVA为单继承,当父类方法种类无法满足子类需求时,可以实现接口扩充子类能力
- 父类给的是类别下的共性
- 接口是超脱了父类给予的,代表一种能力,可以添加独有的能力
- 需要哪种能力,就可以添加一个接口
- 人任何类在实现接口时,必须实现接口中的所有抽象方法,否则此类为抽象类
- 实现接口中的抽象方法时,访问修饰符必须是public.
接口的好处
- 程序的耦合度降低
- 更自然的使用多态
- 设计与实现完全分离
- 更容易搭建程序框架
- 更容易更换具体实现
public class Test{
public static void main(String[] args){
}
}
//父类给的是类别下的共性
abstract class Animal{
String breed;
int age;
String sex;
//抽象方法(规定子类必须存在的行为,并且规范了该行为的具体要求)
public abstract void eat();
public abstract void sleep();
}
//实现了会跑和会游泳的接口,为这个子类添加了两种能力
//重写run和swim抽象方法
class Dog extends Animal implements Runnable, Swimmable{
String furColor;
public void eat(){}
public void sleep(){}
//独有方法
public void run(){}//必须实现接口中的run方法
public void swim(){}
}
class Cat extends Animal implements Runnable{
String furColor;
public void eat(){}
public void sleep(){}
//独有方法
public void run(){}//重写
public void climb(){}
}
class Bird extends Animal implements Runnable{
String furColor;
public void eat(){}
public void sleep(){}
//独有方法
public void run(){}//重写了
public void fly(){}
}
class Fish extends Animal implements Swimmable {
public void eat(){}
public void sleep(){}
//独有方法
public void swim(){}
}
//接口是超脱了父类给予的,代表一种能力,可以添加独有的能力
//接口时一种能力
interface Runnable{
//接口中(的方法)是一种约定
//跑的能力
public abstract void run();
}
interface Swimmable{
//游泳的抽象方法,谁想要这功能就去实现这个接口
public abstract void swim();
}
//公交车也有跑的能力
calss Bus implements Runnable{
public void run(){
}
}
三,接口引用
//其他代码公用上面的
public class Test{
public static void main(String[] args){
//父类引用指向子类对象(多态)
Animal a = new Dog()//把狗当动物看待(狗是一种动物)
//接口引用指向实现类对象(更自然的多态)
//接口关注的是一种能力
Runnable r = new Dog();//狗是一种会跑的东西(把狗当成一种会跑的东西看待)
//r.eat();//Error--Runnable也许是公交车之类的
r.run();//调用实现类的run()方法
//r中存贮了一个会跑的东西,还想调用接口以外的内容
//向下转型
Dog myDog = (Dog)r;
myDog.eat();
myDog.sleep();
myDog.swim();
}
}
注意
- 仅可调用接口中申明的方法,不可调用实现类中独有的方法
- 同父类一样,接口也可声明为引用,并指向实现类对象
- 多种不同类型的引用指向同一个对象时,表示看待对象的视角不同
- 不同引用所看到的对象范围不同 ,只能调用自身类型中所声明的部分
//伪代码
public calss Test{
main(){
游客 c = new 游客;
c.出海游玩;
new Student;
}
}
calss 游客{
public void xxx(Runnable r){//Runnable r = new Bus();
}
//不关心类别,只关注功能(行为),是否实现这个接口
public void 出海游玩(可漂浮的){//使用接口作为方法形参,更自然的实现多态
}
//比如喝水,.只关心是否可以承装水,而不关心是 用杯子还是碗之类的东西
//关注类别,范围会小点
public void 出海游玩(船){//使用父类作为方法形参,实现多态
}
/*
public void 出海游玩(观光游轮){
}
public void 出海游玩(快艇){
}
public void 出海游玩(木筏){
}
*/
}
class Student{
public void 求人换灯泡(会换灯泡的 person){
灯泡 费灯泡 = person.换灯泡();
}
public void 求人换灯泡(电工){
}
}
interface 会换灯泡的{
public 废灯泡 换灯泡();
}
四.常量接口
1>常见关系
- 类与类:
- 单继承
- extends 父类名称
- 类与接口:
- 多实现
- implements 接口名称1, 接 口名称2, 接口名称n
- 接口与接口:
- 多继承
- extends 父接口1, 父接口2,父接口n
public class Test{
public static void main(String[] args){
}
}
interface IA{
void m1();
}
interface IB{
void m2();
}
interface IC{
void m3();
}
class classD implements IA, IB, IC{
public void m1(){}
public void m2(){}
public void m3(){}
}
2>常量接口
- 接口支持公开静态常量更纯粹
- 在一个没有行为的接口上定义公开静态常量,这个接口的意义就是规范取值
- 将多个常用于表示状态或者固定值的变量,已静态常量的形式定义在接口中统一管理,提高代码可读性
public class Test{
public static void main(String[] args){
MyLight.YRELLW;//使用类中的常量,而且不能new对象//意义不大
int currentLight = Light.GREEN;//当前灯
//红绿灯实例,切换灯光,更加的直观.
if(currentLight == Light.GREEN){
currentLight = Light.YELLOW;
}else if(currentLight == Light.YELLOW){
currentLight = Light.RED;
}else{
currentLight = Light.GREEN;
}
//使用枚举类型
Light curr = Light.GREEN;
}
}
//枚举(规范了取值的类型),规定只能取这几个
enum Light{
GREEN, YELLOW, RED
}
//常量接口
interface Light{
double PI = 3.1415926;
public static final int RED = 1;
int YELLOW = 2;
int GREEN = 3;
}
class MyLight(){
public static final int RED = 1;
int YELLOW = 2;
int GREEN = 3;
//定义了私有的构造方法
//这个类不能new对象了
private MyLight(){}
}
五. 接口回调
1> 什么是接口
- 宏观概念: 接口是一种标准.
- 接口的实现者
- 谁使用implements实现了接口谁就是接口的实现者
- 接口的使用者
- 谁创建了接口类的对象,使用了接口的抽象方法,谁就是接口的使用者
- 接口的回调
- 先有了
public class TestUSB{
public static void main(String[] args){
/*
USB usb = new Fan();//实现类对象
usb.service();//输出风扇在转...
usb = new Lamp();.
usb.service();//输出台灯在亮..
usb = new UDisk();.
usb.service();//输出读写数据..
*/
/*
Computer c1 = new Computer();
c1.u1 = new Fan();
c1.u2 = new Lamp();
c1.u3 = new UDisk();
*/
c1.u1//这里如果什么都没有插,调用on()就会发生错误
//如何保证调用时一定会有值
c1.on(new Fan(), new Lamp(), new UDisk());//使用工具
}
}
//标准的使用者
class Computer{//工具
USB u1;
USB u2;
USB u3;
//这里开机的时候传入参数,把设备都插上..
//保证不为空
//或许可以重载或者可变参数来控制下,插几个就使用几个
public void on(USB u1, USB u2, USB u3){
this.u1 = u1;
this.u2 = u2;
this.u3 = u3;
System.out.println("开机,进入操作页面...");
//接口的使用者
u1.service();
u2.service();
u3.service();
}
}
//标准
interface USB{
//服务
public void service();
}
//标准的实现者
class Fan implements USB{
public void service(){
System.out.println("风扇在转....");
}
}
class Lamp implements USB{
public void service(){
System.out.println("台灯在亮....");
}
}
class UDisk implements USB{
public void service(){
System.out.println("读写数据....");
}
}
2> 回调原理
-
接口回调:
- 先有接口的使用者,后有接口的使用者
- 出现的先后顺序
-
4.程序员(工具的使用者)(new 工具,使用方法) --> 2.接口的使用者(工具) (computer)–>1. 标准(接口) -->3. 程序员(接口的实现者)(Fan等)
3> comparable接口
- 此接口中的compareTo抽象方法比较此对象与指定对象的顺序,如果此对象小于,等于,或者大于指定对象,则分贝返回负整数,零数或正整数
- Arrays.sort(xxx xx) 工具类使用了此接口
public class Test{
public static void main(String[] args){
Student[] stus = new Student[]{new Student("张三", 98D), new Student("李四", 99D), new Student("王五", 97D)};
java.util.Arrays.sort(stus);
/*
int n = stus[0].compareTo(stus[1]);
n == 负数 (第一个比第二个小)
n == 零 (二者相等)
n == 正数 (第一个比第二个大)
*/
}
}
//模拟Arrays.sort()一组对象排序
class static void sort(Student students){//硬性要求,必须实现Comparable
for(int i = 0; i < students.lentgth -1; i++){
Comparable c = (comparable)studnts[i];//如果传入的类型没有实现接口中的方法,则会报错
/*
int n = c.compareTo(students[i+1]);//接口的使用者
if(n < 0){
Student temp = students[i];
students[i] = students[i + 1];
students[i+1] = temp;
}
*/
}
}
class Student implements Comparable<Student>{
String name;
int age;
String sex;
double score;
public student(String name, double score){
this.name = name;
this,score = score;
}
//为了使用sort这个工具,被迫要求实现了一个接口,并覆盖了一个方法
public int compareTo(Student s){
if(this.score > s.score){
return 1;
}else if(this.score < s.score){
return -1;
}else{
return 0;
}
}
}
package com.huqi.demo1;
import java.util.Arrays;
public class Test1 {
public static void main(String[] args) {
Student[] student = new Student[]{
new Student("张三",98, 22),
new Student("李四",89, 33),
new Student("王五", 97, 55),
new Student("胡琦",99, 12),
new Student("淑仪",87, 21),
new Student("sue", 76, 22)
};
sort(student);
//重写的系统的方法
//Arrays.sort(student);
for (int i = 0; i < student.length; i++){
System.out.println(student[i]);
}
}
//模拟Arrays.sort()排序
public static void sort(Student[] student){
Comparable comparable;
for (int i = 0; i < student.length - 1; i++){
for(int j = 0; j < student.length-1-i; j++){
comparable = (Comparable)student[j];
int a = comparable.compareTo(student[j+1]);//接口的使用者(抽象)
//进行升序排列
//如果返回正数说明第一个数大于第二个数
//此时将两个数进行交换
if (a > 0){
Student temp = student[j];
student[j] = student[j+1];
student[j+1] = temp;
}
}
}
}
}
class Student implements Comparable<Student>{
String name;
int age;
int score;
public Student(){}
public Student(String name, int score, int age){
this.name = name;
this.score = score;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public int compareTo(Student student) {
//Student student = (Student)o;
// if(this.score > student.score){
// return 1;
// }else if(this.score < student.score){
// return -1;
// }else{
// return 0;
// }
//简化版
//升序排序--按照成绩排序
//return this.score - student.score;
//降序排序
//return -(this.score - student.score);
//按照年龄升序排序
return this.age - student.age;
}
}
6.总结
- 什么是接口
- 微观: 接口是一种能力和约定
- 宏观: 接口是一种标准
- 接口与类的异同:
- 没有构造方法,仅可定义公开静态常量和公开抽象方法
- 接口的应用:
- JAVA为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力
- 接口的规范
- 任何类在实现接口时,必须实现这个接口中的所有抽象方法,否则此类为抽象类
- 实现接口中的抽象方法时,访问修饰符必须为public
- 什么时常量接口
- 将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中同意管理
- 什么是接口回调
- 先有接口的使用者,后有接口的实现者
哥德巴赫猜想习题
class Test{
//工具的使用者
main(){
checkGoldBach(new GoldBash() );//传接口过去
}
//工具
//验证哥德巴赫猜想
//使用接口作为参数,需要使用的时候直接调用传个参数即可
//进行代码分离
public static void checkGoldBach(CheckPrime cp){//要使用这个工具,必须要有一个接口的实现类
//写哥德巴赫猜想的逻辑
int num = 8;
for(int i = 1; i < num; i++){
int a = num - i;
//接口回调
if(cp.isprime(a) && cp.isPrime(i)){
//ok
}
}
}
}
//定义一个标准
//判断是否是质数
interface CheckPrime{
public boolean isPrime(int n){
}
}
//写接口的实现类
class GoldBash implements CheckPrime{
public boolean isPrime(int n){
//进行判断
}
}