栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java笔记——08.面向对象(中级)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java笔记——08.面向对象(中级)

08.面向对象(中级)
常用IDEA快捷键(有部分自行定义)

删除当前行:ctrl+D

复制当前行至下一行:ctrl+Y

补全代码:alt+/

添加注释和取消注释:ctrl+/

导入该行需要的类:alt+enter

快速格式化代码:ctrl+alt+L

快速运行程序:alt+R

生成构造方法:alt+insert

查看一个类的层级关系:ctrl+H

定位到具体的方法:ctrl+B

自动分配变量:alt+enter .var


修饰符
本类同包子类不同包
public
protected
默认
private

封装

小技巧:可以将构造器和setXxx结合,在构造器中调用setXxx方法


继承
  • 子类继承了所有的属性和方法,但是私有属性不能在子类中直接访问,要通过父类提供的公共方法去访问

  • 子类必须调用父类的构造器,完成父类的初始化

  • 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过

  • 如果希望指定去调用父类的某个构造器,则显示的调用一下:super(参数列表 )

  • super在使用时,需要放在构造器的第一行

  • super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

  • java所有类都是Object类的子类,Object类是所有类的基类

  • 父类构造器的调用不限于直接父类,将一直往上追溯直到Object类(顶级父类)

  • 子类最多只能继承一个父类(指直接继承),即java中是单继承机制

  • 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系


继承本质详解

视频地址:https://www.bilibili.com/video/BV1fh411y7R8?p=294

继承的本质就是建立查找关系


方法重写
  • 子类的方法的参数、方法名称要和父类方法的参数、方法名称完全一样

  • 子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类

  • 子类方法不能缩小父类方法的访问权限(public > protested > 默认 > private)


重载(overload)和重写(override)比较

发生范围:本类;父子类

方法名:必须一样;必须一样

形参列表:类型、个数或者顺序至少有一个不同;相同

返回类型:无要求;子类重写的方法,返回的类型和父类返回的类型一致或者是其子类

修饰符:无要求;子类方法不能缩小父类方法的访问权限


多态

方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承的基础之上的。

多态的前提是两个对象(类)存在继承关系。

  • 方法的多态:

    重写和重载就体现多态

  • 对象的多态(核心):

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象时,就确定了,不能改变
  3. 运行类型是可以变化的
  4. 编译类型看定义时 = 号 的左边,运行类型看 = 号 的右边
//Animal类是父类,Dog类和Cat类是子类
Animal animal = new Dog();//animal编译类型是Animal,运行类型是Dog
animal = new Cat();//animal的运行类型变成了Cat,编译类型仍然是Animal

//例如Animal中有一个cry方法,Dog类中进行了重写
animal.cry();//因为运行时,执行到该行时,运行类型是Dog,所以cry是Dog中的cry

打个比方,便于理解:披着羊皮的狼。

表面上看像一只羊,但实际上他是一只狼。羊就好比是编译类型,而狼是运行类型。编译器看到的是编译类型,真正干活的时候是运行类型。


多态的向上转型

本质:父类引用指向子类对象

语法:父类类型 引用名 = new 子类类型();

特点:

  • 编译类型看左边,运行类型看右边
  • 可以调用父类中的所有成员(需遵守访问权限)
  • 不能调用子类中特有成员
  • 最终运行效果看子类的具体实现!!!
//Cat类中有个特有的抓老鼠方法catchMouse(),但是下面的写法不能调用
//因为在编译阶段,能调用哪些成员,是由编译类型来决定的
animal.catchMouse();//会报错

编译的时候是javac来执行的,到了运行阶段是java来执行的,java不关心你的编译类型。(本质上还是一开始的基础,先编译再运行,编译的时候按照编译类型Animal来看,等到运行的时候再按照运行类型Cat来看)

不能理解的,可以看视频地址:https://www.bilibili.com/video/BV1fh411y7R8?p=310


多态的向下转型

语法: 子类类型 引用名 = (子类类型)父类引用;

特点:

  • 只能强转父类的引用,不能强转父类的对象
  • 要求父类的引用必须指向的是当前目标类型的对象
  • 当向下转型后,可以调用子类类型中所有的成员
//cat此时的编译类型和运行类型是什么呢?
Cat cat = (Cat) animal;//编译类型是Cat,运行类型也是Cat
cat.catchMouse();//成功

//“要求父类的引用必须指向的是当前目标类型的对象”,怎么理解这句话呢?
//例子
Animal animal = new Dog();
Dog dog = (Dog) animal;//正确
Cat cat = (Cat) animal;//错误
//因为animal本质上就是Dog,所以转成Dog不犯错,但是下面这句话就相当于是把一只狗转换成一只猫
//当然错误,编译时不报错,运行时会报错,会报 类型转换异常

多态注意事项和细节讨论

属性没有重写之说,属性的值看编译类型

A instanceof B 比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型(A是否是B类型或者是其子类型)

//例如有两个类,Sub类继承base类,都有count属性
class base {
    int count = 10;
}
class Sub extends base {
    int count = 20;
}
//在main方法中调用属性,输出的是哪一个呢
base base = new Sub();
System.out.println(base.count);//输出的是10
//因为count是属性,属性看编译类型,注意和上面方法调用的比较

//定义AA类和BB类,BB类继承AA类
class AA {}
class BB extends AA {}
//下面的判断是真还是假
BB bb = new BB();
System.out.println(bb instanceof BB);//true
System.out.println(bb instanceof AA);//true

动态绑定机制
  • 当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定
  • 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
//父类
class A {
    
    public int i = 10;
    
    public int sum() {
        return getI() + 10;
    }
    
    public int sum1() {
        return i + 10;
    }
    
    public int getI() {
        return i;
    }
}

//子类
class B extends A {
    
    public int i = 20;
    
//    public int sum() {
//        return getI() + 20;
//    }
    
//    public int sum1() {
//        return i + 20;
//    }
    
    public int getI() {
        return i;
    }
}

//main方法中
//请问输出什么?
A a = new B();
System.out.println(a.sum());//30
System.out.println(a.sum1());//20

解析

  • a.sum():首先因为运行类型是B,所以调用B中的sum()方法,但是B中的sum()方法注释掉了,所以向上找到A中的sum()方法,发现A中的sum()方法可用,于是调用它,然后发现里面又调用了getI()方法,根据动态绑定机制,这个getI()方法调用的是B中的getI()方法,所以最终返回30
  • a.sum1():和a.sum()类似,但由于返回的是i + 10,i是属性,不是方法,所以没有动态绑定机制,于是调用的就是A中的i,所以最终返回20

多态应用

多态数组

//Person是父类,Student和Teacher是它的子类
//Person有属性姓名name和年龄age,Student有特有的属性成绩score,Teacher有特有属性工资sal
//创建多态数组,都是向上转型,父类引用指向子类对象
Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("marry", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);

//如何调用子类特有的方法?
//常用方法:利用instanceof
for(int i = 0; i < persons.length; i++) {
    
    //调用公有方法
    
    if(persons[i] instanceof Student) {
        //Student特有方法
    }else if(persons[i] instanceof Teacher) {
        //Teacher特有方法
    }else{
        //......
    }
}

多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型


Object类详解 equals方法

==和equals的对比

==是一个比较运算符

  • 既可以判断基本类型,又可以判断引用类型
  • 如果判断基本类型,判断的是值是否相等
  • 如果判断引用类型,判断的是地址值是否相等,即判断是不是同一个对象

equals是Object类中的方法,只能判断引用类型,但经常在子类中会重写equals方法,用来比较对象的值是否相等

强烈建议:使用ctrl+B查看源码,可以理解的更加透彻,查看源码对能力的提升有很大帮助


hashCode方法
  • 提高具有哈希结构的容器的效率
  • 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的
  • 两个引用,如果指向的是不同的对象,则哈希值是不一样的(不绝对)
  • 哈希值主要根据地址来的,但不能完全将哈希值等价于地址
  • 在集合中hashCode如果有需要的话,也会重写

toString方法
  • 默认返回:全类名+@+哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息
  • 重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString方法
  • 当直接输出一个对象时,toString方法会被默认调用
//Object的toString()方法的源码
//getClass().getName() 类的全类名(包名+类名)
//Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

//当直接输出一个对象时,toString方法会被默认调用
//比如下面这句话就会默认调用monster.toString()
System.out.println(monster);

finalize方法
  • 当对象被回收时,系统自动调用该对象的finalize方法,子类可以重写该方法,做一些释放资源的操作
  • 什么时候被回收:当某个对象没有任何引用时,jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法
  • 垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制(不一定立刻生效)

注意:对于finalize方法了解即可,因为实际开发中,几乎不会使用。


断点调试

重要提示:在断点调试过程中,是运行状态,是以对象的运行类型来执行的

IntelliJ IDEA断点调试如何查看源码:https://blog.csdn.net/qq_43544021/article/details/120633420?spm=1001.2014.3001.5501

**强烈建议:**可以经常进行断点调试,除了检查错误,更重要的是可以对Java的源码,运行机制等等知识点有更深入的理解(尤其是继承,多态这里,看源码真的很重要),而且不只是系统的源码,也可以看看人家高手大佬的代码,提高自己。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/307138.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号