javase-12.续上篇接口

2.5实现多个接口

Java 中,类和类之间是单继承的,一个类只能有一个父类,即 Java 中不支持多继承 ,但是 一个类可以实现多个接 。下面通过类来表示一组动物 .
public abstract class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public abstract void eat();
}
public interface IRunning {
    void run();
}
public interface ISwimming {
    void swim();
}
public interface IFlying {
    void fly();
}
public class Dog extends Animal implements IRunning,ISwimming{
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃狗粮!");
    }

    @Override
    public void run() {
        System.out.println(name+"用狗腿在跑");
    }

    @Override
    public void swim() {
        System.out.println(name+"用狗腿游泳");
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Bird extends Animal implements IRunning,IFlying{

    public Bird(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃鸟粮");
    }

    @Override
    public void fly() {
        System.out.println(name+"用翅膀飞");
    }

    @Override
    public void run() {
        System.out.println(name+"用鸟腿跑");
    }
}
public class Test {

    public static void test1(Animal animal) {
        animal.eat();
    }

    public static void test2(IRunning iRunning) {
        iRunning.run();
    }

    public static void test3(ISwimming iSwimming) {
        iSwimming.swim();
    }

    public static void test4(IFlying iFlying) {
        iFlying.fly();
    }

    public static void main(String[] args) {
        test1(new Dog("狗",4));
        test2(new Dog("狗",4));
        test3(new Dog("狗",4));

        System.out.println("=====================");

        test1(new Bird("鸟",2));
        test2(new Bird("鸟",2));
        test4(new Bird("鸟",2));
    }
}
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类
上面的代码展示了 Java 面向对象编程中最常见的用法 : 一个类继承一个父类 , 同时实现多种接口

2.6接口间的继承

Java 中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。
接口可以继承一个接口 , 达到复用的效果 . 使用 extends 关键字 .
public interface IRunning {
    void run();
}
public interface ISwimming {
    void swim();
}
public interface IFlying extends IRunning,ISwimming{
    void fly();
}//继承了两个接口还可以有自己的接口

2.7抽象类的接口的区别(面试题)

1.接口中的成员都被public static final修饰,而抽象类中的可以有普通成员.

2.接口中的方法默认被public abstract修饰,而抽象类中的方法可以是抽象的也可以是非抽象的.

3.一个类可以继承一个类并执行多个接口,接口之间只有extends关系.

2.8接口使用实例

给对象数组排序实例:

实例化两个学生对象,比较大小并将其排序.

按照我们之前的理解, 数组我们有一个现成的 sort 方法,sort依据数值大小可以排序,但不能用来排两个学生的顺序,学生的大小关系需要我们额外指定变量(名字长度,年龄大小还是身高等等).

我们先来比较学生对象的大小,再利用冒泡排序排好

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) {

        /*法一:
        if(this.age > o.age) {
            return 1;
        }else if(this.age < o.age) {
            return -1;
        }else {
            return 0;
        }*/
        //法二:
        return this.age - o.age;
    }
}
//比较年龄大小
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 Test {
public static void bubbleSort(Comparable[] comparable) {
    for (int i = 0; i < comparable.length - 1; i++) {
        NameComparator nameComparator = new NameComparator();
        for (int j = 0; j < comparable.length - 1 - i; j++) {
            if(nameComparator.compare((Student) comparable[j], (Student)comparable[j+1]) > 0) {
                Comparable tmp = comparable[j];
                comparable[j] = comparable[j+1];
                comparable[j+1] = tmp;
            }
        }
    }
}
public static void main(String[] args) {
    Student student1 = new Student("zhangsan",10);
    Student student2 = new Student("lisi",15);

    System.out.println(student1);
    System.out.println(student2);
    System.out.println("===============");

    System.out.println(student1.compareTo(student2));

    Student[] student = new Student[3];
    student[0] = new Student("zhangsan",10);
    student[1] = new Student("lisi",2);
    student[2] = new Student("wangwu",18);

    bubbleSort(student);
    System.out.println(Arrays.toString(student));

  }
}

2.9Clonable接口和深浅拷贝

Java 中内置了一些很有用的接口 , Clonable 就是其中之一 .
Object 类中存在一个 clone 方法 , 调用这个方法可以创建一个对象的 " 拷贝 ". 但是要想合法调用 clone 方法 , 必须要 先实现 Clonable 接口 , 否则就会抛出 CloneNotSupportedException 异常 .
我想拷贝一份person对象,但发现clone方法不能直接调用.如下:
class Person {
    int age;

    public Person(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
}
public class Test2 {
    public static void main(String[] args) {
        Person person1 = new Person(3);
        Person person2 = person1.clone();

    }
}

在person类当中重写clone方法:

class Person {
    int age;

    public Person(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test2 {
    public static void main(String[] args) {
        Person person1 = new Person(3);
        Person person2 = person1.clone();//仍就调用不了clone方法
    }
}

分析解决:

正确代码:

class Person implements Cloneable{
    int age;

    public Person(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(3);
        Person person2 = (Person)person1.clone();
    }
}

那么什么是浅拷贝呢?

在上述代码的基础上我定义一个类Money,在这个类中定义成员money = 14.3.

class Person implements Cloneable{
    int age;
    public Money m;
    public Person(int age) {
        this.age = age;
        this.m = new Money();
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

//克隆方法在Object当中,并且由protected修饰,所写类默认继承Object类
//protected:不同包中的子类.同时使用时,需要super调用
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(3);
        Person person2 = (Person)person1.clone();
        System.out.println(person1.m.money);//14.3
        System.out.println(person2.m.money);//14.3
        System.out.println("=========================");
        person2.m.money = 99.0;
        System.out.println(person1.m.money);//99.0
        System.out.println(person2.m.money);//99.0
//person2.m.money = 99.0;这句代码原本应该是只改变person2.m.money的值,但是person1也改变了
    }
}

原因:

那怎么实现只改变person2中的money值?代码如下:

class Person implements Cloneable{
    int age;
    public Money m;
    public Person(int age) {
        this.age = age;
        this.m = new Money();
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
        tmp.m = (Money)this.m.clone();//克隆的返回值类型为Object需要强转
        return tmp;
    }
}

//克隆方法在Object当中,并且由protected修饰,所写类默认继承Object类
//protected:不同包中的子类.同时使用时,需要super调用
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(3);
        Person person2 = (Person)person1.clone();
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
        System.out.println("=========================");
        person2.m.money = 99.0;
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
    }
}

3.Object类

//双击shift 搜Object
Object Java 默认提供的一个类。 Java中, Object 类是所有类的父类(哪怕没有写明extends Object),默认会继承 Object 父类。即所有类的对象都可以使用Object 的引用进行接收。
代码示例:
class Person{

}

class Student{

}



public class Test {
    public static void main(String[] args) {
        function(new Person());
        function(new Student());
    }

    public static void function(Object obj) {
        System.out.println(obj);
    }
}

//执行结果:

Person@1b6d3586
Student@4554617c

对于整个Object类中的方法需要实现全部掌握。

3.2获取对象信息

如果要打印对象中的内容,可以直接重写 Object 类中的 toString() 方法,
class Person{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

//1.重写了父类Object中的toString方法,
 2.System.out.println(person);person处,父类引用,调用的是子类对象,最终成功打印出想要的子类(向上转型)
发生了动态绑定

     @Override
   public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person("小吴",21);
        System.out.println(person);
    }
}

3.3对象比较equals方法

Java 中, == 进行比较时:
a. 如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
b. 如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
c.如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:
当比较对象为引用类型对象并且不止一个时:
class Person{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

     @Override
   public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("小吴",21);
        Person person2 = new Person("小吴",21);
        System.out.println(person1);
        System.out.println(person2);
        /*Object中,equals的方法为:
        public boolean equals(Object obj) {
        return (this == obj);
    }*/
        System.out.println(person1 == person2);
        System.out.println(person1.equals(person2));
        //所以在子类还未重写equals方法时,上述两行代码是一样的,无法正确比较
        System.out.println("重写equals方法后:");
        System.out.println(person1.equals(person2));//得到正确的比较结果
    }
}
结论:比较对象中内容是否相同的时候,一定要重写 equals 方法。
  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值