JAVA进阶之路——无奖问答挑战4

JAVA问答

  • [Q1 lock 和 synchronized 有什么区别](#Q1 lock 和 synchronized 有什么区别)
      • [Java 中 Lock 与 Synchronized 的对比](#Java 中 Lock 与 Synchronized 的对比)
        • [1. 功能角度](#1. 功能角度)
        • [2. 特性角度](#2. 特性角度)
        • [3. 性能角度](#3. 性能角度)
  • [Q2 多态性如何实现?](#Q2 多态性如何实现?)

Q1 lock 和 synchronized 有什么区别

Java 中 Lock 与 Synchronized 的对比

1. 功能角度
  • 共同点:Lock 和 synchronized 都是 Java 中用来解决线程安全问题的工具。
2. 特性角度
  • 类型与实现
    • synchronized:是 Java 中的同步关键字。
    • Lock:是 JUC 包里面提供的一个接口,有很多实现类(如 ReentrantLock 重入锁)。
  • 锁的粒度与作用范围
    • synchronized:
      • 粒度 :可通过修饰方法代码块来控制。
      • 范围:取决于加锁对象的生命周期(静态/类对象为全局锁,普通实例对象取决于实例生命周期)。
    • Lock:
      • 粒度:通过 lock() 和 unlock() 方法包裹代码来决定。
      • 范围:取决于 Lock 实例的生命周期。
  • 灵活性
    • Lock 更灵活,可自主决定加锁和释放锁的时间。
    • Lock 提供了 tryLock() 方法,支持非阻塞竞争锁(返回 true/false),而 synchronized 无法实现此功能。
  • 锁释放机制
    • synchronized:释放是被动的(同步代码块执行结束或出现异常时)。
    • Lock:需手动释放(调用 unlock() 方法)。
  • 公平锁机制
    • Lock:支持公平锁(排队,不插队)和非公平锁(尝试插队)。
    • synchronized:只提供了一种非公平锁的实现。
3. 性能角度
  • 总体表现:两者在性能方面相差不大,但实现机制不同。
  • synchronized:引入了偏向锁、轻量级锁、重量级锁以及锁升级机制来实现优化。
  • Lock:用到了自旋锁的方式去实现性能优化。

Q2 多态性如何实现?

在 Java 中,多态性(Polymorphism)是面向对象编程(OOP)的三大核心特性之一,其核心思想是**"同一个行为,具有多种不同的实现"**。通俗地说,就是 ** "父类引用指向子类对象" ** ,并在运行时根据实际对象的类型来决定调用哪个方法。

在 Java 中,多态的实现主要依赖于运行时多态(动态绑定) ,同时也包含编译时多态(静态绑定)。以下我将为你详细拆解这两种实现方式,重点是运行时多态的底层原理。

1. 运行时多态(动态绑定)------ 核心机制

这是 Java 多态最常用、也是最核心的实现方式,它允许程序在运行时才确定具体调用哪个类的方法。

实现条件(缺一不可)

要实现运行时多态,必须同时满足以下三个条件:

  1. 继承关系 :必须存在类的继承(extends)或接口的实现(implements)。
  2. 方法重写 :子类必须重写(@Override)父类的方法。
  3. 向上转型 :必须使用父类的引用 指向子类的对象 (例如:Parent p = new Child();)。
代码示例
java 复制代码
// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

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

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

// 测试类
public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Dog(); // 向上转型:父类引用指向子类对象
        Animal animal2 = new Cat(); 
        
        animal1.makeSound(); // 输出:汪汪
        animal2.makeSound(); // 输出:喵喵
    }
}

在上面的代码中,虽然 animal1animal2 的引用类型都是 Animal,但调用 makeSound() 方法时,实际执行的是它们各自子类中重写后的方法。

底层实现原理:动态绑定与方法表

Java 是如何做到这一点的?这依赖于 JVM 的动态绑定(Dynamic Binding)机制和方法表(Method Table)

  1. 编译期检查 :在编译阶段,编译器只看引用变量的类型(左边)。它会检查 Animal 类中是否有 makeSound() 方法。如果有,编译通过;如果没有,报错。此时并不确定具体执行哪个类的代码。
  2. 运行期决议 :在程序运行时,JVM 会通过对象的实际类型(右边,即 new 出来的对象)去查找该类的方法表
  3. 虚方法调用 :JVM 发现 makeSound() 是一个虚方法(非 static、非 private、非 final),它会去实际对象(如 Dog)的方法表中查找该方法的直接引用。
  4. 调用执行 :JVM 调用的是实际对象(DogCat)中重写后的方法。

注意 :这种机制也被称为"晚绑定"。如果方法是 staticprivatefinal 的,它们不参与多态,因为它们在编译期就已经确定了调用版本(静态绑定)。

2. 编译时多态(静态绑定)

虽然通常提到多态指的都是运行时多态,但 Java 中也存在编译时多态。

  • 实现方式方法重载(Overloading)。
  • 原理 :在同一个类中,允许存在多个同名方法,只要它们的参数列表(参数类型、个数、顺序)不同。编译器在编译代码时,就会根据你传入的参数类型和数量,直接确定调用哪一个具体的方法。
  • 特点:发生在编译期,与继承无关。

3. 总结:多态的实现方式对比

特性 编译时多态 (静态) 运行时多态 (动态)
实现机制 方法重载 (Overloading) 方法重写 (Overriding) + 向上转型
绑定时机 编译期 (Compiler Time) 运行期 (Runtime)
核心依据 方法的参数列表 对象的实际类型 (JVM 动态查找)
性能开销 无运行时开销 有轻微的查表开销 (方法表查找)
灵活性 较低 高 (支持"开闭原则",易于扩展)

4. 为什么使用多态?

  • 消除类型之间的耦合关系:调用者只需要关注父类或接口定义的行为,而不需要知道具体的子类是谁。
  • 可扩展性强 :如果需要增加新功能(例如新增一个 Bird 类继承 Animal),只需要让新类继承父类并重写方法,无需修改已有的调用代码(如 Test 类中的逻辑)。

简单总结:Java 多态的实现就是**"继承做基础,重写做前提,父类引用指向子类对象,JVM 运行时查表调用"**。

相关推荐
寻寻觅觅☆10 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
l1t11 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划11 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿11 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar12312 小时前
C++使用format
开发语言·c++·算法
探路者继续奋斗12 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd
码说AI12 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS12 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子12 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗12 小时前
初识C++
开发语言·c++