【韩顺平Java】Java OOP 学习笔记【上】

面向对象编程 (上)

Java网课:韩顺平 零基础30天学会Java

1. 封装

封装的实现步骤

  1. 将属性进行私有化 private【不能直接修改属性】
  2. 提供一个公共的(public)set方法,用于对属性判断并赋值
public void setXxx(/*类型 参数名*/){ // Xxx表示某个属性
        // 加入数据验证的业务逻辑
        // 属性 = 参数名;
}
  1. 提供一个公共的get方法,用于获取属性的值
public XX getXxx(){ // 权限判断
        return xx;
}

2. 继承

1. 继承的基本注意事项

  1. 子类继承了所有的属性和方法,非私有的属性和方法可以直接访向,但是私有属性和方法不能在子类直接访向,要通过公共的方法去访问
  2. 子类必须调用父类的构造器完成父类的初始化
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参枃造器:则必须在子类的构造器中用 super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过
  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下: super(参数列表)
  5. super在使用时,需要放在构造器第一行
  6. super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器( this() 和 super() 都是在类中的构造器中使用,this() 是调用类本身的另一个构造器,super()是调用父类的构造器,this不是作为构造器的时候则可以和super()共用)
  7. java所有类都是 Object类的子类,Object是所有类的基类
  8. 父类构造器的调用不限于直接父类!将一直往上追溯到 Object类(顶级父类)
  9. 子类最多只能继承一个父类(指直接继承),即java中是单继承机制。 思考:如何让A类继承B类和C类?[A继承B,B继承C]
  10. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
Person is a Music?
Person Music
Music extends Person //不合理 
Anima
Cat extents Animal //合理

2. this和super

No.区别thissuper
1访问属性访问本类中的属性,如果本类没有此属性则从父类中继续查找访问父类中的属性
2调用方法访问本类中的方法,如果本类没有此方法则从父类继续查找直接访问父类中的方法
3调用构造器(二选一)调用本类构造器,必须放在构造器的首行调用父类枃造器,必须放在子类构造器的首行
4特殊表示当前对象子类中访问父类对象

3. 方法重写(方法覆盖)

  1. 子类的方法的 参数、方法名称 要和父类方法的参数方法名称完全一样。
  2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
  3. 子类方法的访问权限 ≥ 父类方法的访向权限

4. 方法重写与重载

名称发生范围方法名参数列表返回类型修饰符
重载(overload)本类必须一样类型、个数、顺序至少有一个不同无要求无要求
重写(override)父子类必须一样必须相同子类重写方法返回类型和父类方法返回类型一致,或者为父类方法返回类型的子类子类方法的访问修饰符 ≥ 父类的访问修饰符

3. 多态

1. 基本概念

  1. 方法的多态——方法重载的多态 + 方法重写的多态

  2. 对象的多态(核心,困难,重点)

    1. 一个对象的编译类型和运行类型可以不一致

    2. 编译类型在定义对象时,就确定了,不能改变

    3. 运行类型是可以变化的

    4. 编译类型看定义时 = 号的左边,运行类型看 = 号的右边

      案例:
      Animal animal= new Dog();【animal编译类型是 Animal,运行类型Dog】
      animal= new Cat(); 【animal的运行类型变成了Cat,编译类型仍然是 Animal】

2. 多态的向上转型

父类引用指向子类对象本质:父类的引用指向了子类的对象
语法: 父类类型 引用名 = new 子类类型();
特点:编译类型看左边,运行类型看右边
可以调用父类中的所有成员(需遵守访向权限)
不能调用子类中特有成员,因为在编译阶段,能调用哪些成员,是由编译类型来决定的
最终运行效果看子类的具体实现!

3. 多态的向下转型

语法: 子类类型 引用名 = (子类类型) 父类引用;
只能强转父类的引用,不能强转父类的对象
要求父类的引用必须指向的是当前目标类型的对象,即父类引用本来就是指向要强转的子类类型的对象的
当向下转型后,可以调用子类类型中所有的成员

编译类型决定可以调用的范围,运行类型决定方法最终的执行效果

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

instanceOf比较操作符,用于判断对象的运行类型是否为X类型成XX类型的子类型

4. java的动态绑定机制

1.当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

提示:看到继承关系,就要联想到动态绑定的问题

5. 多态的应用

1. 多态数组

数组的定义类型为父类类型,里面保存的实际元素类型为子类类型

public class PolyArray {
    public static void main(String[] args) {
		//Teacher和Student是Person的子类
        Person[] people = new Person[5];
        people[0] = new Person("wjh", 16);
        people[1] = new Student("wjh", 17, 646);
        people[2] = new Student("xdd", 17, 630);
        people[3] = new Teacher("jls", 47, 8000);
        people[4] = new Teacher("yyg", 36, 7000);
        for (int i = 0; i < people.length; i++) {
            //people[i]编译类型是Person,运行类型根据实际情况由JVM来判断
            System.out.println(people[i].say());//动态绑定

            //类型判断 + 向下转型,这样就可以调用子类独有的方法了
            if (people[i] instanceof Teacher) {
                ((Teacher) people[i]).teach();
            } else if (people[i] instanceof Student) {
                ((Student) people[i]).study();
            } else if (people[i] instanceof Person) {

            } else {
                System.out.println("你的类型有误,请自己检查...");
            }
        }
    }
}
2. 多态参数
public class PolyParameter {
    public static void main(String[] args) {
        Worker tom = new Worker("Tom", 2500);
        Manager milan = new Manager("milan", 5000, 200000);
        PolyParameter polyParameter = new PolyParameter();
        polyParameter.showEmpAnnual(tom);
        polyParameter.showEmpAnnual(milan);

        polyParameter.testWork(tom);
        polyParameter.testWork(milan);
    }

    public void showEmpAnnual(Employee e) {
        System.out.println(e.getAnnual());  //动态绑定机制
    }

    //多态参数
    public void testWork(Employee e) {
        if (e instanceof Worker) {	//类型判断
            ((Worker) e).work();	//向下转型
        } else if (e instanceof Manager) {
            ((Manager) e).manager();
        } else {
            System.out.println("不做处理");
        }
    }
}

4. Object类详解

1. == 和 equals() 的区别

== 是一个比较运算符
  1. == : 既可以判断基本类型,又可以判断引用类型

  2. == : 如果判断基本类型,判断的是值是否相等

    示例:int i=19; double d=10.0;

  3. 如果判断引用类型,判断的是地址是否相等。即判定是不是同一个对象

equals()
  1. equals : 是 Object类中的方法,只能判断引用类型
  2. 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等

2. hashCode()

  1. 提高具有哈希结构的容器的效率!
  2. 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
  3. 两个引用,如果指向的是不同对象,则哈希值是不一样的
  4. 哈希值主要根据地址号来的!不能完全将哈希值等价于地址
  5. 后面在集合,中 hash Code如果需要的话,也会重写

由类别Object定义的hashCode方法确实会针对不同对象返回不同的整数。这通常通过将对象的内部地址转换为整数来实现,但Java的编程语言不需要此实现技术。

提示:对象的内部地址即实际的地址,由于Java是运行再虚拟机上的,因此我们不能拿到对象的内部地址。与之相对的是,C/C++则可以取得实际的地址

3. toString()

  1. 默认返回:全类名 + @ + 哈希值的十六进制 [全类名 即包名 + 类名]

  2. 子类往往重写 toString(),用于返回对象的属性信息

  3. 重写toString(),打印对象就拼接对象时,都会自动调用该对象的 toString形式 【idea快捷键:alt + insert】

  4. 当直接输出一个对象时, toString()会被默认的调用

    System.out.println(monster) <=> System.out.println(monster.toString)

4. finalize()

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

提示:实际开发中,几乎不会运用 finalize(),所以主要是为了应付面试

public class Finalize_ {
    public static void main(String[] args) {
        Car car = new Car("宝马");
        //执行到 car = null; 时,car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象
        //在销毁对象前,会调用该对象的 finalize()
        //程序员就可以在 finalize() 中,写自己的业务逻辑代码,比如释放资源:数据库连接、或者打开的文件...
        //如果程序员不重写finalize(),那么就调用 Object类的 finalize(),即默认处理
        //如果程序员重写finalize(),那么就可以实现自己的逻辑
        car = null;
        System.gc();    //主动调用垃圾回收器,不一定触发成功

        System.out.println("程序退出了...");
    }
}

class Car {
    private String name;

    public Car(String name) {
        this.name = name;
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("我们销毁汽车:" + name);
        System.out.println("我们释放了某些资源...");
//        super.finalize();
    }
}

//程序输出如下,由于System.gc()调用后,程序不会阻塞在这里,因此不会是简单的顺序输出
/*
程序退出了...
我们销毁汽车:宝马
我们释放了某些资源...
*/

5. 问答

问题一:

什么是多态,多态具体体现有哪些?(可举例说明)

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

多态具体体现

1、方法多态
(1)重载体现多态 (2)重写体现多态

2、对象多态
1)对象的编译类型和运行类型可以不一致,编译类型在定义时,就确定了不能变化
2)对象的运行类型是可以变化的,可以通过 getClass()来查看运行类型
3)编译类型看定时时 = 号的左边,运行类型看 = 号右边

问题二:

java的动态绑定机制是什么?

1、当调用对象的方法时,该方法会和对象的内存地址/运行类型绑定
2、当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

问题三:

== 和 equals() 的区别是什么?

一、== 是一个比较运算符

  1. == : 既可以判断基本类型,又可以判断引用类型
  2. == : 如果判断基本类型,判断的是值是否相等
    示例:int i=19; double d=10.0;
  3. 如果判断引用类型,判断的是地址是否相等。即判定是不是同一个对象

二、equals()

  1. equals : 是 Object类中的方法,只能判断引用类型
  2. 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值