java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)

简介: java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)

接口

基本语法

//定义接口类型
interface IAnimal{
    //抽象方法
    // public static final 字段
}

使用interface 定义一个接口

image.png

接口中的方法一定是抽象方法, 因此可以省略 abstract

接口中的方法一定是public, 因此可以省略public

image.png

接口中只能包含抽象方法,对于字段来说, 接口中只能包含静态常量(final static)

interface IAnimal{
    // public static final 字段 可以省略public static final
    String name = "animal"; //因为是final 修饰,需要赋初值!
    int age = 18;
    //抽象方法
    public abstract void speak();
    void eat(); //省略public abstract
}

子类 使用 implements继承接口。 此时表达的含义不再是 “扩展”, 而是 “实现”


在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例。


接口不能单独被实例化。


扩展(extends)vs 实现(implements)


扩展指的是当前已经有一定的功能了, 进一步扩充功能。

实现指的是当前啥都没有, 需要从头构造出来。


接口不能用限定符修饰

image.png

实现多个接口

接口弥补了java无法多继承的缺陷!

我们可以实现多个接口

基本语法


有时候我们需要让一个类同时继承自多个父类. 这件事情在有些编程语言通过 多继承 的方式来实现的。然而 Java 中只支持单继承, 一个类只extends 一个父类。 但是可以同时实现多个接口, 也能达到多继承类似的效果。

class 类名 implement interfa1,interface2,....interfaceN{
     //实现所有接口中的方法!
}

实例一

下面我们通过类来表示张三

//实现多个接口
interface IAnimal{
    String name = "animal";
    int age = 18;
    void speak();
    void eat();
}
interface IPeople{
    String iQ = "140";
    void study();
}
class Zhansan implements IAnimal,IPeople{
    @Override
    public void speak() {
        System.out.println("Speak Chinese!");
    }
    @Override
    public void eat() {
        System.out.println("Eat food!");
    }
    @Override
    public void study() {
        System.out.println("Study java!");
    }
}
public class Test_6 {
    public static void main(String[] args) {
        Zhansan zhansan = new Zhansan();
        zhansan.eat();
        zhansan.speak();
        zhansan.study();
    }
}

image.png

实例二

现在我们通过一个类来表示一组动物。

class Animal { 
  protected String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
}

另外我们再提供一组接口, 分别表示 “会飞的”, “会跑的”, “会游泳的”。

interface IFlying { 
    void fly(); 
} 
interface IRunning { 
    void run(); 
} 
interface ISwimming { 
    void swim(); 
}

接下来我们创建几个具体的动物

猫, 是会跑的。

class Cat extends Animal implements IRunning { 
    public Cat(String name) { 
        super(name); 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用四条腿跑"); 
    } 
}

image.png


鱼, 是会游的。

class Fish extends Animal implements ISwimming { 
    public Fish(String name) { 
        super(name); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在用尾巴游泳"); 
    } 
}

image.png

青蛙, 既能跑, 又能游(两栖动物)

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 + "正在蹬腿游泳"); 
    } 
}

image.png

提示,IDEA中使用 ctrl + i 快速实现接口

image.png


还有一种神奇的动物, 水陆空三栖, 叫做 “鸭子”

class Duck extends Animal implements IRunning, ISwimming, IFlying { 
    public Duck(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 + "正在漂在水上"); 
    } 
}


image.png

上面的代码展示了 Java面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口。


继承表达的含义是 is - a 语义, 而接口表达的含义是 具有xxx 特性 。


猫是一种动物, 具有会跑的特性。

青蛙也是一种动物, 既能跑, 也能游泳

鸭子也是一种动物, 既能跑, 也能游, 还能飞

这样设计有什么好处呢?


时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力!


例如, 现在实现一个方法, 叫 “散步”

public static void walk(IRunning running) { 
    System.out.println("我带着伙伴去散步"); 
    running.run(); 
}

在这个walk方法内部, 我们并不关注到底是哪种动物, 只要参数是会跑的, 就行

Cat cat = new Cat("小猫"); 
walk(cat); 
Frog frog = new Frog("小青蛙"); 
walk(frog);


image.png

甚至参数可以不是 “动物”, 只要会跑


class Robot implements IRunning { 
    private String name; 
    public Robot(String name) { 
        this.name = name; 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用轮子跑"); 
    } 
} 
Robot robot = new Robot("机器人"); 
walk(robot);

image.png


接口的使用实例

我们java系统包中的很多类都实现了很多接口,使得该类具有某种属性


给对象排序!

//创建student类
class Student{
    private String name;
    private double score;
    public Student(String name,double 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("张三",88.7),
                new Student("李四",67),
                new Student("王五",98),
        };
        Arrays.sort(students); //排序
        System.out.println(students);
    }

显然,我们无法排序对象类型的数据,

报异常,说我们Student类没有实现Comparable接口!

image.png

Comparable接口中的抽象方法 compareTo

方法详细信息


int compareTo(T o)将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。


实现程序必须确保sgn(x.compareTo(y)) == -sgn(y.compareTo(x))所有x和y。 (这意味着x.compareTo(y)必须抛出异常if y.compareTo(x)引发异常。)


实施者还必须确保关系是可传递的: (x.compareTo(y)>0 && y.compareTo(z)>0)表示x.compareTo(z)>0。


最后,实施者必须确保x.compareTo(y)==0意味着sgn(x.compareTo(z)) == sgn(y.compareTo(z)) ,对于所有z 。


强烈建议,但不要严格要求(x.compareTo(y)==0) == (x.equals(y)) 。 一般来说,任何实现Comparable接口并违反这种情况的类应清楚地表明这一点。 推荐的语言是“注意:此类具有与equals不一致的自然排序”。


在前面的描述中,符号sgn( ) 表达式表示数学符号函数,其定义根据表达式的值是否为负,零或正返回的-1一个,0,或1。


参数

o -要比较的对象。

结果

负整数,零或正整数,因为该对象小于,等于或大于指定对象。

异常

NullPointerException- 如果指定的对象为空

ClassCastException- 如果指定的对象的类型阻止它与该对象进行比较。


看到这么多文字,是不是头都大了!

没有关系,bug郭也头大,不过我知道咋用

//创建student类并且实现Comparable接口
class Student implements Comparable{
    private String name;
    private double score;
    public Student(String name,double score){
      this.name = name;
      this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
    @Override  //实现compareTo方法
    public int compareTo(Object o) {
        Student s = (Student)o; //对o强转, o指的是待比较对象
        if (this.score > s.score) {    //当前对象的score值大
            return -1;
        } else if (this.score< s.score) { //对象o的score值大
            return 1;       
        } else {
            return 0;
        }
    }
}

我们可以看到,这时排的升序,如果要降序就只需将大于号变成小于号即可!

image.png

在 sort 方法中会自动调用compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student类型的对象.

然后比较当前对象和参数对象的大小关系(按分数来算).

如果当前对象应排在参数对象之前, 返回小于0 的数字;

如果当前对象应排在参数对象之后, 返回大于 0 的数字;

如果当前对象和参数对象不分先后, 返回0;


注意事项: 对于 sort 方法来说, 需要传入的数组的每个对象都是 “可比较” 的, 需要具备compareTo这样的能力. 通过重写compareTo 方法的方式, 就可以定义比较规则。

为了进一步加深对接口的理解, 我们可以尝试自己实现一个sort方法来完成刚才的排序过程(使用冒泡排序)!


public static void sort(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; 
            } 
        } 
    } 
}

image.png


接口间的继承

接口可以继承一个接口, 达到复用的效果. 使用extends关键字!

interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
    @Override
    public void run() {
        System.out.println("Frog run!");
    }
    @Override
    public void swim() {
        System.out.println("Frog swim!");
    }
}
public class Test_1 {
    public static void main(String[] args) {
           Frog frog = new Frog();
           frog.run();
           frog.swim();
    }
 }

image.png


通过接口继承创建一个新的接口 IAmphibious 表示 “两栖的”. 此时实现接口创建的 Frog类, 就继续要实现 run 方法,也需要实现 swim方法!


接口间的继承相当于将多个接口合并在一起!



目录
相关文章
|
14天前
|
Java API
Java中内置的函数式接口
Java中内置的函数式接口
19 2
|
18天前
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
55 1
|
18天前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
35 1
|
18天前
|
Java
在Java中实现接口的具体代码示例
可以根据具体的需求,创建更多的类来实现这个接口,以满足不同形状的计算需求。希望这个示例对你理解在 Java 中如何实现接口有所帮助。
32 1
|
7月前
|
Java
java面向对象——包+继承+多态(一)-2
java面向对象——包+继承+多态(一)
45 3
|
7月前
|
SQL Java 编译器
java面向对象——包+继承+多态(一)-1
java面向对象——包+继承+多态(一)
40 2
|
存储 Java C语言
Java面向对象进阶5——包和final(含源码阅读)
包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护
103 0
Java面向对象进阶5——包和final(含源码阅读)
|
存储 Java
Java SE基础知识详解第[8]期—面向对象进阶(包、权限修饰符、抽象类、接口)
Java SE基础知识详解第[8]期—面向对象进阶(包、权限修饰符、抽象类、接口)
Java SE基础知识详解第[8]期—面向对象进阶(包、权限修饰符、抽象类、接口)
|
12天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####