当前位置: 首页 > news >正文

整理的一些Java细节问题

1. 为什么要有无参构造?

在 Java 中,如果一个类没有显式定义构造方法,编译器会自动生成一个默认的无参构造方法(也称为默认构造方法)。无参构造方法是一个没有任何参数的构造方法。

无参构造方法的存在有几个重要原因:

  1. 默认初始化:如果没有定义任何构造方法,Java 编译器会自动提供一个无参构造方法,确保类的实例可以被实例化。这允许对象在被创建时执行默认的初始化。

  2. 继承:当一个类继承自另一个类,如果父类有默认的构造方法且没有显式提供其他构造方法,子类也将继承这个默认的无参构造方法。这使得子类实例化时可以使用父类的默认初始化。

  3. 反射和实例化:在某些情况下,例如通过 Java 的反射机制,需要在运行时动态创建对象实例。如果没有提供其他构造方法,可以使用默认的无参构造方法来实例化对象。

尽管编译器会在需要时自动创建无参构造方法,但是在编写 Java 类时,有时会明确地提供一个无参构造方法是一个良好的实践。这样可以确保对类的实例化始终具有一致的行为,并提供额外的灵活性。

2. 为什么声明了有参,就必须声明无参?

在 Java 中,如果一个类显式定义了有参构造方法,但没有显式定义无参构造方法,Java 编译器不会自动生成默认的无参构造方法。

这是因为当你定义了有参构造方法时,Java 编译器默认提供的无参构造方法就不再存在,除非你明确地定义它。这意味着如果在类的其他地方(比如其他类实例化时)使用了无参构造方法来创建对象,但该类中没有定义无参构造方法,就会导致编译错误。

这种行为是 Java 语言的规范之一,确保编程人员在需要时可以明确地控制对象的创建方式。如果你需要提供无参构造方法,即使你已经定义了有参构造方法,可以显式地定义一个无参构造方法,或者利用有参构造方法中的默认值来实现类的实例化。

3. 为什么重写了equals就必须重写hashcode?

在 Java 中,equals() 和 hashCode() 方法之间存在关联,这两个方法用于实现对象的相等性和哈希值。如果你重写了 equals() 方法来定义两个对象相等的条件,那么为了维持哈希表数据结构的一致性,通常也需要重写 hashCode() 方法。

这是由于哈希表数据结构在存储对象时使用了 hashCode() 方法。哈希表是一种常见的数据结构,如 HashMap、HashSet,它们根据对象的哈希码(由 hashCode() 方法返回)将对象存储在内部数组的特定位置。当你需要通过键来查找对象时,哈希表首先根据键的哈希码确定可能的位置,然后再使用 equals() 方法来精确查找这个位置上的对象。

如果两个对象根据 equals() 方法判断相等,那么它们的哈希码应该相等。这是因为哈希表的实现依赖于这个规则,如果这个规则被打破,可能导致对象无法准确地从哈希表中检索。

因此,当你重写 equals() 方法时,为了确保符合相等对象具有相等哈希码的原则,通常也需要重写 hashCode() 方法。在重写 hashCode() 方法时,应该保证如果两个对象根据 equals() 方法相等,它们的哈希码应该一致。

当重写 equals() 方法但未重写 hashCode() 方法时,可以导致在集合中出现相同的对象

比如:考虑一个 Book 类,它包含书名和作者。我们重写了 equals() 方法来比较两本书是否具有相同的书名和作者,但忘记了重写 hashCode() 方法。

import java.util.HashSet;
import java.util.Set;public class Book {private String title;private String author;public Book(String title, String author) {this.title = title;this.author = author;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Book book = (Book) o;return title.equals(book.title) && author.equals(book.author);}
}

现在,让我们创建几本书并将它们放入 HashSet 中:

public class Main {public static void main(String[] args) {Set<Book> bookSet = new HashSet<>();Book book1 = new Book("Java 101", "John Doe");Book book2 = new Book("Java 101", "John Doe");bookSet.add(book1);bookSet.add(book2);System.out.println("HashSet size: " + bookSet.size());}
}

尽管 book1 和 book2 的 equals() 方法返回 true,但由于没有重写 hashCode() 方法,HashSet 会将它们视为两个不同的对象,因此向集合中添加 book2 也会成功。这将导致集合中出现相同的对象,违反了预期的行为。
在这里插入图片描述

解决方法是在 Book 类中重写 hashCode() 方法,确保相等的对象具有相等的哈希码:

import java.util.Objects;public class Book {// ... 其他代码保持不变@Overridepublic int hashCode() {return Objects.hash(title, author);}
}

在这里插入图片描述

通过重写 hashCode() 方法,相等的对象会具有相等的哈希码,从而能够正确地存储和检索于集合类中。

4. HashSet去重细节

在 Java 中,HashSet 是基于哈希表实现的集合类,用于存储不重复元素。当元素被添加到 HashSet 中时,它会执行以下步骤来确保不重复:

  1. 计算哈希码(Hash Code):当一个元素被加入 HashSet 时,HashSet 会调用该元素的 hashCode() 方法来获取其哈希码。哈希码是一个用来快速定位对象的整数值。

  2. 计算存储位置:HashSet 使用哈希码和内部的哈希函数,计算出该元素在内部存储数组中的位置。每个位置对应一个“桶”(bucket)。

  3. 检查是否存在相同哈希码的元素:如果该位置上已经有元素存在(发生哈希冲突),则会进行进一步的检查。

    • 相同哈希码:HashSet 首先会比较待加入元素的哈希码与该位置上已存储元素的哈希码。如果两者相同,它会调用这两个元素的 equals() 方法进行精确比较。

    • 如果两个元素相等:如果 equals() 方法返回 true,则该元素已经存在于 HashSet 中,新元素不会被加入。这是为了保证 HashSet 中不会存储重复的元素。

  4. 插入元素:如果没有相同哈希码的元素存在,且没有发生哈希冲突,新元素将被添加到 HashSet 中。

通过这种方式,HashSet 利用哈希码快速确定元素的存储位置,并利用 equals() 方法进行最终的比较来确保集合中没有重复元素。

5. String为什么是不可变的?

在 Java 中,String 对象是不可变的,即一旦创建后,它的值就无法被修改。这种不可变性是由于以下几个原因:

  1. 安全性(Security)
    由于字符串是不可变的,它们在作为参数传递给方法、作为键用于哈希表等场景时更加安全。因为不可变性可以确保字符串不被意外更改,从而避免在多个地方使用相同的字符串时发生潜在的安全隐患。

  2. 线程安全(Thread Safety)
    不可变性使得字符串成为线程安全的,因为多个线程可以同时访问一个字符串对象而不需要担心它的值被修改。这样就不需要同步控制来保护字符串对象。

  3. 字符串池(String Pool)
    Java 中的字符串池(String Pool)机制利用字符串的不可变性。当你创建一个字符串时,如果这个字符串已经存在于字符串池中,Java 将返回现有的字符串对象而不是创建一个新的。这样可以节省内存空间,提高性能。

  4. 缓存哈希值
    字符串的不可变性使得它们的哈希码可以在创建时缓存。由于字符串的哈希码在使用哈希表等数据结构时经常被需要,缓存它们可以提高性能。

  5. 优化字符串操作
    不可变性允许字符串操作(如连接、截取等)产生新的字符串,而不会修改原始字符串。这样可以避免频繁地创建新的字符串对象。

总的来说,字符串的不可变性是 Java 设计的一部分,它提供了安全、线程安全、性能和一些优化的好处,使得字符串在很多场景下更易于管理和使用。

6. 什么是泛型?有什么好处?

泛型(Generics)是 Java 中的一个强大特性,它允许在编写代码时参数化类型,使得类、接口和方法能够在编译时具有更强的类型安全性。

  • 基本概念:
    参数化类型:允许你在使用类、接口或方法时指定类型。
    泛型类和接口:可以在类或接口中声明类型参数,并在实例化时指定具体类型。
    泛型方法:可以在方法级别使用泛型,允许方法在调用时接受不同类型的参数。

  • 好处:
    类型安全:通过在编译时捕获错误,避免了类型转换错误。编译器能在编译阶段发现并解决类型不匹配的问题。

    代码重用:泛型使得类和方法可以适用于多种类型,提高了代码的重用性。

    性能:泛型在编译时执行类型检查,避免了运行时的类型转换,可以提高性能。

    简化代码:泛型能够减少手动类型转换,使代码更简洁易读。

    集合类的使用:Java 中的集合框架(如 ArrayList, HashMap 等)广泛使用泛型,使得集合中存储的元素类型更明确,减少了强制类型转换。

    扩展数据类型的适用范围:通过泛型,代码可以对多种数据类型进行操作,而不需要为每种类型编写不同的逻辑。

总的来说,泛型提供了类型安全、代码重用、简化代码、提高性能等好处,使得 Java 编程更为灵活、高效和安全。

7. 什么是泛型擦除?有什么好处?

泛型擦除(Generics Erasure)是 Java 泛型机制中的一个概念,指的是在编译时将泛型信息从泛型代码中删除的过程。Java 的泛型是通过类型擦除来实现的。

  • 基本概念:
    类型擦除:Java 的泛型只存在于编译期,在编译后的字节码中,并不保留泛型的类型信息。编译器会擦除泛型类型,并使用原始类型来处理。

    原始类型:在类型擦除后,所有泛型类型参数都会被替换为它们的上限边界或 Object 类。比如 List 在编译后会变成 List。

  • 好处:
    向后兼容性:泛型擦除允许 Java 5 之后引入泛型,同时保留了与旧代码的向后兼容性。因为擦除后的代码与旧的非泛型代码兼容。

    减少运行时负担:擦除泛型信息可以减少字节码的大小,降低运行时内存开销。因为泛型信息在运行时不再存在。

    简化代码:在源代码级别使用泛型,能够提供更好的类型安全性和更清晰的代码结构,但在运行时不需要额外的泛型信息。

尽管泛型擦除提供了许多好处,但也有一些限制和注意事项,比如无法直接获取泛型的类型信息(在运行时),以及某些情况下可能导致潜在的类型不安全性。通常,泛型擦除是为了兼容性和性能而存在的。

8. 抽象类和抽象方法细节

抽象类和抽象方法是面向对象编程中的重要概念,用于实现对继承、多态和封装等特性的支持。

  • 抽象类(Abstract Class):

    1. 概念:
      抽象类是一个不能被实例化的类,用 abstract 关键字定义。它可以包含抽象方法,也可以包含普通方法。

    2. 特点:

      抽象类不能被实例化,只能用于派生其他类。

      可以包含抽象方法和普通方法。

      抽象类的子类必须实现其所有的抽象方法,除非子类也声明为抽象类。

    3. 用途:
      提供通用的方法实现,但也留有抽象方法供子类实现,促进了代码重用和多态性。

  • 抽象方法(Abstract Method):

  1. 概念:
    抽象方法是在抽象类中声明但没有具体实现的方法,不包含方法体。使用 abstract 关键字标记。

  2. 特点:

    抽象方法只能存在于抽象类中。

    抽象方法没有实际的实现,其实现必须在子类中完成。

  3. 用途:
    定义一种契约,要求继承的子类必须实现这些方法,从而促进了多态性和多态方法调用。

示例:

// 抽象类
abstract class Shape {// 抽象方法public abstract double area(); // 无方法体// 普通方法public void display() {System.out.println("Displaying shape...");}
}// 抽象类的子类
class Circle extends Shape {private double radius;// 实现抽象方法public double area() {return Math.PI * radius * radius;}
}

抽象类和抽象方法提供了一种设计机制,让代码更具扩展性和灵活性,通过强制要求继承类实现抽象方法,达到对特定行为进行标准化的目的。

相关文章:

整理的一些Java细节问题

1. 为什么要有无参构造&#xff1f; 在 Java 中&#xff0c;如果一个类没有显式定义构造方法&#xff0c;编译器会自动生成一个默认的无参构造方法&#xff08;也称为默认构造方法&#xff09;。无参构造方法是一个没有任何参数的构造方法。 无参构造方法的存在有几个重要原因…...

初识AUTOSAR网络管理

文章目录 目的模式时间参数T_REPEAT_MESSAGET_NM_TIMEOUTT_WAIT_BUS_SLEEPT_START_Tx_AppFrameT_NM_ImmediateCycleTimeT_NM_MessageCycleN_ImmediateNM_TIMEST_START_NM_TXT_WakeUp跳转状态NM_1NM_2NM_3NM_4NM_5NM_6NM_7...

Flink SQL Hive Connector使用场景

目录 1.介绍 2.使用 2.1注册HiveCatalog 2.2Hive Read 2.2.1流读关键配置 2.2.2示例...

【Docker】联合探讨Docker:容器化技术的革命性应用

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…...

dirhunt使用手册,中文版

“dirhunt” 的命令行工具的帮助信息&#xff0c;用于目录扫描和网站内容分析。以下是这个命令的使用方法和示例&#xff1a; 命令格式&#xff1a; dirhunt [OPTIONS] [URLS]… [URLS]…&#xff1a;一个或多个域名或 URL&#xff0c;可以加载来自文件的 URL&#xff0c;使用…...

【从0到1设计一个网关】如何设计一个稳定的网关?

文章目录 高可用分析软件架构心跳检测自动恢复熔断降级接口重试隔离压测和预案多机房灾备以及双活数据中心异常处理机制重试主备服务自动切换动态剔除或恢复异常机器超时时间的考虑服务设计这篇文章并没有具体的业务实现,而只是对于如何设计一个高可用,稳定的网关列举出了一些…...

chromedp库编写程序

步骤1&#xff1a;首先&#xff0c;我们需要导入chromedp库&#xff0c;以便使用它来下载网页内容。 import chromedp 步骤2&#xff1a;然后&#xff0c;我们需要创建一个函数&#xff0c;该函数接受一个URL作为参数&#xff0c;并使用chromedp库下载该URL的内容。 func do…...

pngquant failed to build, make sure that libpng-dev is installed 问题

第一个参考方案失败 &#xff1a;npm install -g windows-build-tools4.0.0 安装失败&#xff0c;提示 依赖不在支持 第二个方案&#xff0c;降低node 版本 失败 第三种方案&#xff0c;成功 先执行&#xff0c;下面两行代码&#xff0c;再按照依赖 npm install imagemin-pn…...

进程控制(二):进程等待

文章目录 进程控制&#xff08;二&#xff09;进程等待wait函数waitpid函数wait/waitpid获取子进程状态码的过程进程等待相关的宏 总结 进程控制&#xff08;二&#xff09; 延续对于上文进程结束&#xff0c;我们继续对于进程控制进行学习&#xff0c;本文我们主要是对于进程…...

SWAT-MODFLOW地表水与地下水耦合模型的建模及应用

目录 第一讲 模型原理与层次结构 第二讲 QGIS软件 第三讲 基于QSWATMOD的SWAT-MODFLOW模拟 第四讲 QSWAT模型介绍与建模 第五讲 基于QGIS的数据制备 第六讲 基于CUP的SWAT参数率定 第七讲 MODFLOW模型讲解 第八讲 结果分析 更多应用 耦合模型被应用到很多科学和工程领…...

使用navicat操纵数据库

<1>连接数据库 打开Navicat&#xff0c;点击“连接”&#xff0c;选择“MySQL”&#xff0c;这边是本机安装的mysql,主机为localhost&#xff0c;输入root密码。 使用Navicat创建数据库并导入SQL文件 SQL查询 普通SQL查询 USE demo; SELECT * FROM t_emp;SELECT emp…...

websocket入门

一&#xff0c;什么是websocket WebSocket是HTML5下一种新的协议&#xff08;websocket协议本质上是一个基于tcp的协议&#xff09;它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通讯的目的Websocket是一个持久化的协议。 WebSocket有…...

Word里MathType插件符号表消失了

场景再现 在word里面编辑数学公式&#xff0c;结果符号表跑到屏幕外面了&#xff0c;找不到&#xff1b; 解决办法 在其中找到视图->工具栏&#xff0c;点击即可&#xff1a; 还嫌弃它跑到外边了&#xff0c;那就可以点击符号表的边框&#xff1a; 双击左边边框&#x…...

利用MySQL玩转数据分析之基础篇

知识无底&#xff0c;学海无涯&#xff0c;到今天进入MySQL的学习4天了&#xff0c;知识点虽然简单&#xff0c;但是比较多&#xff0c;所以写一篇博客将MySQL的基础写出来&#xff0c;方便自己以后查找&#xff0c;还有就是分享给大家。 1、SQL简述 1&#xff09;SQL的概述 S…...

【ML】分类问题

分类问题 classification&#xff1a;根据已知样本特征&#xff0c;判断输入样本属于哪种已知样本类。 常用入门案例&#xff1a;垃圾邮件检测、图像分类、手写数字识别、考试通过预测。 分类问题和回归问题的明显区别&#xff1a; 分类问题的结果是非连续型标签&#xff0c…...

python @classmethod装饰器作用 与 使用 类方法 实例方法

1 表示是类方法, 类方法可以修改类变量, 实例方法不能修改类变量 类方法可以访问和修改类变量&#xff08;也称为类属性&#xff09;。这是实例方法做不到的&#xff0c;因为实例方法只能访问和修改实例变量&#xff08;也称为实例属性&#xff09; 1.1 例子 class MyClass:…...

layui form 中input输入框长度的统一设置

Layui.form中使用class"layui-input-inline"就可轻松将元素都放到一行&#xff0c;但如果元素过多&#xff0c;就会自动换行。那就需要手动设置input框的长度。 像这种情况&#xff1a; 其实只需要添加css样式就可修改了 .layui-form-item .layui-input-inline {wid…...

【WSL/WSL 2-Redis】解决Windows无法安装WSL Ubuntu子系统与Redis安装

前言 在现代计算环境中&#xff0c;开发人员和技术爱好者通常需要在不同的操作系统之间切换&#xff0c;以便利用各种工具和应用程序。在这方面&#xff0c;Windows用户可能发现WSL&#xff08;Windows Subsystem for Linux&#xff09;是一个强大的工具&#xff0c;它允许他们…...

数据结构(四)--队列及面试常考的算法

一、队列介绍 1、定义 与栈相似&#xff0c;队列是另一种顺序存储元素的线性数据结构。栈与队列的最大差别在于栈是LIFO&#xff08;后进先出&#xff09;&#xff0c;而队列是FIFO&#xff0c;即先进先出。 2、优缺点及使用场景 优点&#xff1a;先进先出&#xff08;FIFO&…...

PMIC、电源管理MAX77646ANP、MAX77647AANP、MAX77675AEWE、MAX77847AEWL DC-DC 开关稳压器

一、MAX77646ANP、MAX77647AANP 低IQ SIMO PMIC支持原电池应用的1.8V工作电压 MAX77646/MAX77647为尺寸和效率至关重要的低功耗应用提供电源解决方案。该IC集成单电感多输出(SIMO)降压/升压稳压器&#xff0c;可通过单个电感提供三个可独立编程的电源轨&#xff0c;尽可能地减…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...