Java基础面试题(三)

1. == 和 equals 的区别?

  • == 操作符
    • == 是一个比较操作符,用于比较两个对象的引用是否相等。也就是说,它检查两个对象引用是否指向内存中的同一位置。
    • 对于基本数据类型(如 int, char, boolean 等),== 用于比较它们的值是否相等。
    • 对于对象引用,== 比较的是引用的地址,而不是对象的内容。因此,即使两个对象的内容完全相同,如果它们是不同的对象实例(即,它们有不同的内存地址),== 也会返回 false
  • equals() 方法
    • equals()Object 类中的一个方法,所有Java对象都继承了这个方法。默认情况下,Object 类中的 equals() 方法的行为与 == 相同,即比较对象的引用是否相等。
    • 但是,许多类(如 String, Integer, Date 等)都重写了 equals() 方法,以便提供更有意义的比较。在这些类中,equals() 通常用于比较对象的内容是否相等,而不是比较引用是否相等。
    • 因此,当使用这些重写了 equals() 方法的类时,你应该使用 equals() 而不是 == 来比较对象的内容是否相等。

示例

String str1 = new String("hello");
String str2 = new String("hello");// 使用 == 比较
System.out.println(str1 == str2); // 输出 false,因为 str1 和 str2 是不同的对象实例// 使用 equals() 比较
System.out.println(str1.equals(str2)); // 输出 true,因为 str1 和 str2 的内容相同

例子中,尽管 str1str2 引用的是不同的对象实例(即它们有不同的内存地址),但它们的内容是相同的。因此,使用 == 比较时返回 false,而使用 equals() 比较时返回 true

2. 两个对象的 hashCode() 相同,则 equals() 也一定为 true 吗?

在Java中,两个对象的hashCode()相同,并不意味着它们的equals()方法也一定返回truehashCode()equals()方法之间并没有强制性的约束关系,尽管它们经常一起使用,并且根据Java的约定,它们之间应该存在一定的关系。

Java的Object类规定:

  • 如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象的hashCode方法必须产生相同的整数结果。
  • 如果两个对象根据equals(java.lang.Object)方法是不相等的,那么调用这两个对象中任一对象的hashCode方法,不要求必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

这意味着:

  • 如果两个对象相等(即equals()返回true),则它们的hashCode()必须相同。
  • 如果两个对象的hashCode()相同,这并不意味着它们一定相等。hashCode()主要用于哈希表等数据结构中,以提高查找效率,而equals()用于确定两个对象在逻辑上是否相等。

例如,考虑一个Person类,它有两个属性:nameage。如果两个Person对象具有相同的name但不同的age,它们的hashCode()可能会因为name属性的相同而相同,但equals()会因为age属性的不同而返回false

因此,不能仅根据两个对象的hashCode()是否相同来判断它们是否相等。正确的做法是先比较hashCode(),如果相同再调用equals()进行进一步比较。但即使hashCode()不同,也不意味着equals()就一定返回false,因为不同的对象也可能有相同的哈希码(尽管这种情况应该尽量避免,以提高哈希表的性能)。

3. 为什么重写 equals() 就一定要重写 hashCode() 方法?

重写equals()方法时通常也建议重写hashCode()方法,这主要是基于以下几个原因:

  1. Java规范的要求:Java的Object类的规范明确指出了如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象的hashCode方法必须产生相同的整数结果。如果你重写了equals()方法但没有重写hashCode()方法,这可能会违反这个约定。
  2. 哈希表性能:当你使用哈希表(如HashMap, HashSet等)时,对象的hashCode()被用来确定对象在哈希表中的存储位置。如果两个对象根据equals()是相等的,但它们的hashCode()不同,那么哈希表可能无法正确地识别这两个对象是相等的,从而导致性能下降或逻辑错误。
  3. 一致性:保持equals()hashCode()的一致性对于对象的行为来说是重要的。如果两个对象在逻辑上是相等的(即equals()返回true),但它们的hashCode()不同,这会导致一些依赖于这两个方法一致性的代码出现问题。
  4. 合同(Contract)的保持:在Java中,类通常被设计为具有特定的行为或“合同”。如果一个类重写了equals()方法,但没有相应地重写hashCode()方法,那么它就不完全遵守Object类的合同,这可能会导致在与其他类交互时出现意外行为。

因此,当你重写equals()方法时,通常也应该重写hashCode()方法,以确保它们的行为一致,并满足Java规范的要求。这样,你的对象就可以正确地与哈希表等数据结构一起使用,并避免潜在的逻辑错误和性能问题。

重写hashCode()方法时,一般遵循以下规则:

  • 如果两个对象根据equals(Object)方法是相等的,那么调用这两个对象的hashCode方法必须产生相同的整数结果。
  • 如果两个对象根据equals(java.lang.Object)方法是不相等的,那么调用这两个对象中任一对象的hashCode方法,并不要求必须产生不同的整数结果,但是程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

在实际编程中,可以使用IDE(如IntelliJ IDEA或Eclipse)提供的自动生成hashCode()equals()方法的工具,以确保它们被正确地重写。

4. & 和 && 的区别?

&&&都是逻辑运算符,用于进行逻辑与运算,但它们之间存在几个关键的区别:

  1. 短路功能&&具有短路的功能,即如果第一个表达式的结果为false,则整个表达式的结果就确定为false,并且不再计算第二个表达式。而&不具备这种短路功能,它会计算所有的表达式。
  2. 效率:由于&&具有短路功能,当第一个条件不满足时,它不会继续判断后面的条件,因此在某些情况下,使用&&可能比使用&更高效。
  3. 返回值类型:当用作逻辑运算符时,&&&的返回值类型都是boolean。然而,&还可以作为位运算符使用,当&两边的表达式不是boolean类型时,它表示按位与操作。例如,我们通常使用0x0f来与一个整数进行&运算,以获取该整数的最低4个bit位。
  4. 使用范围&&是编程语言中的符号,主要用在c、c++、Java、PHP等编程语言中。而&符号的使用范围更广泛,它不但能用在编程语言中,还能用在HTML文档中表示“and”或“联合”的意思,以及在电子制表程序中。

&&&在功能、效率、返回值类型和使用范围等方面存在区别。在选择使用哪一个时,需要根据具体的需求和场景来决定。

5. Java 中的参数传递时传值呢?还是传引用?

Java 中的参数传递是传值的,但这里的“值”对于基本数据类型(如 int, char, boolean, double, float, long, short, byte)和引用类型(如对象、数组)来说,含义有所不同。

  1. 基本数据类型
    对于基本数据类型,Java 直接传递它们的值。当你在方法内修改这个值时,它不会影响方法外的那个变量。

    public class Test {public static void main(String[] args) {int x = 10;modify(x);System.out.println(x); // 输出 10,而不是修改后的值}public static void modify(int y) {y = 20;}
    }
    
  2. 引用类型
    对于引用类型,Java 传递的是引用的值,即对象的内存地址的拷贝。这意味着你不能通过参数来直接修改原始引用本身使其指向一个新的对象,但你可以修改引用所指向对象的状态(即对象的属性)。

    public class Test {static class MyObject {int value;}public static void main(String[] args) {MyObject obj = new MyObject();obj.value = 10;modify(obj);System.out.println(obj.value); // 输出 20,因为对象的状态被修改了}public static void modify(MyObject objRef) {objRef.value = 20; // 修改对象的状态// objRef = new MyObject(); // 这不会改变 main 方法中的 obj 引用}
    }
    

在上面的例子中,modify 方法接收的是 obj 引用的拷贝(objRef),所以通过 objRef 修改对象的 value 属性会影响原始对象。但是,如果你试图在 modify 方法中让 objRef 指向一个新的 MyObject 实例,那么 main 方法中的 obj 引用不会受到任何影响。

总的来说,Java 总是通过值来传递参数,对于引用类型,传递的是引用的值(即内存地址的拷贝),而不是引用的本身。这意味着你不能通过方法参数来直接改变一个引用变量使其指向新的对象,但你可以改变它所指向对象的内部状态。

6. Java 中的 Math.round(-1.5) 等于多少?

Math.round() 方法用于四舍五入一个 double 类型的数值,返回一个 long 类型的整数。当对一个负数进行四舍五入时,它会向零的方向进行舍入。

对于 Math.round(-1.5),因为 -1.5 介于 -2-1 之间,且四舍五入时它会向零的方向舍入,所以,Math.round(-1.5) 在Java中等于 -1

7. 如何实现对象的克隆?

在Java中,实现对象的克隆主要有两种方式:浅克隆(Shallow Clone)和深克隆(Deep Clone)。这两种方式的主要区别在于它们处理对象中的引用类型字段的方式不同。

1. 浅克隆(Shallow Clone)

浅克隆会创建一个新对象,并复制原始对象的所有非静态字段到新对象中。对于字段的值是值类型的,直接复制值即可。但对于字段的值是引用类型的,则复制引用但不复制引用的对象。因此,原始对象及其克隆会共享这些对象。

在Java中,可以通过实现Cloneable接口并重写Object类的clone()方法来实现浅克隆。Cloneable接口是一个标记接口,没有定义任何方法。一个类实现Cloneable接口,就表明这个类的对象是可以被克隆的。

以下是一个简单的示例:

public class ShallowCloneExample implements Cloneable {private int x;private String str; // 引用类型字段public ShallowCloneExample(int x, String str) {this.x = x;this.str = str;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public static void main(String[] args) throws CloneNotSupportedException {ShallowCloneExample original = new ShallowCloneExample(1, "Hello");ShallowCloneExample cloned = (ShallowCloneExample) original.clone();System.out.println(cloned.str == original.str); // 输出 true,说明两个对象共享同一个字符串对象}
}

2. 深克隆(Deep Clone)
深克隆会创建一个新对象,并复制原始对象的所有非静态字段到新对象中。对于字段的值是引用类型的,则递归地复制引用的对象,直到所有对象都是新的。因此,原始对象及其克隆不会共享任何对象。

实现深克隆通常比浅克隆更复杂,因为需要手动处理所有引用类型字段的复制。可以使用序列化和反序列化的方式来实现深克隆,或者手动编写代码来复制对象的所有字段(包括引用类型字段)。

以下是一个使用序列化和反序列化实现深克隆的示例:

import java.io.*;public class DeepCloneExample implements Serializable {private int x;private String str; // 引用类型字段public DeepCloneExample(int x, String str) {this.x = x;this.str = str;}public static <T> T deepClone(T obj) throws IOException, ClassNotFoundException {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(obj);oos.close();byte[] bytes = bos.toByteArray();ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));return (T) ois.readObject();}public static void main(String[] args) throws IOException, ClassNotFoundException {DeepCloneExample original = new DeepCloneExample(1, "Hello");DeepCloneExample cloned = deepClone(original);System.out.println(cloned.str == original.str); // 输出 false,说明两个对象不共享同一个字符串对象}
}

需要注意的是,使用序列化和反序列化的方式实现深克隆有一些限制,比如被克隆的类必须实现Serializable接口,且不能包含瞬态(transient)字段。此外,这种方式可能不是最高效的,特别是对于大型对象或复杂对象图。因此,在实际应用中,可能需要根据具体需求来选择最合适的克隆方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/759946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Centos7部署单节点MongoDB(V4.2.25)

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

Java面试题(Spring篇)

&#x1f49f;&#x1f49f;前言 ​ 友友们大家好&#xff0c;我是你们的小王同学&#x1f617;&#x1f617; 今天给大家打来的是 Java面试题(Spring篇) 希望能给大家带来有用的知识 觉得小王写的不错的话麻烦动动小手 点赞&#x1f44d; 收藏⭐ 评论&#x1f4c4; 小王的主页…

[STM32] Keil MDK 新建工程编译不通过(warning: #2803-D和Error: L6218E)解决方法备忘

按照野火的PDF教程的第4章&#xff1a;[野火]《RT-Thread 内核实现与应用开发实战—基于STM32》.pdf 新建 Keil MDK 工程&#xff0c;工程设置完成后点击编译按钮&#xff0c;编译不通过&#xff1a; RTE\Device\ARMCM3\startup_ARMCM3.c(75): warning: #2803-D: unrecognize…

简易C语言词法分析程序

更好的阅读体验 \huge{\color{red}{更好的阅读体验}} 更好的阅读体验 问题 词法规则&#xff1a; <标识符>::<字母> <标识符>::<标识符><字母> <标识符>::<标识符><数字> <常量>::&#xff1d;<无符号整数> <…

【DP】第十三届蓝桥杯省赛C++ B组《李白打酒加强版》(C++)

【题目描述】 话说大诗人李白&#xff0c;一生好饮。 幸好他从不开车。 一天&#xff0c;他提着酒壶&#xff0c;从家里出来&#xff0c;酒壶中有酒 2 斗。 他边走边唱&#xff1a; 无事街上走&#xff0c;提壶去打酒。 逢店加一倍&#xff0c;遇花喝一斗。 这一路上&am…

如何准备2024年汉字小达人:历年考题练一练-18道选择题解析

距离2024年第11届汉字小达人比赛还有七个多月的时间&#xff0c;如何利用这段时间有条不紊地备考呢&#xff1f;我的建议是两手准备&#xff1a;①把小学1-5年级的语文课本上的知识点熟悉&#xff0c;重点是字、词、成语、古诗。阅读理解不需要。②把历年真题刷刷熟&#xff0c…

Mybatis之自定义映射resultMap

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

基于springboot+vue的失物招领平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

更智能的广告素材生成!看A/B测试如何驱动AIGC素材调优

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 前言&#xff1a;AIGC 大爆发&#xff0c;引发广告营销行业变革 ChatGPT 等 AI 产品引发的 AIGC 大爆发引起了各行业的震动&#xff0c;其中以图片生成甚至视频生成…

操作系统:malloc与堆区内存管理

malloc是函数而不是系统调用&#xff0c;他的底层是同调调用brk和mmap这两个系统调用实现功能的&#xff0c;具体选择brk还是mmap要看申请的空间大小以及malloc中的阈值&#xff08;一般是128kb&#xff09; 注意申请的空间只有使用才会触发缺页中断映射到物理内存 不理解的话先…

现货黄金做对冲的具体方法

现货黄金做对冲的具体方法是运用金融衍生工具和策略&#xff0c;以减轻或消除持有现货黄金所面临的市场风险。具体而言&#xff0c;投资者可通过期货合约、期权、掉期等金融工具来实现对冲&#xff0c;保障其投资价值不受金价波动的负面影响。 &#xfeff; 期货合约在对冲中…

Ceres求解非线性优化问题步骤与示例

【版权声明】 本文为博主原创文章&#xff0c;未经博主允许严禁转载&#xff0c;我们会定期进行侵权检索。 在计算机视觉和机器人领域&#xff0c;经常需要解决非线性优化问题来估计相机姿态或运动模型。Ceres Solver是一个开源的C库&#xff0c;专门用于解决最小二乘问题&am…

HarmonyOS/OpenHarmony应用开发-HDC环境变量设置

hdc&#xff08;HarmonyOS Device Connector&#xff09;是 HarmonyOS 为开发人员提供的用于调试的命令行工具&#xff0c;通过该工具可以在 windows/linux/mac 系统上与真实设备或者模拟器进行交互。 hdc 工具通过 HarmonyOS SDK 获取&#xff0c;存放于 /Huawei/Sdk/openhar…

C++:指针 引用 普通变量适用场景

什么时候用指针 什么时候用引用 什么时候用普通变量 在C中&#xff0c;我们可以根据不同的需求选择使用指针、引用或普通变量。 使用指针的情况&#xff1a; 指针是一个变量&#xff0c;它存储了一个内存地址。我们可以使用指针来间接访问和修改内存中的数据。以下是一些使用…

sde的几个问题

数据库:aix6.1oracle11.2.0.1 sde数据为从原先oracle10.2.0.5中导入的。 环境&#xff1a;windows2008x64 安装sde10 for oracle11g x64oracle11.2.0.1x64客户端。 启动出现问题&#xff1a; ST_Geometry Schema Owner: (SDE) Type Release: 1007 Instance initialized fo…

5.1.7、【AI技术新纪元:Spring AI解码】Mistral AI Chat

Mistral AI 聊天 Spring AI 支持 Mistral AI 的各种 AI 语言模型。您可以与 Mistral AI 语言模型进行互动,并基于 Mistral 模型创建多语言对话助手。 先决条件 您需要创建一个与 MistralAI 的 API 以访问 Mistral AI 语言模型。在 MistralAI 注册页面创建账户并在 API Keys…

零基础学python:17、课后练习作业

课后练习 #1.写一个装饰器,传入一个函数,测量一下这个函数的运行时间 import time def wrapper(func):def run(*args,**kwargs):start = time.time()func(*args

HTTP协议初识

HTTP协议 HTTP协议简介与作用HTTP基本工作原理非持久连接与持久连接的区别HTTP请求与响应HTTP请求HTTP响应请求与响应的交互流程 HTTP方法实例GET 请求示例POST 请求示例HEAD 请求示例 使用场景 HTTP状态码HTTP消息结构与头字段头字段 HTTP的无状态性与状态管理初步了解安全性与…

C++(4): std::ofstream的使用

1. ofstream 之前讲到&#xff0c;ifstream具有将文件从硬盘中读进内存的功能。而ofstream则是执行反操作&#xff0c;它提供了将文件从内存写入磁盘的功能。 std::ofstream 是 C 标准库中用于文件输出的类&#xff0c;它提供了向文件写入数据的能力。std::ofstream 属于 <…

559: 字符串排序(python)

收藏 难度&#xff1a;一般 标签&#xff1a;暂无标签 题目描述 在对字符串的排序中&#xff0c;往往具有不同的规则来判断字符串的大小先后。这里有两种比较常见的规则&#xff1a; 1&#xff0e; 首先按字符串长度进行排序&#xff0c;对长度相同的字符串&#xff0c;按字…