JavaSE学习之--抽象类,接口,内部类(二)

简介: JavaSE学习之--抽象类,接口,内部类(二)

JavaSE学习之--抽象类,接口,内部类(一)+https://developer.aliyun.com/article/1413496

8.在jdk8中:接口还可以包含default方法

  我们知道接口中的方法都是抽象方法,不含有主体,但在jdk8中引入了一个新特性-->default关键字,在接口中,如果方法被default修饰,则此方法可以含有主体,且在类中不必须被重写(相当于自动继承了)

interface IUSB {
    void method1();
    default void method2() {
        System.out.println("This is a default method!");
    }
}
class Mouse implements IUSB {
    @Override
    public void method1() {
        System.out.println("hehe");
    }
    // method2不重写也不会报错
    // 相当于“自动继承”
}
public class Test1 {
    public static void main(String[] args) {
        Mouse mouse = new Mouse();
        mouse.method1();
        // 没有重写method2,也能调用该方法,证明该方法被“自动继承”了
        mouse.method2();
    }
}

4.实现多接口

 Java中类是单继承的,一个类无法继承多个类(不能有多个父亲),但可以同时实现多个接口!

通过implements+','实现多个接口!!!

下面通过类来表示一组动物

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

另外提供一些接口,分别表示 "会飞的", "会跑的", "会游泳的".

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

猫类:跑

// 猫类
class Cat extends Animal implements IRunning {
    public Cat(String name) {
        super(name);
    }
    // ctrl+i快速调出接口抽象方法的重写
    @Override
    public void run() {
        System.out.println(this.name + "猫正在跑步");
    }
}

狗类:跑,游

// 狗类 跑+游
class Dog extends Animal implements IRunning,ISwimming {
    public Dog(String name) {
        super(name);
    }
    @Override
    public void swim() {
        System.out.println(this.name + "正在狗刨");
    }
    @Override
    public void run() {
        System.out.println(this.name + "狗正在跑步");
    }
}

鸭子类:跑,游,飞

// 鸭子类 跑,飞,游
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 swim() {
        System.out.println(this.name + "鸭子正在游泳");
    }
    @Override
    public void run() {
        System.out.println(this.name + "鸭子正在跑步");
    }
}

注意:一个类实现多个接口时,所有接口中的抽象方法都要被重写!!!

public class Test1 {
    public static void main(String[] args) {
        Dog dog = new Dog("mimi");
        dog.run();
        dog.swim();
        System.out.println("================");
        Cat cat = new Cat("jiji");
        cat.run();
        System.out.println("================");
        Duck duck = new Duck("hehe");
        duck.fly();
        duck.run();
        duck.swim();
    }
}

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

可以理解为接口时“部分共性”,但本质还是为了代码复用

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

  • 猫是一种动物, 具有会跑的特性.
  • 狗也是一种动物, 既能跑, 也能游泳
  • 鸭子也是一种动物, 既能跑, 也能游, 还能飞

这样做的好处是可以让程序员忘记类型,只关注实现特性,关注某个类是否具有该特性

比如我们可以创建一个Robot类,他也可以实现IRunning接口,尽管他不是Animal类!

class Robot implements IRunning {
    @Override
    public void run() {
        System.out.println("the robot is running!");
    }
}

创建一个方法调用接口中的方法(接口作为参数)

public class Test1 {
    // 接口和类一样,可以作为参数类型,当对象传递时发生动态绑定
    // 谁实现了接口,谁就可以调用接口方法
    public static void Run(IRunning running) {
        running.run();
    }
    public static void main(String[] args) {
        // 匿名对象的直接调用
        Run(new Cat("jiji"));
        Run(new Dog("mimi"));
        Run(new Duck("hehe"));
        Run(new Robot());
    }

5.接口之间的继承

 接口之间也存在继承关系,不同于类的是,一个接口可以继承多个接口

interface IRunning {
    void run();
}
interface ISwimming {
    void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
...
}

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

6.抽象类和接口的区别:

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

2.方法:抽象类中既可以有抽象方法也可以有普通方法,而接口中所有的方法都是public abstract修饰

3.继承关系:一个类只能继承一个父类,但可以实现多个接口。但接口与接口之间只有继承关系

 

三. Object类

 Object类是Java中默认提供的一个类,他是所有类的父类,是类的“祖先”。为什么会有这么一个类呢?其实也很好理解,Java是一个面向对象编程的语言,它存在很多自定义的类,那程序员是如何写出这些自定义的类呢?本质上还是通过Object这个祖先类来开发的!!!

1.Object可以接受任意类型的对象

class Person{};
class Stu{};
public class Test1 {
    // 此处发生了向上转型
    public static void func(Object object) {
        System.out.println(object);
    }
    public static void main(String[] args) {
        func(new Person());
        func(new Stu());
    }
}

2.Object本质上还是Java中的一个类,含有一些自带的方法

 

本文主要讲解equals,hashcode,toString方法

1.toString方法--获取对象信息

   前面我们已经重写了很多toString方法,当时可能很不理解为什么toString方法要重写呢?他是来源于哪个类呢?现在可以解释这个问题了,toString方法是Object类自带的一个方法,所有的类都是Object的子类,所以要重写toString方法来实现我想获取的信息

toString的源码

2.equals方法--进行对象比较

 在Java中,==比较时

如果左右两侧是基本数据类型(int等等),直接比较值的大小即可

如果左右两侧是引用数据类型(比如对象),实际上比较的是引用类型的地址是否相同

如果想比较对象中的内容,就要重写equals方法

equals的源码:

public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
        // 当两个引用类型比较时,实际上比较的是地址
        System.out.println(10 == 20);// false
        System.out.println(person1 == person2);// false
        System.out.println(person1.equals(person2));// false
        System.out.println("=======================");
        person2 = person1;
        System.out.println(person1.equals(person2));// true
    }

两个对象的比较是判断对象的地址是否相同,也即是在内存中存储的位置是否相同

Person person1 = new Person("lisi",18);
        Person person2 = new Person("lisi",18);
        System.out.println(person1.toString());
        System.out.println(person2.toString());

可以看出,两个对象的地址不同

重写equals方法 :

假如我想使用Person类中的age来判断两个对象是否相同,此时就要重写equals方法

class Person{
    int age;
    public Person(int age) {
        this.age = age;
    }
    @Override
    public boolean equals(Object object) {
        // 两个对象地址相同,直接返回true
        if (this == object) return true;
        // 比较的对象是null或两个对象的类型不同,直接返回false
        if (object == null || getClass() != object.getClass()) return false;
        // 此处进行向下转型
        Person person = (Person) object;
        return age == person.age;
    }
    @Override
    public int hashCode() {
        return Objects.hash(age);
    }
}
public class Test1 {
    public static void main(String[] args) {
        Person person1 = new Person(10);
        Person person2 = new Person(20);
        Person person3 = new Person(20);
        System.out.println(person1.equals(person2));// false
        System.out.println(person2.equals(person3));// true
    }

注意:可以通过快捷键快速生成toString和hashcode的重写方法

结论:通过对象中的内容进行比较时,一定要重写toString方法!


JavaSE学习之--抽象类,接口,内部类(三)+https://developer.aliyun.com/article/1413501

目录
相关文章
【JavaSE专栏64】抽象类和接口,不能被实例化的类有什么用?
【JavaSE专栏64】抽象类和接口,不能被实例化的类有什么用?
199 0
|
6月前
|
安全 Java
JavaSE&匿名对象 , 继承 , 抽象类
JavaSE&匿名对象 , 继承 , 抽象类
18 0
|
6月前
|
Java
JavaSE学习之--抽象类,接口,内部类(一)
JavaSE学习之--抽象类,接口,内部类(一)
87 0
|
6月前
|
存储 Java 编译器
JavaSE学习之--抽象类,接口,内部类(三)
JavaSE学习之--抽象类,接口,内部类(三)
39 0
|
6月前
|
Java 编译器
JavaSE学习之--继承和多态(三)
JavaSE学习之--继承和多态(三)
62 0
|
6月前
|
Java 编译器
JavaSE学习之--继承和多态(一)
JavaSE学习之--继承和多态
62 0
|
6月前
|
Java
JavaSE学习之--继承和多态(二)
JavaSE学习之--继承和多态(二)
69 0
|
6月前
|
Java 编译器
【Java 抽象类&抽象方法】什么是抽象类&方法,如何定义,起什么作用?
【Java 抽象类&抽象方法】什么是抽象类&方法,如何定义,起什么作用?
|
11月前
|
Java 编译器
JavaSE抽象类和接口
JavaSE抽象类和接口
|
11月前
|
安全 Java 程序员
JavaSE继承和多态
JavaSE继承和多态