0基础学java-day7-(面向对象编程(中级部分))

一、IDE(集成开发环境)-IDEA

1 、IDEA 介绍

  • IDEA 全称 IntelliJ IDEA
  • 在业界被公认为最好的 Java 开发工具
  • IDEA JetBrains 公司的产品,总部位于捷克的首都布拉格
  • 除了支持 Java 开发,还支持 HTMLCSSPHPMySQLPython

2.IDE(集成开发环境)-Eclipse 

  • Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。
  • 最初是由 IBM 公司耗资 3000 万美金开发的下一代 IDE 开发环境
  • 2001 11 月贡献给开源社区
  • Eclipse 是目前最优秀的 Java 开发 IDE 之一

3.IDE(集成开发环境)-IDEA 的使用 

 3.1 IDEA 的安装

  • 官网: https://www.jetbrains.com/
  • IDEA 下载后,就可以开始安装。
  • 看老师给同学们演示如何安装
  • IDEA 工作界面介绍

IntelliJ IDEA2020安装教程

3.2 IDEA 的基本介绍和使用

我们可以新建项目,项目存放的位置可以自定义,每个项目的src是存放源码的位置

 3.3 IDEA 使用技巧和经验

  • 设置字体  和 颜色主题 

  • 字符编码设置(默认UTF-8)

 4.IDEA 常用快捷键

  • 删除当前行, 默认是 ctrl + Y 自己配置 ctrl + d
  • 复制当前行, 自己配置 ctrl + alt + 向下光标
  • 补全代码 alt + /
  • 添加注释和取消注释 ctrl + / 【第一次是添加注释,第二次是取消注释】
  • 导入该行需要的类 先配置 auto import , 然后使用 alt+enter 即可
  • 快速格式化代码 ctrl + alt + L
  • 快速运行程序 自己定义 alt + R
  • 生成构造器等 alt + insert [提高开发效率]
  • 查看一个类的层级关系 ctrl + H [学习继承后,非常有用]
  • 将光标放在一个方法上,输入 ctrl + B , 可以定位到方法 [学继承后,非常有用]
  • 自动的分配变量名 , 通过 在后面假 .var [老师最喜欢的]
  • 还有很多其它的快捷键

5.模板/自定义模板 

 二、

1看一个应用场景 

 2包的三大作用

 3包基本语法

4. 包的本质分析(原理)

5.快速入门 

 包的命名

 7常用的包

 如何引入包

 9.注意事项和使用细节

 三、访问修饰符

1基本介绍 

  • java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):
  • 公开级别:public 修饰,对外公开
  • 受保护级别:protected 修饰,对子类和同一个包中的类公开
  • 默认级别:没有修饰符号,向同一个包的类公开.
  • 私有级别:private 修饰,只有类本身可以访问,不对外公开.

2  四种访问修饰符的访问范围 

 使用的注意事项

 

三、面向对象编程三大特征 

  • 面向对象编程有三大特征:封装、继承和多态 

1.封装 

1.1 封装介绍 

 1.2 封装的理解和好处

 1.3 封装的实现步骤

1.4 代码示例 

package com.hspedu.encap;

public class Encapsulation01 {
    public static void main(String[] args) {
        Person person =new Person();
        person.setName("Jack111");
        person.setAge(3000);
        person.setSalary(5000);
        System.out.println(person.info());
    }
}
/*
那么在 java 中如何实现这种类似的控制呢?
请大家看一个小程序(com.hspedu.encap: Encapsulation01.java), 不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认
年龄, 必须在 1-120, 年龄, 工资不能直接查看 , name 的长度在 2-6 字符 之间
*/
class Person{
    public  String name;//名字公开
    private int age;//age私有化
    private double salary;
    public String getName() {
        //可以这里增加对当前对象的权限判断
        return name;
    }

    public void setName(String name) {
        //加入对数据的校验
        if (name.length()>=2&&name.length()<=6)
            this.name = name;
        else{
            System.out.println("名字的长度不对,需要(2-6个字符),将给默认名字Tom");
            this.name="Tom";
        }
    }

    public int getAge() {
        //可以这里增加对当前对象的权限判断
        return age;
    }

    public void setAge(int age) {
        if (age>=1&&age<=120)
            this.age = age;
        else
        {System.out.println("年龄需要在1-120之间,本次将设置默认年龄为18");
        this.age=18;

        }
    }

    public double getSalary() {
        //可以这里增加对当前对象的权限判断
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public  String info(){
        return "信息为 name= "+name+" age= "+age+" 薪水= "+salary;
    }

}

 1.5 将构造器和 setXxx 结合

当构造器赋值时,可以将set 方法写在构造器中,这样仍然可以验证

// 有三个属性的构造器
public Person(String name, int age, double salary) {
// this.name = name;
// this.age = age;
// this.salary = salary;
// 我们可以将 set 方法写在构造器中,这样仍然可以验证
        setName(name);
        setAge(age);
        setSalary(salary);
}

1.6 课堂练习 

package com.hspedu.encap;

public class Account {
    private String name;
    private double balance;
    private String pwd;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name.length()>=2&&name.length()<=4)
            this.name = name;
        else{
            System.out.println("姓名长度应该为2-4位,系统将默认设置名字为无名人");
            this.name="无名人";
        }
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        if (balance>20)
            this.balance = balance;
        else{
            System.out.println("余额应该为20以上,系统将默认设置余额为2000");
            this.balance=2000;
        }
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        if(pwd.length()==6)
            this.pwd = pwd;
        else{
            System.out.println("密码长度应该为6位,系统将默认设置密码为000000");
            this.pwd="000000";
        }
    }
    public String info(){
        return "账户名:"+name+" 余额:"+balance+" 密码:"+pwd;
    }
}
package com.hspedu.encap;

public class Account_test {
    public static void main(String[] args) {
        Account a1=new Account();
        a1.setName("林林林");
        a1.setBalance(1);
        a1.setPwd("23");
        System.out.println(a1.info());
    }
}

2. 继承

2.1为什么需要继承 

 2.2继承基本介绍和示意图

继承可以解决代码复用 , 让我们的编程更加靠近人类思维 . 当多个类存在相同的属性 ( 变量 ) 和方法时 , 可以从这些类中 抽象出父类, 父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。画出继承的示意图

 2.3继承的基本语法

2.4 快速入门案例 

测试入口

package com.hspedu.extend_.improve_;

import com.hspedu.extend_.Graduate;
import com.hspedu.extend_.Pupil;

public class TestExtends {
    public static void main(String[] args) {
        com.hspedu.extend_.Pupil pupil =new Pupil();
        pupil.name="小明";
        pupil.age=10;
        pupil.testing();
        pupil.setScores(98);
        pupil.showInfo();
        System.out.println("====================");
        com.hspedu.extend_.Graduate graduate = new Graduate();
        graduate.name="金角大王";
        graduate.age=20;
        graduate.testing();
        graduate.setScores(100);
        graduate.showInfo();
    }
}

 Student类

package com.hspedu.extend_.improve_;
//父类,是pupil和Graduate的父类
public class Student {
    //共有属性
    public String name;
    public int age;
    private double scores;
    public void setScores(double scores) {
        this.scores = scores;
    }
   //共有方法
    public void showInfo(){
        System.out.println("大学生名 "+name+" 年龄 "+age+" 成绩 "+scores);
    }
}
package com.hspedu.extend_.improve_;

public class Pupil extends Student{//继承
    public void testing(){
        System.out.println("小学生 "+name+" 正在考小学数学..");
    }
}
package com.hspedu.extend_.improve_;

public class Graduate extends Student {
    public void testing(){
        System.out.println("大学生 "+name+" 正在考大学数学..");
    }
}

2.5 继承给编程带来的便利

  • 代码的复用性提高了
  • 代码的扩展性和维护性提高了

 2.6 继承的深入讨论/细节问题

  • 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访 问,要通过父类提供公共的方法去访问
  • 子类必须调用父类的构造器, 完成父类的初始化
  • 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过(怎么理解。)
  • 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
  • super 在使用时,必须放在构造器第一行(super ()只能在构造器中使用,)
  • super() this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  • java 所有类都是 Object 类的子类, Object 是所有类的基类.
  • 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object (顶级父类)
  • 子类最多只能继承一个父类(直接继承),即 java 中是单继承机制。
  • 思考:如何让 A 类继承 B 类和 C 类? 【A 继承 BB 继承 C
  • 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
  • 程序入口
package com.hspedu.extend_;

public class ExtendsDetail {
    public static void main(String[] args) {
// System.out.println("===第 1 个对象====");
// Sub sub = new Sub(); //创建了子类对象 sub
// System.out.println("===第 2 个对象====");
// Sub sub2 = new Sub("jack"); //创建了子类对象 sub2
        System.out.println("===第 3 对象====");
        Sub sub3 = new Sub("king", 10); //创建了子类对象 sub2
//sub.sayOk();
    }
}

 第一层【object类】-第二层【TopBase类】

package com.hspedu.extend_;

public class TopBase {
    public TopBase() {
//super(); Object 的无参构造器
        System.out.println("构造器 TopBase() 被调用...");//1
    }
}

第三层 Base类 

package com.hspedu.extend_;

public class Base extends TopBase{//父类
    //4 个属性
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;
    public Base() { //无参构造器
        System.out.println("父类 Base()构造器被调用....");
    }
    public Base(String name, int age) {//有参构造器
//默认 super()
        System.out.println("父类 Base(String name, int age)构造器被调用....");
    }
    public Base(String name) {//有参构造器
        System.out.println("父类 Base(String name)构造器被调用....");
    }
    //父类提供一个 public 的方法,返回了 n4
    public int getN4() {
        return n4;
    }
    public void test100() {
        System.out.println("test100");
    }
    protected void test200() {
        System.out.println("test200");
    }
    void test300() {
        System.out.println("test300");
    }
    private void test400() {
        System.out.println("test400");
    }
    //call
    public void callTest400() {
        test400();
    }
}

第四层sub类

package com.hspedu.extend_;
//输入 ctrl + H 可以看到类的继承关系
public class Sub extends Base{
    public Sub(String name, int age) {
//1. 老师要调用父类的无参构造器, 如下或者 什么都不写,默认就是调用 super()
//super();//父类的无参构造器
//2. 老师要调用父类的 Base(String name) 构造器
//super("hsp");
//3. 老师要调用父类的 Base(String name, int age) 构造器
        super("king", 20);
//细节: super 在使用时,必须放在构造器第一行
//细节: super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
//this() 不能再使用了
        System.out.println("子类 Sub(String name, int age)构造器被调用....");
    }
    public Sub() {//无参构造器
//super(); //默认调用父类的无参构造器
        super("smith", 10);
        System.out.println("子类 Sub()构造器被调用....");
    }
    //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
    public Sub(String name) {
        super("tom", 30);
    //do nothing... System.out.println("子类 Sub(String name)构造器被调用....");
    }
    public void sayOk() {//子类方法
    //非私有的属性和方法可以在子类直接访问
    //但是私有属性和方法不能在子类直接访问
        System.out.println(n1 + " " + n2 + " " + n3);
        test100();
        test200();
        test300();
//test400();错误
//要通过父类提供公共的方法去访问
        System.out.println("n4=" + getN4());
        callTest400();//
    }
}

 2.7 继承的本质分析(重要)

package com.hspedu.extend_;

public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son();//内存的布局
//?-> 这时请大家注意,要按照查找关系来返回信息
//(1) 首先看子类是否有该属性
//(2) 如果子类有这个属性,并且可以访问,则返回信息
//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object... System.out.println(son.name);//返回就是大头儿子
//System.out.println(son.age);//返回的就是 39
//System.out.println(son.getAge());//返回的就是 39
        System.out.println(son.hobby);//返回的就是旅游
    }
}
class GrandPa { //爷类
    String name = "大头爷爷";
    String hobby = "旅游";
}
class Father extends GrandPa {//父类
    String name = "大头爸爸";
    private int age = 39;
    public int getAge() {
        return age;
    }
}
class Son extends Father { //子类
    String name = "大头儿子";
}

2.8 课堂练习

 

在下面代码中,并不会执行B类的无参方法,因为this()把super顶掉了 

package com.hspedu.extend_;

public class ExtendsExercise02 {
    public static void main(String[] args) {
        C c = new C();
    }
}
class A {//A 类
    public A() {
        System.out.println("我是 A 类");
    }
}
class B extends A { //B 类,继承 A 类 //main 方法中: C c =new C(); 输出么内容? 3min
    public B() {
        System.out.println("我是 B 类的无参构造");
    }
    public B(String name) {
        System.out.println(name + "我是 B 类的有参构造");
    }
}
class C extends B { //C 类,继承 B 类
    public C() {
        this("hello");
        System.out.println("我是 c 类的无参构造");
    }
    public C(String name) {
        super("hahah");
        System.out.println("我是 c 类的有参构造");
    }
}

2.9 super 关键字 

  • super 代表父类的引用,用于访问父类的属性、方法、构造 
  • 基本语法 

  •  super 给编程带来的便利/细节

2.10 super this 的比较 

 3.方法重写/覆盖

3.1 基本介绍 

 返回类型在一定的条件下可以是不一样的;要么一样,要么子类返回的是父类返回2类型的子类

3.2 注意事项和使用细节 

 3.3 课堂练习

3.3.1 请对方法的重写和重载做一个比较 

3.3.2 题2

 4.多态

 4.1 先看一个问题

  • 使用传统的方法来解决(private 属性)
  • 传统的方法带来的问题是什么? 如何解决?
  • 问题是: 代码的复用性不高,而且不利于代码维护
  • 解决方案: 引出我们要讲解的多态

4.2 [多种][状态]基本介绍 

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

4.3 多态的具体体现 

4.3.1 方法的多态 
  • 重写和重载就体现多态 
4.3.2 对象的多态 

 以运行的时候的类型为主

package com.hspedu.poly_.objectpoly_;

public class Animal {
    public void cry() {
        System.out.println("Animal cry() 动物在叫....");
    }
}
package com.hspedu.poly_.objectpoly_;

public class Cat extends Animal{
    @Override
    public void cry() {
        System.out.println("Cat cry() 小猫喵喵叫...");
    }
}
package com.hspedu.poly_.objectpoly_;

public class Dog extends Animal{
    @Override
    public void cry() {
        System.out.println("Dog cry() 小狗汪汪叫...");
    }
}
package com.hspedu.poly_.objectpoly_;

public class PolyObject {
    public static void main(String[] args) {
        //体验对象多态特点
        //animal 编译类型就是 Animal , 运行类型 Dog
        Animal animal = new Dog();
        //因为运行时 , 执行到改行时,animal 运行类型是 Dog,所以 cry 就是 Dog 的 cry
        animal.cry(); //小狗汪汪叫
        //animal 编译类型 Animal,运行类型就是 Cat
        animal = new Cat();
        animal.cry(); //小猫喵喵叫
    }
}

4.4 多态快速入门案例

  • 使用多态的机制来解决主人喂食物的问题,走代码 

 4.5 多态注意事项和细节讨论

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

  • 多态的向上转型 :子类的特有成员调用的话会报错,也就是所调用的是子类跟父类都有的,只是说子类对父类的方法进行了重写而已。

  • 多态向下转型 

package com.hspedu.poly_.detail_;

public class Animal {
    String name = "动物";
    int age = 10;
    public void sleep(){
        System.out.println("睡");
    }
    public void run(){
        System.out.println("跑");
    }
    public void eat(){
        System.out.println("吃");
    }
    public void show(){
        System.out.println("hello,你好");
    }
}
package com.hspedu.poly_.detail_;

public class Cat extends Animal {
    public void eat(){//方法重写
        System.out.println("猫吃鱼");
    }
    public void catchMouse(){//Cat 特有方法
        System.out.println("猫抓老鼠");
    }
}
package com.hspedu.poly_.detail_;

public class Dog extends Animal{
}
package com.hspedu.poly_.detail_;

public class PolyDetail {
    public static void main(String[] args) {
        //向上转型: 父类的引用指向了子类的对象
        //语法:父类类型引用名 = new 子类类型();
        Animal animal = new Cat();
        Object obj = new Cat();//可以吗? 可以 Object 也是 Cat 的父类
        //向上转型调用方法的规则如下:
        //(1)可以调用父类中的所有成员(需遵守访问权限)
        //(2)但是不能调用子类的特有的成员
        //(#)因为在编译阶段,能调用哪些成员,是由编译类型来决定的
        //animal.catchMouse();错误
        //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法
        //,然后调用,规则我前面我们讲的方法调用规则一致。
        animal.eat();//猫吃鱼.. animal.run();//跑
        animal.show();//hello,你好
        animal.sleep();//睡
        //老师希望,可以调用 Cat 的 catchMouse 方法
        //多态的向下转型
        //(1)语法:子类类型 引用名 =(子类类型)父类引用;
        //问一个问题? cat 的编译类型 Cat,运行类型是 Cat
        Cat cat = (Cat) animal;
        cat.catchMouse();//猫抓老鼠
        //(2)要求父类的引用必须指向的是当前目标类型的对象
        Dog dog = (Dog) animal; //可以吗?可以
        System.out.println("ok~~");
    }
}
  • 属性没有重写之说!属性的值看编译类型
package com.hspedu.poly_.detail_;
public class PolyDetail02 {
public static void main(String[] args) {
//属性没有重写之说!属性的值看编译类型
Base base = new Sub();//向上转型
System.out.println(base.count);// ? 看编译类型 10
Sub sub = new Sub();
System.out.println(sub.count);//? 20
}
}
class Base { //父类
int count = 10;//属性
}
class Sub extends Base {//子类
int count = 20;//属性
}
  •  instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型
package com.hspedu.poly_.detail_;
public class PolyDetail03 {
    public static void main(String[] args) {
        BB bb = new BB();
        System.out.println(bb instanceof BB);// true
        System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
//BB 是 AA 子类
        AA aa = new BB();
        System.out.println(aa instanceof AA);
        System.out.println(aa instanceof BB);
        Object obj = new Object();
        System.out.println(obj instanceof AA);//false
        String str = "hello";
//System.out.println(str instanceof AA);
        System.out.println(str instanceof Object);//true
    }
}
class AA {} //父类
class BB extends AA {}//子类

 4.6 课堂练习

  • 请说出下面的每条语言,哪些是正确的,哪些是错误的,为什么? 

  •  PolyExercise02.java

4.7 java 的动态绑定机制 

  • Java 重要特性: 动态绑定机制 

看改完代码的案例

package com.hspedu.poly_.dynamic_;

public class DynamicBinding {
    public static void main(String[] args) {
//a 的编译类型 A, 运行类型 B
        A a = new B();//向上转型
        System.out.println(a.sum());//?40 -> 30
        System.out.println(a.sum1());//?30-> 20
    }
}
class A {//父类
    public int i = 10;
    //动态绑定机制:
    public int sum() {//父类 sum()
        return getI() + 10;//20 + 10
    }
    public int sum1() {//父类 sum1()
        return i + 10;//10 + 10
    }
    public int getI() {//父类 getI
        return i;
    }
}
class B extends A {//子类
    public int i = 20;
    // public int sum() {
// return i + 20;
// }
    public int getI() {//子类 getI()
        return i;
    }
// public int sum1() {
// return i + 10;
// }
}

4.8 多态的应用

4.8.1 多态数组 
  • 数组的定义类型为父类类型,里面保存的实际元素类型为子类类型 
  • 应用实例:现有一个继承结构如下:要求创建 1 Person 对象、2 Student 对象和 2 Teacher 对象, 统一放在数组 中,并调用每个对象 say 方法
  • 应用实例升级:如何调用子类特有的方法,比如 Teacher 有一个 teach , Student 有一个 study怎么调用

package com.hspedu.poly_.polyarr_;

public class Person {//父类
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public String say() {//返回名字和年龄
        return name + "\t" + age;
    }
}
package com.hspedu.poly_.polyarr_;

public class Student extends Person {
    private double score;

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
    //重写父类 say
    @Override
    public String say() {
        return "学生 " + super.say() + " score=" + score;
    }
    //特有的方法
    public void study() {
        System.out.println("学生 " + getName() + " 正在学 java...");
    }
}
package com.hspedu.poly_.polyarr_;

public class Teacher extends Person{
    private double salary;

    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    //写重写父类的 say 方法
    @Override
    public String say() {
        return "老师 " + super.say() + " salary=" + salary;
    }
    //特有方法
    public void teach() {
        System.out.println("老师 " + getName() + " 正在讲 java 课程...");
    }
}
package com.hspedu.poly_.polyarr_;

public class PloyArray {
    public static void main(String[] args) {
        //应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、
        // 2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象 say 方法
        Person[] persons = new Person[5];
        persons[0] = new Person("jack", 20);
        persons[1] = new Student("mary", 18, 100);
        persons[2] = new Student("smith", 19, 30.1);
        persons[3] = new Teacher("scott", 30, 20000);
        persons[4] = new Teacher("king", 50, 25000);
        //循环遍历多态数组,调用 say
        for (int i = 0; i < persons.length; i++) {
//老师提示: person[i] 编译类型是 Person ,运行类型是是根据实际情况有 JVM 来判断
            System.out.println(persons[i].say());//动态绑定机制
//这里大家聪明. 使用 类型判断 + 向下转型. if(persons[i] instanceof Student) {//判断 person[i] 的运行类型是不是 Student
            if(persons[i] instanceof Student) {//判断 person[i] 的运行类型是不是 Student
                Student student = (Student)persons[i];//向下转型
                student.study();

//小伙伴也可以使用一条语句 ((Student)persons[i]).study();
            } else if(persons[i] instanceof Teacher) {
                Teacher teacher = (Teacher)persons[i];
                teacher.teach();
            } else if(persons[i] instanceof Person){
//System.out.println("你的类型有误, 请自己检查...");
            } else {
                System.out.println("你的类型有误, 请自己检查...");
            }

        }
    }
    }

4.8.2 多态参数

 四.Object 类详解

1 equals 方法 

1.1 ==equals 的对比 

 //带大家看看 Jdk 的源码 String 类的 equals 方法

// Object equals 方法重写了 , 变成了比较两个字符串值是否相同
// Object equals 方法默认就是比较对象地址是否相同
// 也就是判断两个对象是不是同一个对象 .
// 从源码可以看到 Integer 也重写了 Object equals 方法 ,
// 变成了判断两个值是否相同

package com.hspedu.object_;

public class Equals01 {
    public static void main(String[] args) {
        A a =new A();
        A b = a;
        A c = b;
        System.out.println(a==c);//true
        B bobj =a;
        System.out.println(bobj==c);//true
    }
}
class A extends B{

}
class B {

}

2.hashCode 方法

  • 提高具有哈希结构的容器的效率!
  • 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
  • 两个引用,如果指向的是不同对象,则哈希值是不一样的
  • 哈希值主要根据地址号来的!, 不能完全将哈希值等价于地址
  • 案例演示[HashCode_.java]: obj.hashCode() [测试:A obj1 = new A(); A obj2 = new A(); A obj3 = obj1]
  • 后面在集合,中 hashCode 如果需要的话,也会重写, 在讲解集合时,再说如何重写hashCode()
package com.hspedu.object_;


public class HashCode_ {
    public static void main(String[] args) {
        AA aa = new AA();
        AA aa2 = new AA();
        AA aa3 = aa;
        System.out.println("aa.hashCode()=" + aa.hashCode());
        System.out.println("aa2.hashCode()=" + aa2.hashCode());
        System.out.println("aa3.hashCode()=" + aa3.hashCode());
    }
}
class AA {}

3.toString 方法

  • 默认返回:全类名+@+哈希值的十六进制,【查看 Object toString 方法】
  • 子类往往重写 toString 方法,用于返回对象的属性信息
  • 重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式.
  • 当直接输出一个对象时, toString 方法会被默认的调用 , 比如 System.out.println(monster) ; 就会默认调用 monster.toString()

 4.finalize 方法

  • 当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法,做一些释放资源的操作 
  • 什么时候被回收:当某个对象没有任何引用时,则 jvm 就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来 销毁该对象,在销毁该对象前,会先调用 finalize 方法
  • 垃圾回收机制的调用,是由系统来决定(即有自己的 GC 算法), 也可以通过 System.gc() 主动触发垃圾回收机制,测 试【不一定百分之百会调用垃圾回收器】
  • 我们在实际开发中,几乎不会运用 finalize , 所以更多就是为了应付面试.
package com.hspedu.object_;

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

    public Car(String name) {
        this.name = name;
    }
    //重写 finalize
    @Override
    protected void finalize() throws Throwable {
        System.out.println("我们销毁 汽车" + name );
        System.out.println("释放了某些资源...");
    }
}

 五、断点调试

1.一个实际需求 

 2.断点调试介绍

 3.断点调试的快捷键

  • F7(跳入) F8(跳过)
  • shift+F8(跳出) F9(resume,执行到下一个断点)
  • F7:跳入方法内
  • F8: 逐行执行代码.
  • shift+F8: 跳出方法

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜菜小林然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值