7.JAVA 面向对象编程
7.面向对象编程
7.1 IDE(集成开发环境)-IDEA
- IDEA 全称 IntelliJ IDEA
- 在业界被公认为最好的Java开发工具
- IDEA是JetBrains 公司的产品,总部位于捷克的首都布拉格
- 除了支持Java开发,还支持HTML,CSS,PHP,MySQL,Python等
7.2IDE(集成开发环境)-Eclipse
- Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。
- 最初是由IBM 公司耗资3000万美金开发的下一代IDE开发环境
- 2001 年11月贡献给开源社区
- Eclipse 是目前最优秀的Java开发IDE之一
7.3 IDE(集成开发环境)-IDEA的使用
[ 官网:] (https://www.jetbrains.com)
IDEA 常用快捷键
- 删除当前行, 默认是ctrl+Y 自己配置 ctrl+d
- 复制当前行, 自己配置 ctrl+alt+ 向下光标
- 补全代码 alt+/
- 添加注释和取消注释 ctrl+/ 【第一次是添加注释,第二次是取消注释】
- 导入该行需要的类 先配置autoimport, 然后使用 alt+enter即可
- 快速格式化代码 ctrl+alt+L
- 快速运行程序 自己定义 alt+R
- 生成构造器等 alt+insert [提高开发效率]
- 查看一个类的层级关系 ctrl+H [学习继承后,非常有用]
- 将光标放在一个方法上,输入 ctrl+B, 可以定位到方法 [学继承后,非常有用
- 自动的分配变量名 , 通过 在后面假 .var
- 还有很多其它的快捷键...
7.4 包
7.4.1 应用场景
当 Java 项目规模扩大,类和接口数量增多时,容易出现命名冲突问题。包提供了一种层级化的命名空间机制,可将相关类 / 接口组织在一起。例如:
- 开发电商系统时,可将订单相关类放在
com.company.order
包 - 用户相关类放在
com.company.user
包 - 工具类放在
com.company.utils
包
7.4.2 包的三大作用
- 解决命名冲突:不同包中可以有同名类,通过全限定名(包名 + 类名)区分
- 实现访问控制:配合访问修饰符(如
protected
)控制类成员的访问范围 - 便于代码组织:按功能或模块分类管理类,提高代码可维护性和可读性
7.4.3 包基本语法
-
定义包:
package com.company.module; // 必须放在Java文件第一行
-
导入包:
import com.company.utils.Tool; // 导入特定类 import com.company.utils.*; // 导入包中所有类 import static java.lang.Math.PI; // 静态导入
-
使用类:
// 方式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 语言的核心包,无需手动导入,默认自动加载。
-
主要内容
:
- 基本数据类型包装类(
Integer
、Double
等) - 字符串类(
String
、StringBuilder
) - 系统类(
System
、Runtime
) - 线程类(
Thread
、Runnable
) - 异常类(
Exception
、RuntimeException
)
- 基本数据类型包装类(
2. java.util
-
特点:工具类包,提供大量实用工具和数据结构。
-
主要内容
:
- 集合框架(
List
、Set
、Map
及其实现类如ArrayList
、HashMap
) - 日期时间类(
Date
、Calendar
、Java 8 + 的LocalDateTime
) - 随机数生成(
Random
) - 工具类(
Arrays
、Collections
用于集合 / 数组操作)
- 集合框架(
3. java.io
-
特点:输入输出包,用于处理文件和流操作。
-
主要内容
:
- 字节流(
InputStream
、OutputStream
) - 字符流(
Reader
、Writer
) - 文件操作(
File
、FileInputStream
)
- 字节流(
4. java.net
-
特点:网络编程包,支持 TCP/IP、UDP 等网络通信。
-
主要内容
- 网络连接(
Socket
、ServerSocket
)
- 网络连接(
-
URL 处理(
URL
、URLConnection
)- 网络接口(
InetAddress
)
5.
java.sql
-
特点:数据库操作包,提供 JDBC(Java 数据库连接)接口。
-
主要内容
- 数据库连接(
Connection
)
- 数据库连接(
- 网络接口(
-
SQL 执行(
Statement
、PreparedStatement
)- 结果集(
ResultSet
)
6.
java.awt
与javax.swing
-
特点:图形用户界面(GUI)开发包。
-
主要内容
java.awt
:基础 GUI 组件(如Frame
、Button
),依赖本地系统外观。
- 结果集(
-
javax.swing
:轻量级 GUI 组件(如JFrame
、JButton
),跨平台统一外观。7.
java.math
-
特点:高精度数学运算包。
-
主要内容
BigInteger
:任意精度整数运算。
-
-
BigDecimal
:高精度小数运算,避免浮点数误差。8.
java.text
-
特点:文本处理包,用于格式化和解析。
-
主要内容
- 日期格式化(
SimpleDateFormat
)
- 日期格式化(
-
-
数字格式化(
NumberFormat
)这些包是 Java 开发的基础,掌握其核心类和功能能显著提高开发效率。实际开发中,还会结合第三方包(如
org.springframework
、com.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封装的理解和好处
- 隐藏实现细节:例如方法(连接数据库等复杂操作),外部调用只需传入参数,无需知晓内部实现流程。
- 保证数据安全合理:以
Person {name, age}
为例,若直接赋值p.age = 1200;
会出现不合理数据,通过封装可避免这类问题,如下代码演示直接赋值的问题:
Person p = new Person(); p.name = "jack"; p.age = 1200; // 年龄数值不合理,但未做限制
-
7.6.4 封装的实现步骤(三步)
- 属性私有化:用
private
修饰属性,使其不能直接被外部修改,代码示例:
private 数据类型 属性名; // 如 private String name;
- 提供公共
set
方法:用于对属性判断并赋值,可加入数据验证逻辑,语法模板:
public void setXxx(类型 参数名){ // 数据验证的业务逻辑,如年龄范围判断 属性 = 参数名; } // 示例(以 Person 类 age 属性为例) public void setAge(int age) { if(age > 0 && age < 150) { // 简单年龄验证 this.age = age; } else { System.out.println("年龄数值不合理"); } }
- 提供公共
get
方法:用于获取属性的值,可按需加入权限判断,语法模板:
public 数据类型 getXxx(){ return xx; } // 示例(以 Person 类 age 属性为例) public int getAge() { return this.age; }
通过这三步,既能保护属性安全,又能规范对属性的操作,是实现封装的核心流程 。
- 属性私有化:用
7.8 面向对象编程-继承
-
7.8.1为什么需要继承
-
7.8.2继承基本介绍和示意图
继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中 抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends声明继承父类即可。画出继承的示意图
-
7.8.3继承的基本用法
class 子类 extends 父类{ } 1. 子类的就会自动拥有父类定义的属性和方法 2. 父类又叫超类,基类 3. 子类又叫派生类
-
7.8.5继承给编程带来的便利
- 代码的复用性提高了
- 代码的扩展性和维护性提高了
-
7.8.5继承细节问题
-
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有的属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
-
子类必须调用父类的构造器,完成父类的初始化
-
当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
-
如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
-
super在使用时,必须放在构造器第一行(super
()
(调用父类构造器)只能在构造器中使用)super` 关键字还可以在非静态方法中使用,用于访问父类的成员,此时没有位置限制
-
super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
-
java所有类都是Object类的子类,Object是所有类的基类.
-
父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
-
子类最多只能继承一个父类(指直接继承),即java中是单继承机制。 思考:如何让A类继承B类和C类?【A继承B,B继承C】
-
不能滥用继承,子类和父类之间必须满足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="大头儿子"; }
子类创建的内存布局
7.9super关键字
-
7.9.1基本介绍
super代表父类的引用,用于访问父类的属性、方法、构造器
-
7.9.2基本语法
-
访问父类的属性,但不能访问父类的private属性 super.属性名
-
访问父类的方法,但不能访问父类的private方法 super.方法名(参数列表)
-
访问父类的构造器 super(参数列表)
只能放在构造器的第一句只能出现一句
-
-
7.9.3super 给编程带来的便利/细节
-
7.9.4super 和 this 的比较
7.10 方法重写/覆盖(override)
-
7.10.1 基本介绍
简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法
-
7.10.2 注意事项和使用细节
-
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();
(父类引用指向子类对象,多态的基础);//向上转型调用方法的规则如下: //(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;
(需先判断类型,避免类型转换异常)。//多态的向下转型 //(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 个注意事项和细节
-
父类引用不能直接调用子类独有的方法
多态下,父类引用只能访问父类中声明的方法(或子类重写的方法),无法直接调用子类特有的方法。若需调用,必须先 “向下转型” 为子类类型。
示例: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(); // 正确 } } }
-
多态下,方法调用看 “子类重写”,属性访问看 “父类”
- 方法:运行时调用子类重写的版本(动态绑定);
- 属性:编译和运行都看父类(属性不参与多态)。
示例:
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(调用子类重写方法)
}
}
-
向上转型(安全)与向下转型(需谨慎)
- 向上转型:
Parent p = new Child();
总是安全的(子类是父类的 “一种”); - 向下转型:必须通过
instanceof
判断实际类型,否则可能抛出
- 向上转型:
Parent p = new Dog();
// if (!(p instanceof Cat)) { ... } 若直接转Cat会报错
if (p instanceof Dog) {
Dog d = (Dog)p; // 正确
}
-
静态方法不参与多态
静态方法属于 “类” 而非 “对象”,调用时由 “引用的类型”(编译时类型)决定,与对象实际类型无关。示例:
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(看父类类型)
}
}
```
-
构造器的调用顺序影响多态初始化
子类构造器执行时,会先调用父类构造器。若父类构造器中调用了 “被子类重写的方法”,则会触发子类的重写方法(此时子类属性可能未初始化,需特别注意)。示例(风险场景):
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 多态的应用场景
多态的核心价值是 “统一接口,灵活扩展”,在实际开发中应用广泛:
-
简化代码,统一调用
用父类作为方法参数,可接收所有子类对象,无需为每个子类编写单独方法。示例:
java
// 统一处理所有动物的方法
public static void letAnimalCry(Animal animal) {
animal.cry(); // 传入Cat则猫叫,传入Dog则狗叫
}
public static void main(String[] args) {
letAnimalCry(new Cat()); // 猫喵喵叫
letAnimalCry(new Dog()); // 狗汪汪叫
}
```
-
提高扩展性
新增子类时,无需修改原有代码(符合 “开闭原则”)。示例:若新增 “猪” 类(
Pig extends Animal
),letAnimalCry
方法无需修改即可直接使用。 -
框架与设计模式的基础
多数设计模式(如工厂模式、策略模式)依赖多态实现。例如:- 集合框架中,
List list = new ArrayList();
或List list = new LinkedList();
,通过多态统一操作接口; - Spring 框架中,依赖注入(DI)通过多态实现对象的灵活替换。
- 集合框架中,
总结:多态是 OOP 中实现代码复用和灵活扩展的核心机制,其底层依赖动态绑定,理解多态是掌握面向对象编程的关键。
7.11 Object类详解
Object 类是 Java 中所有类的根类(超类),任何类都直接或间接继承自 Object 类(包括数组)。如果一个类没有显式声明父类,编译器会默认使其继承 Object 类。
Object 类定义了所有对象都具备的基本方法,掌握这些方法是理解 Java 面向对象特性的基础。
-
7.11.1 Object 类的常用方法
- 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}
}
}
- 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);
}
}
- hashCode() 方法
- 作用:返回对象的哈希码(一个 int 值),主要用于哈希表(如 HashMap、HashSet)中快- - 速定位对象。
- 核心约定:
若两个对象 equals() 返回 true,则它们的 hashCode() 必须相等;
若两个对象 hashCode() 不等,则 equals() 一定返回 false(反之不成立)。 - 实际用途:重写 equals() 时必须同时重写 hashCode(),否则会导致哈希表存储异常。
示例(重写 hashCode()):
@Override
public int hashCode() {
return 31 * name.hashCode() + age; // 结合属性计算哈希码
}
- getClass() 方法
- 作用:返回对象的运行时类型(Class 对象),用于反射编程。
- 特点:返回的是对象实际类型(多态中体现为子类类型),且方法是 final 的,不能被重写。
示例:
Animal a = new Dog();
System.out.println(a.getClass()); // 输出:class com.example.Dog(实际类型)
System.out.println(a.getClass() == Dog.class); // true
- 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(); // 克隆对象
- 线程相关方法
- wait():使当前线程进入等待状态,直到被 notify() 或 notifyAll() 唤醒。
- notify():唤醒在此对象监视器上等待的单个线程。
- notifyAll():唤醒在此对象监视器上等待的所有线程。
这些方法用于多线程通信,必须在 synchronized 同步块中使用。
- 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一个实际需求
-
7.12.2 断点调试介绍
-
7.12.3 断点调试的快捷键
F7(跳入) F8(跳过) shift+F8(跳出)F9(resume,执行到下一个断点)
F7:跳入方法内
F8: 逐行执行代码.
shift+F8: 跳出方法