Java - 程序员面试笔记记录 实现 - Part1

社招又来学习 Java 啦,这次选了何昊老师的程序员面试笔记作为主要资料,记录一下一些学习过程。

1.1 Java 程序初始化

Java 程序初始化遵循规则:静态变量优于动态变量;父类优于子类;成员变量的定义顺序;

具体体现为:父类静态变量 -> 父类静态代码块 -> 子类静态变量 -> 子类静态代码 -> 父类非静态变量 -> 父类非静态代码块 -> 父类构造方法 -> 子类非静态变量 -> 子类非静态代码块 -> 子类构造方法。

1.2 构造方法

- 每个类可以有多个构造方法,当没有提供时,编译器在将源代码编译为字节码的时候会提供一个默认的没有参数的构造方法。

- 仅在对象实例化时调用,不可显示调用。

- 不可以被继承,也就无法被重写。但可以被重载:重写(Override)是指子类有一个方法与其父类中的某个方法具有相同的方法名、返回类型和参数列表。然而,构造方法不能被重写,因为它们没有返回类型,并且其名称必须与类名相同,这使得子类无法声明一个与父类构造方法签名相同的方法。Java设计者选择不允许构造方法被继承或重写,主要是为了避免构造过程中的复杂性和潜在的错误。构造方法的调用必须明确无误,以确保对象在使用前被正确初始化。

- 子类可以通过 super 关键字显式调用父类的构造方法;实例化对象时,首先会调用父类的构造方法再执行子类的构造方法;

1.3 clone 方法的作用

Java 在处理基本数据类型时采用值传递的方式,其他类型都是按引用传递。clone 提供从某个已有的对象创造出一个和此对象相同状态的对象的方法。

clone 的类继承 cloneable 接口(实际无任何接口方法,仅为标识),重写 Object 类中的 clone 方法,在 clone 方法里调用 super.clone()(最终都会调用到 object 的 clone 方法,这个方法返回 object 对象的一个拷贝),最终将浅拷贝的引用指向对象新的克隆体。

默认的 clone 方法仅提供了浅克隆,实现深克隆通常比实现浅克隆更复杂,因为深克隆需要递归地复制对象的所有引用对象。以下是实现深克隆的一些方法:

  1. 重写clone()方法:如果你的类中的对象引用了其他对象,并且你想要复制这些对象,你需要重写clone()方法,并在这个方法中确保所有引用的对象也被复制。

  2. 使用序列化:一种实现深克隆的简单方式是使用对象序列化机制。通过将对象序列化到一个字节数组,然后再从该字节数组反序列化,可以创建对象的一个完整副本。

  3. 复制构造函数:创建一个复制构造函数,它接受一个原对象作为参数,并使用该对象的值来初始化新对象。这种方法需要确保所有引用的对象也通过复制构造函数被复制。

  4. 复制工厂方法:类似于复制构造函数,但使用一个静态方法来创建对象的副本。

  5. 使用Apache Commons Lang:如果你使用Apache Commons Lang库,可以使用SerializationUtils.clone()方法来实现深克隆。

在Java中,数组的克隆行为取决于数组的维度:

  1. 一维数组:当克隆一维数组时,会进行浅克隆。这意味着克隆操作会创建一个新的数组对象,但数组中的元素不会被克隆。如果数组元素是引用类型,那么克隆后的数组将引用与原始数组相同的对象。

  2. 多维数组:对于多维数组,克隆行为取决于每个维度的数组。每个维度的数组都是作为一个单独的一维数组来克隆的,因此每个维度的数组都是浅克隆的。这意味着,如果克隆一个二维数组,你会得到一个新的二维数组对象,但每个子数组仍然是原始子数组的引用。

如果你需要对数组进行深克隆,即数组及其所有元素都是全新的独立副本,你需要手动实现这一过程。对于一维数组,你可以创建一个新数组并复制每个元素;对于多维数组,你需要递归地复制每个子数组。

1.3 补充 - 访问级别

在Java中,publicprotectedprivate是访问修饰符,它们控制类成员(包括字段、方法和构造函数)的访问级别。以下是这三个访问修饰符的区别:

  1. public(公共的)

    • 成员可以被任何其他类访问,不受限制。
    • 无论是同一个包中的类还是不同包中的类,都可以访问public成员。
  2. protected(受保护的)

    • 成员可以被同一个包中的其他类访问,也可以被不同包中的子类访问。
    • 访问级别比public更受限,因为不同包中的非子类不能访问protected成员。
  3. private(私有的)

    • 成员只能在其所在的类内部访问。
    • private成员不能被同一个包中的其他类访问,也不能被子类访问(即使子类在同一包中)。
    • private是访问级别最受限的修饰符。

以下是一些额外的考虑:

  • 默认访问级别:如果既不使用publicprotected,也不使用private修饰,类成员具有默认访问级别。默认访问级别意味着成员只能被同一个包中的其他类访问,但不能被子类访问(即使子类在同一包中)。

  • 访问控制:访问修饰符是Java实现封装的一种方式。通过限制对类成员的访问,可以隐藏类的内部实现细节,只暴露必要的操作界面。

  • 继承和访问级别:当子类继承父类时,只能继承publicprotected成员。private成员不能被继承,因为它们不可见。

  • 类访问:类本身也可以使用这些访问修饰符。public类可以被任何其他类访问,而private类只能在定义它的类加载器中访问。

1.4 反射

反射机制是指对于处在运动状态的类,都可以获取到这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法及访问他的属性。具体为对任何一个类都可以得到对应的 Class 实例,通过 Class 实例就可以获取类或者对象的所有信息。

  1. 设计原则:反射的使用应该遵循Java的设计原则,即封装应该被尊重。滥用反射来访问私有成员可能会破坏类的封装性,使代码难以理解和维护。

  2. 使用场景:反射通常用于框架和库的开发,例如依赖注入框架、ORM(对象关系映射)框架等,这些框架需要访问目标类的私有成员以实现其功能。

1.5 Lambda 表达式

Lambda 表达式允许把函数作为一个方法的参数,即匿名函数。

1.6 多态的实现机制

多态意为同一个操作作用在不同的对象的时候会出现不同的语义,例如"+" 的操作。主要表现形式为

- 重载:同一个类中不同参数列表的同名方法,在编译时决定调用。

- 重写:子类可以重写父类的方法,运行时才计算用哪个方法。

1.8 抽象类与接口的异同

一个类中包含抽象方法即为抽象类;抽象类在使用时不能被实例化。其设计思想为继承,is - a 关系。

接口是方法的集合,可以设置默认实现;强调功能的实现,has a 关系

1.8 补充 - final 对象

在Java中,final变量表示一旦变量被初始化赋值之后,就不能再给它赋新的值。final变量可以是类的成员变量,也可以是局部变量。以下是final变量的一些关键特性:

  1. 不可变性final变量的值是不可变的。这意味着一旦给final变量赋了初值,就不能再修改它。

  2. 必须初始化final变量必须在声明时或者在构造器中被初始化。对于类的成员变量,如果它们是final的,并且在声明时没有显示初始化,那么它们必须在每个构造器中被初始化。

  3. 引用的不变性:如果final变量是一个引用,那么这个引用一旦指向一个对象,就不能指向另一个对象。但是,被引用的对象本身的字段是可以被修改的(除非对象本身是不可变的)。

  4. 局部变量:在方法中,你可以使用final来声明一个局部变量,表示这个方法不会改变这个变量的值。

  5. 参数:方法的参数也可以是final的,这表示方法内部不会改变参数的值。

  6. 匿名内部类:在使用匿名内部类时,如果外部类的成员变量是final的,那么这些变量可以在匿名内部类中安全使用,因为它们不会被改变。

  7. 常量:通常使用final来声明常量,因为常量的值不应该被改变。

  8. 性能优化:由于final变量的不可变性,编译器和运行时环境可以对它们进行优化。

1.8 补充 - 静态方法

静态方法(Static Method)是与类本身相关联,而非与类的任何特定对象相关联的方法。在Java中,静态方法使用static关键字进行声明。以下是静态方法的一些关键特性:

  1. 调用方式:静态方法可以通过类名直接调用,而不需要创建类的实例。例如:ClassName.methodName()

  2. 类级别:静态方法属于类级别,这意味着它们与类的所有实例共享,而不是与单个对象关联。

  3. 访问类变量:静态方法可以访问类的静态变量,但它们不能直接访问类的非静态成员变量或方法,除非通过对象引用。

  4. 构造函数:静态方法不能被重写(Override),因为它们不属于类的实例,但可以被再次声明(Overload)。

  5. 实例化:静态方法在类加载时即被初始化,不需要类实例化。

  6. 工厂模式:静态方法常用于实现工厂模式,用于创建类的实例,例如:return new Constructor()

  7. 工具类:静态方法常用于工具类(Utility Class),提供一组静态工具方法,这些方法通常执行通用操作,与类的实例无关。

  8. 单例模式:静态方法在实现单例模式时也非常重要,用于控制实例的创建。

  9. 静态初始化块:静态方法可以与静态初始化块(Static Initializer Block)一起使用,以执行类加载时的初始化操作。

1.9 break \ continue \ return

break:强制跳出当前循环;仅终止当前嵌套;

continue:停止当前循环,进入下次循环;

return:从方法返回;

1.10 switch 

仅支持枚举常量:int \ Integer \ byte \ short \ char(可以隐式的转换为 int 类型)。Java 7 后支持 String,本质是将其进行hash,得到一个int 类型的 hash值进行比较,匹配成功后还会调用 String.equals 方法进行判断。

1.11 volatile

volatile 的使用是为了线程安全但不保证线程安全。线程安全的三个要素:可见性、有序性和原子性。

  1. 原子性(Atomicity)

    • 原子性是指一个操作或者一系列操作要么全部执行,要么全部不执行,不会出现中间状态。
    • 在多线程环境中,为了确保操作的原子性,通常需要使用同步机制,如synchronized关键字、锁(Lock接口及其实现类)、原子变量类(如AtomicInteger)等。
  2. 可见性(Visibility)

    • 可见性是指当一个线程修改了共享变量的值,其他线程能够立即看到这个修改。
    • Java内存模型(JMM)规定了变量的修改和访问规则。为了确保可见性,可以使用volatile关键字、锁、以及一些并发API,如ThreadLocal
  3. 有序性(Ordering)

    • 有序性是指程序执行的顺序需要符合逻辑上的先后关系。
    • 在多线程环境中,由于编译器优化、处理器乱序执行等原因,指令重排序可能导致线程安全问题。为了确保有序性,可以使用volatile关键字来禁止指令重排序,或者使用synchronized和锁来保证代码块的执行顺序。

可以解决:缓存副本、指令重排序,但不可解决原子性问题(当一个线程执行写的时候才会修改标记)。synchoronized 关键字可以解决多线程的原子操作问题。

以下场景不需要保证原子性,仅需要提供可见性和有序性:

  1. 状态标志:如果一个变量仅用作标志,以指示某个状态或条件,而这个状态或条件的变更本身不涉及复杂的操作。

  2. 监控变量:在某些监控系统中,可能需要记录某个事件发生的次数或状态,而这些记录操作不需要复合操作的原子性。

  3. 控制变量:用于控制线程行为的变量,如启动标志、停止标志等,这些标志的状态改变不需要复杂的同步操作。

  4. 观察者模式:在观察者模式中,观察者的状态可能需要立即被主题所知,而不需要执行复合的原子操作。

  5. 日志记录:在多线程应用中,日志记录可能使用volatile变量来确保日志信息的可见性,尽管写入操作本身可能不是原子的。

  6. 简单的状态通知:当一个变量用于在线程间传递简单的状态信息,而不需要执行复合操作时。

  7. 非核心数据:对于那些不会引起严重后果的非核心数据,即使出现偶尔的数据不一致,也可以接受。

1.12 Java 基本数据类型

基本类型的数据变量在声明之后就会立刻在栈上分配内存空间,除以上类型外,其余都是引用类型。

1.14 值传递和引用传递的区别

值传递:方法调用中实参把值传给形参。形参仅是一个临时变量。

引用传递:传递对象的地址,形参和实参指向同一个存储单元,因此对形参的修改会影响实参的值。

1.16 字符串

JVM 中存在一个字符串常量池,可以被共享使用。从 JDK 1.7 开始字符串常量池从 Perm 移动到堆区了。

- 直接通过双引号声明的对象会放在常量池中;

- 通过 String 提供的 intern 方法会放入常量池中;

1.16 补充 - 内存泄露

通常指认为一个对象会被垃圾回收期收集,但是由于某种原因垃圾回收期器无法回收这个对象。eg: 1.6 版本之前的 substring 方法。

1.17 == \ equals \ hashCode

==:比较变量对应的内存中存储的数值是否相同。对于基础类型可以直接比较,对于引用类型只能判断是否指向同一块存储空间。

equals: 没有复写的情况下等于 ==;用于自定义两个类何时是相同的。

hashCode:Object类提供的将内存地址转换成一个int值,所以当没有重写时,任何对象的 hashcode 都不相同。一般覆盖 equals 也需要覆盖 hashcode 

1.18 String \ Stringbuffer \ StringBuilder \ StringTokenizer

String :不可变类。适用于共享。修改时会首先创建一个 StringBuilder。

StringBuffer:适用于一个字符串常被修改的场景。线程安全。

StringBuilder:类似 StringBuffer,线程不安全。

StringTokenizer:用于分割字符串。

1.19 finally

由于程序执行 return 时意味着当前方法的结束,任何语句只能在 return 之前执行(除开 exit),finnaly 也在 Return 之前结束且覆盖其他 return 语句。并且 return 时会复制变量的值。

- 首先执行 return 的语句但不返回,然后执行 finnally 块,最后才返回。

1.20 try with resource

在 Java 中,try-with-resources 特性可以应用于实现了 java.lang.AutoCloseable 接口或其子接口 java.io.Closeable 的对象。以下是一些常见的实现了这些接口的对象类型:文件、管道、数据库等。

1.21 补充 - 异常

Java的异常分为两大类:

  1. 编译时异常(Checked Exceptions):这些异常需要在代码中进行显式处理,通常是通过 throws 关键字在方法签名中声明,或者在方法内部使用 try-catch 块捕获并处理。
  2. 运行时异常(Runtime Exceptions):这些异常是程序逻辑错误导致的,比如空指针异常(NullPointerException)、数组越界异常(ArrayIndexOutOfBoundsException)等。它们是 RuntimeException 类的子类,不需要强制处理。

1.21 补充 - 金额

可以用 BigDecimal 来表示金额,因为 float 和 double 会存在丢失精度的问题。并且需要使用 string 类型进行调用。

1.21 补充 - 实现线程安全

方法一:使用提供了安全能力的原子变量例如 AtomicInteger;

方法二:用 sychronized 修饰方法,保证同一时刻只有一个线程调用;

方法三:手动对操作加锁解锁;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用TensorFlow进行OCR识别:将表格图片转换为结构化数据

随着人工智能和机器学习技术的不断发展,OCR(Optical Character Recognition,光学字符识别)技术已经成为处理图像中文本信息的强大工具。TensorFlow是一个广泛使用的开源机器学习框架,它提供了丰富的API和工具&#xff…

【源码 +文档+调试讲解】大学生企业推荐系统ssm

大学生企业推荐系统采用B/S结构、java开发语言、以及Mysql数据库等技术。系统主要分为管理员和学生、企业三部分,管理员主要功能包括:首页、个人中心、学生管理、企业管理、招聘信息管理、个人简历管理、应聘职位管理、评价企业管理、交流论坛、系统管理…

IDEA中Maven的配置

目录 1. 安装maven 2. 配置环境变量 3. IDEA中配置Maven 4. 配置仓库目录 1. 安装maven 官网下载地址:Maven – Download Apache Maven 下载后,将zip压缩包解压到某个目录即可。 2. 配置环境变量 变量名称随意,通常为M2_HOME&#xff…

双向广搜——AcWing 190. 字串变换

双向广搜 定义 双向广度优先搜索(Bi-directional Breadth-First Search, Bi-BFS)是一种在图或树中寻找两点间最短路径的算法。与传统的单向广度优先搜索相比,它从起始点和目标点同时开始搜索,从而有可能显著减少搜索空间&#x…

【MindSpore学习打卡】应用实践-计算机视觉-FCN图像语义分割-基于MindSpore实现FCN-8s进行图像语义分割的教程

图像语义分割是计算机视觉领域中的一个重要任务,它旨在对图像中的每个像素进行分类,从而实现对图像内容的详细理解。在众多图像语义分割算法中,全卷积网络(Fully Convolutional Networks, FCN)因其端到端的训练方式和高…

vlan基础相关

7.2以太网交换基础 数据链路层也叫2层网络,用的是Mac地址,想到Mac地址就要想到交换机。 以太网协议(LAN)以太网是建立在CSMA/CD载波监听多路访问/冲突检测,机制上的广播型网络。CSMA工作原理是先监听,在介…

宇宙第一大厂亚马逊云科技AWS人工智能/机器学习证书即将上线,一篇文章教你轻松拿下

据麦肯锡《在华企业如何填补AI人才缺口》研究表明,到2030年人工智能为中国带来的潜在价值有望超过1万亿美元,而随着各大企业进入人工智能化,对该领域的人才需求将从目前的100万增长到2030年的600万。然而到保守估计,到2030可以满足…

「实战应用」如何用图表控件LightningChart JS创建SQL仪表板应用(三)

LightningChart JS是Web上性能特高的图表库,具有出色的执行性能 - 使用高数据速率同时监控数十个数据源。 GPU加速和WebGL渲染确保您的设备的图形处理器得到有效利用,从而实现高刷新率和流畅的动画,常用于贸易,工程,航…

WPS-Word文档表格分页

一、问题描述 这种情况不好描述 就是像这种表格内容,但是会有离奇的分页的情况。这种情况以前的错误解决办法就是不断地调整表格的内容以及间隔显得很乱,于是今天去查了解决办法,现在学会了记录一下避免以后忘记了。 二、解决办法 首先记…

PLC_博图系列☞F_TRIG:检测信号下降沿

PLC_博图系列☞F_TRIG:检测信号下降沿 文章目录 PLC_博图系列☞F_TRIG:检测信号下降沿背景介绍F_TRIG: 检测信号下降沿说明参数示例 关键字: PLC、 西门子、 博图、 Siemens 、 F_TRIG 背景介绍 这是一篇关于PLC编程的文章&a…

中南大学湘雅三院张如旭/刘爱华团队发现牙髓干细胞来源的外泌体减轻脑缺血再灌注损伤的神经保护机制

随着我国人口老龄化的加剧,中风已成为我国主要的公共卫生疾病之一,确定其潜在的分子机制和治疗靶点对于开发有效的预防和治疗策略至关重要。近期,中南大学湘雅第三医院张如旭、刘爱华团队在经典权威期刊《Pharmacological Research》&#xf…

从一次 SQL 查询的全过程了解 DolphinDB 线程模型

1. 前言 DolphinDB 的线程模型较为复杂,写入与查询分布式表都可能需要多个类型的线程。通过了解 SQL 查询的全过程,可以帮助我们了解 DolphinDB 的线程模型,掌握 DolpinDB 的配置,以及优化系统性能的方法。 本教程以一个分布式 …

华清远见人工智能课程:项目优势助力,学习更高效!

在人工智能飞速发展的今天,学习人工智能成为新的高薪赛道。我们都知道人工智能的学习离不开项目练手,只有通过实际项目的操作,才能真正掌握人工智能的核心技能。但遗憾的是,很多人工智能课程只注重理论知识的传授,缺乏…

WEB项目通过浏览器打开windows上的exe应用

一、背景 最近有一个新需求,是通过浏览器打开本地exe应用。因为我们公司的产品是以exe为主,用web项目管理数据,接到的新项目是web为企业门户需要集成所有的应用,前端通过按钮点击打开本地exe应用。一开始还有点懵,因为…

Coze 国际版停止免费开启商业化

昨晚 Coze 国际版没有任何官方通知,悄悄开启了 Premium 服务,API 和 SDK 调用不再免费。 免费版只提供每日 10 条消息,最低的 9 刀套餐,每日最多 100 条消息,GPT-4o 最多 10 条。 国内版目前还是免费的,但…

大数据之FlinkCDC

最近在做FLinkCDC数据实时同步的数据抽取处理 目标: 将源端系统Oracle数据库的实时数据通过FLINKCDC的形式抽取到Doris中 问题: 在抽取的过程中,如果表的数据量太大,抽取超过30张表以后,所有的任务大概运行25~30分钟以后,所有的任务的状态会从running 变为 Failed. 解决方案…

BitLocker 的作用是什么?如何开启或者关闭它?

BitLocker 是什么 BitLocker 是一种全盘加密(FDE)技术,最早在 Windows Vista 中引入,并在后续版本的 Windows 中得到了持续改进。BitLocker 使用高级加密标准(AES)来加密整个磁盘分区,确保只有…

国产集成DSP内核无线音频传输的无线接收芯片U1R32D

国产集成DSP内核无线音频传输的无线接收芯片 - U1R32D,是一款用于无线音频传输的接收芯片,配合无线发射芯片完成高品质无线音频传输。射频工作范围为UHF的500M~980MHz之间。由于集成了DSP内核及必要的外设,单芯片集成度高,性价比好…

电商控价:系统监测的必要性与优势

在品牌的发展进程中,会遭遇各种各样的渠道问题,控价乃是其中颇为关键的一环。品牌进行控价的目的无疑是为了妥善治理低价链接,低价链接的发现途径可以是人工,也可以是系统。力维网络在为上百个品牌提供服务的过程中察觉到&#xf…