7. 面向对象编程(中级)

8. 面向对象编程(中级)

8.1 包和访问修饰符

8.1.1 包的基本语法

image-20210801200102755

包的本质,实际上就是创建不同的文件夹/目录来保存类文件。

例子:

package com.forever.win.anomaly

import java.util.Arrays;
  
8.1.1.1 包的命名

image-20210801200202159

8.1.2 访问修饰符

image-20210801200421481

8.2 面向对象编程的三大特性(重点)

基本介绍

面向对象编程的三大特性:封装、继承和多态。

8.2.1 封装

封装(encapssulation)就是把抽象出的数据**[属性]**和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。

8.2.1.1 封装的实现步骤

隐藏实现细节,仅对外暴露公共的访问方式。

image-20210801201158670

8.2.2 继承

image-20210804073347927

继承的基本语法
class 子类 extends 父类{
  
}
(1) 子类就会自动拥有父类定义的属性和方法
(2) 父类又叫超类,基类。
(3) 父类又叫派生类。
继承给编程带来的便利
  1. 代码的复用性提高了
  2. 代码的扩展性和维护性提高了
继承的细节(重点)
  1. 子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,如果子类和父类不在同一个包下面的话,默认的访问修饰符也不能直接访问,要通过父类提供公共的方法去访问。
  2. 子类必须调用父类的构造器,完成父类的初始化。
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作。否则,编译不会通过。
  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
  5. super构造器在使用时,必须放在构造器的第一行
  6. super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器。
  7. java所有类都是Object类的子类,Object类是所有类的基类。
  8. 父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
  9. 子类最多只能继承一个父类(指直接继承),即java中是单继承机制。
  10. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系,is-a,即什么是一个什么,比如说猫是动物,即猫类可以继承动物类。

super关键字

  1. 访问父类的属性,但是不能访问父类的private属性,如果不在同一个包下,父类的默认属性也不能访问,super.属性名
  2. 访问父类的方法,不能访问父类的private方法
  3. 访问父类的构造器
  4. super(参数列表);只能放在构造器的第一句,只能出现一句。

image-20210805073340076

super和this 的比较

image-20210805073427405

方法重写@Override

使用细节
  1. 子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样
  2. 子类的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类,比如父类返回类型是Object,子类方法返回类型可以是String
  3. 子类方法不能缩小父类方法的访问权限
    1. public > protected > 默认 > private
  4. image-20210810064425380
  5. 子类重写父类的方法时,所抛出的异常要么和父类抛出的异常一致,要么为父类抛出异常类型的子类型

8.2.3 多态

  1. 一个对象的编译类型可以和运行类型不一致。
  2. 编译类型在定义对象时,就确定了,不能改变。
  3. 运行类型是可以改变的。
  4. 编译类型看定义时 = 号的左边,运行类型看 = 的右边。
  5. image-20210815171312130
多态的向上转型
  1. 多态的本质就是父类的引用指向了子类的对象。
  2. 语法 父类类型 引用名 = new 子类类型()。
  3. 特点:编译类型看左边,运行类型看右边。
  4. 可以调用父类中的所有成员(需遵守访问权限)
  5. 不能调用子类中的特有成员。
  6. 最终运行效果看子类的具体实现。
多态的向下转型
  1. 语法:子类类型 引用名 = (子类类型) 父类引用。

  2. 只能强转父类的引用,不能强转父类的对象

  3. 要求父类的引用必须指向的是当前目标类型的对象。

    1. Animal animal = new Cat();
      Cat cat = (Cat) animal;//正确
      Dog dog = (Dog) animal;//错误
      
  4. 当向下转型后,可以调用子类类型中的所有的成员。

重点:
public class Properties {
    public int a = 1;
    public Properties(int a){
        this.a = a;
    }

    public static void main(String[] args) {
        Properties properties = new C(45);

        //属性没有重写之说!属性的值看编译类型,即properties
        //所以输出1,但是可以用构造器来初始化父类属性的参数,所以输出45
        //如果该编译类型没有该属性的话,就会报错
        System.out.println(properties.a);
    }
}

class C extends Properties{
    public int a = 2;

    public C(int a){
        super(a);
    }
}
class D extends Properties{
    public int a = 3;

    public D(int a){
        super(a);
    }
}

instanceOf

instanceOf 比较操作符,用于判断对象的运行类型(看右边)是否为XX类型或者是XX类型的子类型

动态绑定机制(运行时绑定)

  1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定。

  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。即该属性的值是看编译类型

    package dynamicBinding;
    
    /**
     * @Description TODO
     * @Author zhaojiawei
     * @Since 2021-08-15
     */
    public class DynamicBinding {
        public static void main(String[] args) {
            A a = new B();
    
            //10,会调用编译类型的属性,因为属性没有动态绑定机制,如果删除了A对象属性n,则会报错,但是也可以强制调用其子类B对象的属性,如:((B) a).n
            System.out.println(a.n);
    
            //30 因为方法有动态绑定机制,所以会调用B的getN方法
            System.out.println(a.get());
        }
    }
    
    class A {
        int n  = 10;
        public int say(){
            return n;
        }
        public int get(){
            return n + getN();
        }
        public int getN(){
            return n;
        }
    }
    
    class B extends A{
        int n = 20;
    
        @Override
        public int say(){
            return n;
        }
    //    public int get(){
    //        return n + getN();
    //    }
        @Override
        public int getN(){
            return n;
        }
    
    }
    
    

==和equals详解

  1. ==:既可以判断基本类型,也可以判断引用类型
  2. ==:如果判断基本类型,判断的是值是否相等。
  3. ==:如果判断引用类型,判断的是地址是否相等,即判断是不是同一个对象。

image-20210924075800695

HashCode

  1. 提高具有哈希结构的容器的效率
  2. 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的。
  3. 两个引用,如果指向的是不同的对象,则哈希值肯定是不一样的
  4. hashCode一般是通过对象的内部地址经过hash算法转换成一个整数来实现的,因为java是跑在虚拟机上的,找不到对象的内部地址(实际地址)。

toString()

基本介绍

默认返回:全类名+@+哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息。

当直接输出一个对象是,toString方法默认会被调用

finallize()

  1. 当垃圾回收器确定该对象没有指向它的引用时,由对象的垃圾回收器调用此方法。
  2. 什么时候回收:当某个对象没有任何引用的时候,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法。我们可以重写Object里面的finilize方法来写自己的业务逻辑(比如释放资源等)
  3. 垃圾回收机制的调用,是由系统来决定的(即有自己的GC算法),也可以通过**System.gc()**主动触发垃圾回收机制。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值