【Java】Java核心要点总结 68

简介: 1. 为什么重写 equals() 时候必须重写 hashCode()因为两个相等的对象的 hashCode 值必须是相等。也就是说如果 equals 方法判断两个对象是相等的,那这两个对象的 hashCode 值也要相等。如果重写 equals() 时没有重写 hashCode() 方法的话就可能会导致 equals 方法判断是相等的两个对象,hashCode 值却不相等。

1. 为什么重写 equals() 时候必须重写 hashCode()

因为两个相等的对象的 hashCode 值必须是相等。也就是说如果 equals 方法判断两个对象是相等的,那这两个对象的 hashCode 值也要相等。


如果重写 equals() 时没有重写 hashCode() 方法的话就可能会导致 equals 方法判断是相等的两个对象,hashCode 值却不相等。

2. 字符串常量池


字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。

3. 字符串中的 intern() 方法

String.intern() 是一个 native(本地)方法,其作用是将指定的字符串对象的引用保存在字符串常量池中,可以简单分为两种情况:


● 如果字符串常量池中保存了对应的字符串对象的引用,就直接返回该引用。


● 如果字符串常量池中没有保存了对应的字符串对象的引用,那就在常量池中创建一个指向该字符串对象的引用并返回。

4. try-catch-finally

注意:不要在 finally 语句块中使用 return! 当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。


以下代码会输出啥:

int a = 10;
try {
    int b = a / 0;
    return a;
}catch (Exception e){
    return 20;
}finally {
    a =  30;
    return a;
}
int a = 10;
try {
    int b = a / 0;
    return a;
}catch (Exception e){
    return 20;
}finally {
    a =  30;
}
int a = 10;
try {
    int b = a / 1;
    return a;
}catch (Exception e){
    return 20;
}finally {
    a =  30;
}

详解

    执行流程:
            1. 先计算返回值, 并将返回值存储起来, 等待返回
            2. 执行finally代码块
            3. 将之前存储的返回值, 返回出去;
    需注意:
            1. 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不会改变。 SO:

5. finally 中的代码不一定会执行


在编程中,使用try-catch-finally块时,finally中的代码确实有些情况下可能不会执行。以下是几种情况:

程序终止:如果在try或catch块之前发生了无法恢复的错误或程序异常终止,那么finally中的代码将不会执行。


线程终止:如果在try或catch块中的线程被强制终止,那么finally中的代码也不会执行。


关闭JVM:如果在try或catch块中关闭了Java虚拟机(JVM),则finally中的代码不会执行。


需要注意的是,这些情况属于异常情况,一般情况下finally中的代码都会执行。finally块通常用于确保资源的释放或清理,无论是否有异常抛出。

相关文章
|
安全 Java 数据库连接
【Java】Java核心要点总结:62
1. 线程中的线程是怎么创建的,是一开始就随着线程池的启动创建好的吗? 线程中的线程通常是通过在父线程中创建新的Thread对象并将其加入线程池中实现的。当然,这个过程也可以通过一些其他的方式来实现,比如使用ExecutorService.submit()方法提交一个Callable或Runnable任务。
|
缓存 安全 Java
【Java】Java核心要点总结70
1. volatile 如何保证变量的可⻅性? 在Java中,使用volatile关键字可以确保变量的可见性。 当一个线程修改了一个被volatile修饰的变量时,它会立即将该变量的最新值刷新到主内存。而其他线程在读取该变量时,会从主内存中重新获取最新值,而不是使用缓存中的旧值。 这样做的原因是,普通的变量在多线程环境下存在线程间不可见的问题。每个线程都有自己的工作内存,由于运行速度快和编译优化等原因,线程可能会直接读取工作内存中的旧值,而不去主内存中获取最新的值,导致线程之间的数据不一致。
|
2月前
|
消息中间件 NoSQL Java
Java知识要点及面试题
该文档涵盖Java后端开发的关键知识点,包括Java基础、JVM、多线程、MySQL、Redis、Spring框架、Spring Cloud、Kafka及分布式系统设计。针对每个主题,文档列举了重要概念及面试常问问题,帮助读者全面掌握相关技术并准备面试。例如,Java基础部分涉及面向对象编程、数据类型、异常处理等;JVM部分则讲解内存结构、类加载机制及垃圾回收算法。此外,还介绍了多线程的生命周期、同步机制及线程池使用,数据库设计与优化,以及分布式系统中的微服务、RPC调用和负载均衡等。
|
缓存 监控 Java
【Java】Java核心要点总结:61
1. java中的线程池是如何实现的 Java 中的线程池是通过 ThreadPoolExecutor 类实现的。ThreadPoolExecutor 继承自 AbstractExecutorService,并实现了 Executor、ExecutorService 和 Future 接口,它可以为程序提供管理和控制多个工作者线程的功能,提高线程重用性并避免线程频繁创建销毁的开销。
|
监控 安全 Java
Java面试题-Java核心基础
Java面试题-Java核心基础
104 2
|
算法 安全 Java
【Java】Java核心要点总结:58
1. java中 怎么确保一个集合不能被修改 Java 中可以使用 Collections 类的 unmodifiableXXX() 方法来确保一个集合不能被修改。其中,XXX 表示需要被转换的集合类型,如 List、Set、Map 等。这些方法都返回指定集合的不可修改视图
|
算法 安全 Java
【Java】Java核心要点总结:59
1. 线程的run()和start()有什么区别,为什么不直接调用run() Java中通过继承 Thread 或实现 Runnable 接口来创建线程,线程是通过 start() 方法启动的,而不是直接调用 run() 方法。下面是它们之间的区别: start() 和 run() 的区别 调用 start() 方法会启动一个新线程并执行其中的 run() 方法,而直接调用 run() 方法将在当前线程中执行 run() 方法,并不会创建新的线程。
|
存储 缓存 Java
【Java】Java核心要点总结 66
1. 成员变量 和 局部变量 的区别 ● 语法形式 :从语法形式上看,成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。 ● 存储方式 :从变量在内存中的存储方式来看,如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,如果没有使用 static 修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
|
存储 Java 程序员
【Java】Java核心要点总结 69
1. BIO NIO AIO 在Java中,BIO、NIO和AIO是针对网络编程的不同I/O模型: BIO(Blocking I/O):传统的阻塞式I/O模型,它以阻塞的方式进行数据读写操作。当一个线程执行I/O操作时,会被阻塞,直到数据准备好或者操作完成。这种模型相对简单,但对并发处理能力较弱。 NIO(Non-blocking I/O):非阻塞式I/O模型,引入了选择器(Selector)和通道(Channel)的概念。使用NIO,可以通过一个线程处理多个通道的I/O操作,提升了并发处理能力。但需要手动检查是否有数据可用,必要时才进行读写操作。
|
安全 Java API
【Java】Java核心要点总结:60
1. 乐观锁一定就是好的吗 乐观锁并不一定好,它有自己的适用场景和局限性。 乐观锁的优点在于在低并发环境下表现良好,操作基本上都能够成功,不会阻塞其他线程的执行。此外,乐观锁没有锁带来的资源竞争和多线程间的上下文切换开销,对于高并发的场景下可以提供更好的性能表现。 但是,在高并发场景下乐观锁的表现往往受到影响,因为多个线程同时执行操作和检查比较,会出现重试次数增加的情况,进而增加了延迟和开销,降低了系统的吞吐量和性能。此时,悲观锁可能比乐观锁更适合解决问题,因为它能够阻塞其他线程,等待当前线程释放锁后再执行。