• 详解Object类和抽象类


    在这里插入图片描述

    一、抽象类是什么?

    在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
    在这里插入图片描述
    由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
    父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

    二、初始抽象类

    2.1 基本语法

    在 Java 语言中使用 abstract class 来定义抽象类。如下实例:

    abstract class Employee {
        
        //普通的成员属性
        private String name;
        private String address;
    
        //构造方法
        public Employee(String name, String address) {
            this.name = name;
            this.address = address;
        }
    
        //普通的成员方法
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    注意到该 Employee 类没有什么不同,尽管该类是抽象类,但是它仍然有 成员变量,成员方法和 构造方法
    注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法

    public static void main(String[] args) {
            Employee employee = new Employee("zhangsan","shanxi");
        }
    
    • 1
    • 2
    • 3

    代码可以编译通过吗?
    在这里插入图片描述
    我们可以发现抽象类是无法实例化对象的.

    2.2 继承抽象类

    1.抽象方法的权限

    abstract class Shape {
        abstract private void func();
    }
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    抽象类要被继承,需要子类实现抽象方法,所以抽象方法的权限不能是private.
    注意:抽象方法没有加访问限定符时,默认是public.

    abstract class Shape {
        abstract final void func();
    }
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    ** 抽象方法不能被final和static修饰,因为抽象方法要被子类重写**

    先写一个Shape抽象类

    abstract class Shape {
        //被abstract修饰的抽象方法,没有方法体
        abstract public void draw();
        abstract void calcArea();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰

    class Circle extends Shape {
        private double r;
        final private static double PI = 3.14;
    
        public Circle(double r) {
            this.r = r;
        }
    
        @Override
        public void draw() {
            System.out.println("画圆!");
        }
    
        @Override
        void calcArea() {
            System.out.println("面积为: "+PI*r*r);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    public static void main(String[] args) {
            Circle circle = new Circle(2);
            circle.draw();
            circle.calcArea();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    实现父类的抽象方法后,即可正常实例化

    class Rect extends Shape {
        @Override
        public void draw() {
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    子类继承抽象类时,要么把抽象方法全部实现,不然将子类继续抽象化.

    三、抽象类总结

    1.抽象类中必须使用abstract修饰类
    2.抽象类中可以包含普通类所能包含的成员
    3.抽象类和普通类不一样的是:抽象类可以包含抽象方法.
    4.抽象方法使用abstract修饰的,这个方法没有具体的实现
    5.不能实例化抽象类
    6.抽象类最大的意义就是被继承
    7.如果一个普通类继承了一个抽象类,那么必须重写抽象类当中的方法,否则写为抽象类
    8.抽象方法不能是私有的,static?也就是要满足重写的规则
    9.final?不可以它和abstract是矛盾的
    10.抽象类当中可以有构造方法,为了方便子类调用,来初始化类中的成员变量.
    11.抽象类的出现,是为了让程序员更早的发现错误,防止出错,让编译器及时提醒我们.

    四、Object类

    4.1 初始Object

    Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。
    Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。

    class Person {
        
    }
    class Person extends Object {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这两种是一模一样的.
    在这里插入图片描述

    4.2 toString

    Object中的toString方法
    在这里插入图片描述

    public static void main(String[] args) {
            Circle circle = new Circle(2);
            System.out.println(circle);
        }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    我们要打印circle对象具体内容的话,需要重写toString方法.

    public String toString() {
            return "Circle{" +
                    "r=" + r +
                    '}';
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    4.3 equals

    在Java中,进行比较时:
    a.如果双等号左右两侧是基本类型变量,比较的是变量中值是否相同
    b.如果双等号左右两侧是引用类型变量,比较的是引用变量地址是否相同
    c.如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:

    public static void main(String[] args) {
            Circle circle = new Circle(2);
            Circle circle1 = new Circle(2);
            int a = 1;
            int b = 1;
            System.out.println(a == b);
            System.out.println(circle == circle1);
            System.out.println(circle.equals(circle1));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    每次new一个对象都会在堆开辟一个新的空间.
    在这里插入图片描述
    Object定义的equals方法,在两个对象调用时对比的是两个对象地址是否相等,而不是具体对象中的内容这时候我们需要重写equals方法.

     @Override
        public boolean equals(Object obj) {
            if(obj == null) {
                return false;
            }
            if(this == obj) {
                return true;
            }
            if(!(obj instanceof Circle)) {
                return false;
            }
            Circle circle = (Circle)obj;
            return this.r == circle.r;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述
    比较对象中内容是否相同的时候,一定要重写equals方法。

    4.4 hashcode

    在这里插入图片描述
    我们可以发现toString方法中有使用到这个方法,我们目前只需要知道它是一个内存地址,然后调用Integer.toHexString()方法,将这个地址以16进制输出。

    public static void main(String[] args) {
            Circle circle1 = new Circle(2);
            Circle circle2 = new Circle(2);
            System.out.println(circle1.hashCode());
            System.out.println(circle2.hashCode());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    我们认为两个存储相同值的Circle对象,在调用Object的hashcode方法时,输出的值不一样.

    //重写hashCode方法
    @Override
        public int hashCode() {
            return Objects.hash(r);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    当我们重写hashCode后,当两个对象存储的内容一样时,输出的哈希值是一样的.
    结论:
    1、hashcode方法用来确定对象在内存中存储的位置是否相同
    2、事实上hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

  • 相关阅读:
    数据结构——图(图的基本概念)
    Vagrant+VirtualBox+Docker+MySQL+Redis+Nacos
    RabbitMQ之死信队列解读
    GitHub上传本地文件
    自己用操作系统四元素:进程线程管理、内存管理、文件系统和驱动一起拼一个RTOS
    如何实现微服务
    HMI-Board上手指南
    Magento_CentOS安装
    OS模块中获取当前文件的绝对路径的相关方法
    linux安装mysql
  • 原文地址:https://blog.csdn.net/buhuisuanfa/article/details/126425103