7.JAVA 面向对象编程

7.面向对象编程

7.1 IDE(集成开发环境)-IDEA

  1. IDEA 全称 IntelliJ IDEA
  2. 在业界被公认为最好的Java开发工具
  3. IDEA是JetBrains 公司的产品,总部位于捷克的首都布拉格
  4. 除了支持Java开发,还支持HTML,CSS,PHP,MySQL,Python等

7.2IDE(集成开发环境)-Eclipse

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

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

[ 官网:] (https://www.jetbrains.com)

IDEA 常用快捷键

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

7.4 包

7.4.1 应用场景

当 Java 项目规模扩大,类和接口数量增多时,容易出现命名冲突问题。包提供了一种层级化的命名空间机制,可将相关类 / 接口组织在一起。例如:

  • 开发电商系统时,可将订单相关类放在com.company.order
  • 用户相关类放在com.company.user
  • 工具类放在com.company.utils

7.4.2 包的三大作用

  1. 解决命名冲突:不同包中可以有同名类,通过全限定名(包名 + 类名)区分
  2. 实现访问控制:配合访问修饰符(如protected)控制类成员的访问范围
  3. 便于代码组织:按功能或模块分类管理类,提高代码可维护性和可读性

7.4.3 包基本语法

  1. 定义包

    package com.company.module; // 必须放在Java文件第一行
    
  2. 导入包

    import com.company.utils.Tool; // 导入特定类
    import com.company.utils.*;    // 导入包中所有类
    import static java.lang.Math.PI; // 静态导入
    
  3. 使用类

    // 方式1:使用全限定名
    com.company.utils.Tool tool = new com.company.utils.Tool();
    
    // 方式2:先导入再使用简名
    Tool tool = new Tool();
    

7.4.4 包的本质分析(原理)

包本质上是文件系统的目录结构,与 Java 的命名空间机制对应:

  • 包名com.company.module对应目录结构com/company/module

  • Java 编译器将.java文件编译为.class文件时,会按照包结构创建相应目录

  • 类加载器通过全限定名查找对应的.class文件

  • 包名通常采用反转的域名(如com.baidu),确保全球唯一性

7.4.5 常用的包(Java)

在 Java 开发中,系统提供了许多常用包,涵盖了基础功能、数据处理、IO 操作、网络通信等多个领域,以下是最常用的核心包及其功能:

1. java.lang

  • 特点:Java 语言的核心包,无需手动导入,默认自动加载。

  • 主要内容

    • 基本数据类型包装类(IntegerDouble等)
    • 字符串类(StringStringBuilder
    • 系统类(SystemRuntime
    • 线程类(ThreadRunnable
    • 异常类(ExceptionRuntimeException

2. java.util

  • 特点:工具类包,提供大量实用工具和数据结构。

  • 主要内容

    • 集合框架(ListSetMap及其实现类如ArrayListHashMap
    • 日期时间类(DateCalendar、Java 8 + 的LocalDateTime
    • 随机数生成(Random
    • 工具类(ArraysCollections用于集合 / 数组操作)

3. java.io

  • 特点:输入输出包,用于处理文件和流操作。

  • 主要内容

    • 字节流(InputStreamOutputStream
    • 字符流(ReaderWriter
    • 文件操作(FileFileInputStream

4. java.net

  • 特点:网络编程包,支持 TCP/IP、UDP 等网络通信。

  • 主要内容

    • 网络连接(SocketServerSocket
  • URL 处理(URLURLConnection

    • 网络接口(InetAddress

    5. java.sql

    • 特点:数据库操作包,提供 JDBC(Java 数据库连接)接口。

    • 主要内容

      • 数据库连接(Connection
  • SQL 执行(StatementPreparedStatement

    • 结果集(ResultSet

    6. java.awtjavax.swing

    • 特点:图形用户界面(GUI)开发包。

    • 主要内容

      • java.awt:基础 GUI 组件(如FrameButton),依赖本地系统外观。
  • javax.swing:轻量级 GUI 组件(如JFrameJButton),跨平台统一外观。

    7. java.math

    • 特点:高精度数学运算包。

    • 主要内容

      • BigInteger:任意精度整数运算。
  • BigDecimal:高精度小数运算,避免浮点数误差。

    8. java.text

    • 特点:文本处理包,用于格式化和解析。

    • 主要内容

      • 日期格式化(SimpleDateFormat
  • 数字格式化(NumberFormat

    这些包是 Java 开发的基础,掌握其核心类和功能能显著提高开发效率。实际开发中,还会结合第三方包(如org.springframeworkcom.alibaba.fastjson等)扩展功能。

7.5访问修饰符

访问修饰符 同类 同包 子类 不同包
public true true true true
protected true true true
默认 true true
private true

7.6 面向对象编程三大特征

  • 7.6.1基本介绍

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

  • 7.6.2封装介绍

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

  • 7.6.3封装的理解和好处

    1. 隐藏实现细节:例如方法(连接数据库等复杂操作),外部调用只需传入参数,无需知晓内部实现流程。
    2. 保证数据安全合理:以 Person {name, age} 为例,若直接赋值 p.age = 1200; 会出现不合理数据,通过封装可避免这类问题,如下代码演示直接赋值的问题:
    Person p = new Person();
    p.name = "jack"; 
    p.age = 1200; // 年龄数值不合理,但未做限制
    
  • 7.6.4 封装的实现步骤(三步)

    1. 属性私有化:用 private 修饰属性,使其不能直接被外部修改,代码示例:
    private 数据类型 属性名; // 如 private String name; 
    
    1. 提供公共 set 方法:用于对属性判断并赋值,可加入数据验证逻辑,语法模板:
    public void setXxx(类型 参数名){ 
        // 数据验证的业务逻辑,如年龄范围判断
        属性 = 参数名; 
    }
    // 示例(以 Person 类 age 属性为例)
    public void setAge(int age) {
        if(age > 0 && age < 150) { // 简单年龄验证
            this.age = age;
        } else {
            System.out.println("年龄数值不合理");
        }
    }
    
    1. 提供公共 get 方法:用于获取属性的值,可按需加入权限判断,语法模板:
    public 数据类型 getXxx(){ 
        return xx; 
    }
    // 示例(以 Person 类 age 属性为例)
    public int getAge() {
        return this.age;
    }
    

    通过这三步,既能保护属性安全,又能规范对属性的操作,是实现封装的核心流程 。

7.8 面向对象编程-继承

  • 7.8.1为什么需要继承

    image-20250806215045212

  • 7.8.2继承基本介绍和示意图

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

    image-20250806215318984

  • 7.8.3继承的基本用法

    class 子类 extends 父类{
    }
    1. 子类的就会自动拥有父类定义的属性和方法
    2. 父类又叫超类,基类
    3. 子类又叫派生类
    
  • 7.8.5继承给编程带来的便利

    1. 代码的复用性提高了
    2. 代码的扩展性和维护性提高了
  • 7.8.5继承细节问题

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

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

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

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

    5. super在使用时,必须放在构造器第一行(super()(调用父类构造器)只能在构造器中使用)

      super` 关键字还可以在非静态方法中使用,用于访问父类的成员,此时没有位置限制

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

    7. java所有类都是Object类的子类,Object是所有类的基类.

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

    9. 子类最多只能继承一个父类(指直接继承),即java中是单继承机制。 思考:如何让A类继承B类和C类?【A继承B,B继承C】

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

  • 7.8.6继承的本质分析(重要)

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

子类创建的内存布局

image-20250806224346208

7.9super关键字

  • 7.9.1基本介绍

    super代表父类的引用,用于访问父类的属性、方法、构造器

  • 7.9.2基本语法

    1. 访问父类的属性,但不能访问父类的private属性 super.属性名

    2. 访问父类的方法,但不能访问父类的private方法 super.方法名(参数列表)

    3. 访问父类的构造器 super(参数列表)

      只能放在构造器的第一句只能出现一句

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

    image-20250806230333024

  • 7.9.4super 和 this 的比较

    image-20250806230430836

7.10 方法重写/覆盖(override)

  • 7.10.1 基本介绍

    简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法

  • 7.10.2 注意事项和使用细节

    image-20250806231351511

  • 7.10.3重写和重载做一个比较

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

    7.10 面向对象编程 - 多态

  • 7.10.1、多态基本介绍

多态(Polymorphism)是面向对象编程(OOP)的三大特性之一(封装、继承、多态),字面含义是 “多种状态”—— 即同一行为(方法)在不同对象上会表现出不同的实现效果
简单来说:当使用 “通用的方式” 调用方法时,不同对象会根据自身特性做出 “个性化响应”。
多态的前提条件

1. 存在继承关系(子类继承父类);
2. 子类重写父类的方法(核心,体现 “不同状态”);
3. 父类引用指向子类对象(`Parent p = new Child();`,即 “向上转型”)。
  • 7.10.2、多态的具体体现

多态主要通过 “方法的多态” 和 “对象的多态” 体现,核心是 “父类引用调用方法时,实际执行子类的重写版本”。

1. 方法的多态(核心体现)

同一方法名在不同子类中被重写,通过父类引用调用时,表现出不同行为。

示例:

// 父类:动物
class Animal {
    public void cry() {
        System.out.println("动物叫...");
    }
}

// 子类:猫(重写cry方法)
class Cat extends Animal {
    @Override
    public void cry() {
        System.out.println("猫喵喵叫");
    }
}

// 子类:狗(重写cry方法)
class Dog extends Animal {
    @Override
    public void cry() {
        System.out.println("狗汪汪叫");
    }
}

public class Test {
    public static void main(String[] args) {
        // 父类引用指向子类对象(多态的前提)
        Animal a1 = new Cat(); 
        Animal a2 = new Dog();
        
        // 同一方法调用,表现不同状态
        a1.cry(); // 输出:猫喵喵叫(实际执行Cat的cry)
        a2.cry(); // 输出:狗汪汪叫(实际执行Dog的cry)
    }
}
2. 对象的多态(引用的多态)

同一子类对象可以被当作 “父类类型” 或 “自身类型” 看待(即 “向上转型” 和 “向下转型”)。

  • 向上转型(自动转换):Parent p = new Child();(父类引用指向子类对象,多态的基础);

    image-20250806233528191

    //向上转型调用方法的规则如下:
    //(1)可以调用父类中的所有成员(需遵守访问权限)
    //(2)但是不能调用子类的特有的成员
    //(#)因为在编译阶段,能调用哪些成员,是由编译类型来决定的
    //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法
    //,然后调用,规则我前面我们讲的方法调用规则一致。
    
    // 父类(编译类型)
    class Animal {
        public void eat() {
            System.out.println("动物吃东西");
        }
        
        public void sleep() {
            System.out.println("动物睡觉");
        }
    }
    
    // 子类(运行类型)
    class Dog extends Animal {
        // 重写父类方法
        @Override
        public void eat() {
            System.out.println("狗吃骨头");
        }
        
        // 子类特有方法
        public void bark() {
            System.out.println("狗汪汪叫");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            // 向上转型:编译类型为Animal,运行类型为Dog
            Animal animal = new Dog();
            
            // 1. 可以调用父类中的成员(遵守访问权限)
            animal.eat();   // 运行时调用子类重写的方法:输出"狗吃骨头"
            animal.sleep(); // 调用父类方法:输出"动物睡觉"
            
            // 2. 不能调用子类特有的成员(编译报错)
            // animal.bark();  // 错误!编译类型Animal中没有bark()方法
            
            // 3. 编译阶段由编译类型决定可调用的成员
            //    (此处只能调用Animal类中声明的方法)
            
            // 4. 运行效果看子类的具体实现
            //    (eat()方法实际执行的是Dog类的重写版本)
        }
    }
    
  • 向下转型(强制转换):Child c = (Child)p;(需先判断类型,避免类型转换异常)。

    image-20250806233550941

    //多态的向下转型
    //(1)语法:子类类型 引用名 =(子类类型)父类引用;
    //(2)要求父类的引用必须指向的是当前目标类型的对象
    //instanceof 是 Java 中的一个双目运算符,用于判断对象的实际类型是否为指定的类(或其子类、实现类),返回值为 boolean 类型(true 或 false)。
        
    // 父类
    class Animal {
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    
    // 子类1
    class Dog extends Animal {
        @Override
        public void eat() {
            System.out.println("狗吃骨头");
        }
        
        // 子类特有方法
        public void bark() {
            System.out.println("狗汪汪叫");
        }
    }
    
    // 子类2
    class Cat extends Animal {
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
        
        // 子类特有方法
        public void catchMouse() {
            System.out.println("猫抓老鼠");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            // 向上转型:父类引用指向Dog对象
            Animal animal = new Dog();
            animal.eat(); // 调用Dog的eat()
            
            // 向下转型:将父类引用转换为子类类型
            // 要求:父类引用必须指向当前目标类型的对象(这里animal实际指向的是Dog)
            if (animal instanceof Dog) { // 先判断类型,确保安全
                Dog dog = (Dog) animal; // 向下转型语法
                dog.bark(); // 可以调用Dog的特有方法了
                
                // 也可以调用重写的方法
                dog.eat(); // 仍然是"狗吃骨头"
            }
            
            // 错误示例:父类引用指向的是Dog,不能转为Cat
            if (animal instanceof Cat) { // 条件不成立,不会执行
                Cat cat = (Cat) animal; // 若强行转换会抛出ClassCastException
            }
        }
    }
    
  • 7.10.3、多态的 5 个注意事项和细节

  1. 父类引用不能直接调用子类独有的方法
    多态下,父类引用只能访问父类中声明的方法(或子类重写的方法),无法直接调用子类特有的方法。若需调用,必须先 “向下转型” 为子类类型。
    示例:

    class Cat extends Animal {
        @Override
        public void cry() { ... }
        // 子类独有方法
        public void catchMouse() { 
            System.out.println("猫抓老鼠"); 
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Animal a = new Cat(); // 向上转型
            a.cry(); // 正确(子类重写的方法)
            // a.catchMouse(); // 错误!父类引用不能调用子类独有方法
            
            // 向下转型后可调用
            if (a instanceof Cat) { // 先判断类型,避免异常
                Cat c = (Cat)a; 
                c.catchMouse(); // 正确
            }
        }
    }
    
  2. 多态下,方法调用看 “子类重写”,属性访问看 “父类”

    • 方法:运行时调用子类重写的版本(动态绑定);
    • 属性:编译和运行都看父类(属性不参与多态)。

示例:

class Parent {
    int num = 10; // 父类属性
    public void show() { System.out.println("Parent show"); }
}

class Child extends Parent {
    int num = 20; // 子类属性(与父类同名)
    @Override
    public void show() { System.out.println("Child show"); }
}

public class Test {
    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.num); // 输出:10(访问父类属性)
        p.show(); // 输出:Child show(调用子类重写方法)
    }
}


  1. 向上转型(安全)与向下转型(需谨慎)

    • 向上转型:Parent p = new Child(); 总是安全的(子类是父类的 “一种”);
    • 向下转型:必须通过 instanceof 判断实际类型,否则可能抛出
    Parent p = new Dog(); 
    // if (!(p instanceof Cat)) { ... } 若直接转Cat会报错
    if (p instanceof Dog) {
        Dog d = (Dog)p; // 正确
    }
  1. 静态方法不参与多态
    静态方法属于 “类” 而非 “对象”,调用时由 “引用的类型”(编译时类型)决定,与对象实际类型无关。

    示例:

    class Parent {
    public static void staticMethod() {
     System.out.println("Parent static");
    }
    }
    
   class Child extends Parent {
         public static void staticMethod() { // 静态方法"重写"(实际是隐藏)
          System.out.println("Child static");
         }
  }
 ```

 public class Test {
     public static void main(String[] args) {
         Parent p = new Child();
         p.staticMethod(); // 输出:Parent static(看父类类型)
     }
 }
 ```
  1. 构造器的调用顺序影响多态初始化
    子类构造器执行时,会先调用父类构造器。若父类构造器中调用了 “被子类重写的方法”,则会触发子类的重写方法(此时子类属性可能未初始化,需特别注意)。

    示例(风险场景):

    
    
class Parent {
     public Parent() {
      method(); // 父类构造器调用方法(被子类重写)
     }
  public void method() { }
 }

 class Child extends Parent {
  int num = 100; 
     @Override
  public void method() {
         System.out.println(num); // 输出:0(子类num尚未初始化)
     }
 }
 
 public class Test {
     public static void main(String[] args) {
         new Child(); // 执行父类构造器时调用子类method,num为默认值0
     }
 }
 ```
  • 7.10.4、Java 的动态绑定机制(多态的底层核心)

动态绑定(Dynamic Binding)是多态的实现基础,指程序在运行时才确定要调用的方法具体版本,而非编译时。

动态绑定的执行流程(调用对象方法时)

1. 编译时:检查父类(引用类型)是否有该方法。若没有,编译报错;若有,进入运行时。
2. 运行时:JVM 确定对象的实际类型(子类),查找该类型中是否重写了该方法:
   - 若重写:调用子类的重写方法;
   - 若未重写:调用父类的方法。

示例解析动态绑定

class Animal {
    public void eat() { System.out.println("动物吃饭"); }
}

class Cat extends Animal {
    @Override
    public void eat() { System.out.println("猫吃鱼"); }
}

public class Test {
    public static void main(String[] args) {
        Animal a = new Cat(); // 父类引用指向子类对象
        a.eat(); // 动态绑定过程:
        // 1. 编译时:检查Animal是否有eat() → 有,编译通过;
        // 2. 运行时:确定a的实际类型是Cat → 调用Cat的eat() → 输出“猫吃鱼”。
    }
}
  • 7.10.5 多态的应用场景

多态的核心价值是 “统一接口,灵活扩展”,在实际开发中应用广泛:

  1. 简化代码,统一调用
    用父类作为方法参数,可接收所有子类对象,无需为每个子类编写单独方法。

    示例:

    java

    
    
// 统一处理所有动物的方法
 public static void letAnimalCry(Animal animal) {
  animal.cry(); // 传入Cat则猫叫,传入Dog则狗叫
 }

 public static void main(String[] args) {
  letAnimalCry(new Cat()); // 猫喵喵叫
     letAnimalCry(new Dog()); // 狗汪汪叫
}
 ```
  1. 提高扩展性
    新增子类时,无需修改原有代码(符合 “开闭原则”)。

    示例:若新增 “猪” 类(Pig extends Animal),letAnimalCry 方法无需修改即可直接使用。

  2. 框架与设计模式的基础
    多数设计模式(如工厂模式、策略模式)依赖多态实现。例如:

    • 集合框架中,List list = new ArrayList();List list = new LinkedList();,通过多态统一操作接口;
    • Spring 框架中,依赖注入(DI)通过多态实现对象的灵活替换。

总结:多态是 OOP 中实现代码复用和灵活扩展的核心机制,其底层依赖动态绑定,理解多态是掌握面向对象编程的关键。

7.11 Object类详解

Object 类是 Java 中所有类的根类(超类),任何类都直接或间接继承自 Object 类(包括数组)。如果一个类没有显式声明父类,编译器会默认使其继承 Object 类。
Object 类定义了所有对象都具备的基本方法,掌握这些方法是理解 Java 面向对象特性的基础。

  • 7.11.1 Object 类的常用方法

  1. toString() 方法
  • 作用:返回对象的字符串表示(默认格式为 类名@哈希码的十六进制,如 com.example.Person@1b6d3586)。
  • 实际用途:通常在子类中重写,用于返回对象的 “可读性信息”(如属性值),方便打印和调试。
    示例:
class Person {
    String name;
    int age;
    
    // 重写toString()
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        p.name = "张三";
        p.age = 20;
        System.out.println(p); // 等价于 System.out.println(p.toString())
        // 输出:Person{name='张三', age=20}
    }
}
  1. equals() 方法
  • 作用:判断两个对象是否 “相等”(默认比较地址值,即是否为同一个对象)。
  • 注意:== 对于引用类型也比较地址值,因此 Object 类的 equals() 与 == 效果相同。
  • 实际用途:子类通常重写 equals(),按 “内容相等” 判断(如两个 Person 对象的 name 和 age 相同则认为相等)。
    示例(重写 equals()):
class Person {
    String name;
    int age;
    
    @Override
    public boolean equals(Object obj) {
        // 1. 若地址相同,直接返回true
        if (this == obj) return true;
        // 2. 若obj为null或类型不同,返回false
        if (obj == null || getClass() != obj.getClass()) return false;
        // 3. 转换类型后比较属性
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
}
  1. hashCode() 方法
  • 作用:返回对象的哈希码(一个 int 值),主要用于哈希表(如 HashMap、HashSet)中快- - 速定位对象。
  • 核心约定:
    若两个对象 equals() 返回 true,则它们的 hashCode() 必须相等;
    若两个对象 hashCode() 不等,则 equals() 一定返回 false(反之不成立)。
  • 实际用途:重写 equals() 时必须同时重写 hashCode(),否则会导致哈希表存储异常。
    示例(重写 hashCode()):
@Override
public int hashCode() {
    return 31 * name.hashCode() + age; // 结合属性计算哈希码
}
  1. getClass() 方法
  • 作用:返回对象的运行时类型(Class 对象),用于反射编程。
  • 特点:返回的是对象实际类型(多态中体现为子类类型),且方法是 final 的,不能被重写。
    示例:
Animal a = new Dog();
System.out.println(a.getClass()); // 输出:class com.example.Dog(实际类型)
System.out.println(a.getClass() == Dog.class); // true
  1. clone() 方法
  • 作用:创建并返回对象的 “副本”(默认是浅拷贝:基本类型复制值,引用类型复制地址)。
  • 使用条件:
  • 类必须实现 Cloneable 接口(标记接口,无实际方法);
  • 重写 clone() 方法(默认是 protected,需改为 public)。
运行
class Student implements Cloneable {
    String name;
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // 调用父类clone()
    }
}

// 使用
Student s1 = new Student();
s1.name = "李四";
Student s2 = (Student) s1.clone(); // 克隆对象
  1. 线程相关方法
  • wait():使当前线程进入等待状态,直到被 notify() 或 notifyAll() 唤醒。
  • notify():唤醒在此对象监视器上等待的单个线程。
  • notifyAll():唤醒在此对象监视器上等待的所有线程。
    这些方法用于多线程通信,必须在 synchronized 同步块中使用。
  1. finalize() 方法
  • 作用:垃圾回收器回收对象前调用,用于释放资源(如关闭文件、网络连接)。

  • 注意:
    执行时机不确定,不建议依赖此方法释放资源;
    Java 9 后已标记为过时(@Deprecated),推荐使用 try-with-resources 替代。

  • 7.11.2、核心总结

  • Object 是所有类的父类,定义了对象的通用行为;

  • 最常用的方法是 toString()、equals()、hashCode(),子类通常需要重写;

  • equals() 与 hashCode() 需同时重写,遵循 “相等对象必须有相等哈希码” 的约定;

  • getClass() 用于获取对象实际类型,clone() 用于对象拷贝,线程方法用于多线程通信。

  • 理解 Object 类的方法是掌握 Java 面向对象编程的基础,尤其在集合、多线程等场景中频繁使用。

7.12 断点调试

  • 7.12.1一个实际需求

    image-20250807000126919

  • 7.12.2 断点调试介绍

    image-20250807000146536

  • 7.12.3 断点调试的快捷键

    F7(跳入) F8(跳过) shift+F8(跳出)F9(resume,执行到下一个断点)

    F7:跳入方法内

    F8: 逐行执行代码.

    shift+F8: 跳出方法

posted @ 2025-08-07 00:07  *珍惜当下*  阅读(13)  评论(0)    收藏  举报