Java 基础面试题——常见类
目录
- 1.String 为什么是不可变的?
- 2.字符串拼接用“+” 和 StringBuilder 有什么区别?
- 3.String、StringBuffer 和 StringBuilder 的区别是什么?
- 4.String 中的 equals() 和 Object 中的 equals() 有何区别?
- 5.Object 类有哪些常用的方法?
- 6.如何获取当前系统的剩余内存、总内存及最大堆内存?
- 7.LocalDateTime & Calendar
- 7.1.如何取当前的年、月、日、时、分、秒、毫秒?
- 7.2.如何获取从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数?
- 7.3.如何获取某年某月的最后一天?
- 7.4.如何打印昨天的当前时刻?
- 7.5.如何格式化日期?
1.String 为什么是不可变的?
(1)String 类中使用 final 关键字修饰的字符数组来保存字符串,如下面的代码所示:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];...
}
(2)我们知道被 final 关键字修饰的类不能被继承,修饰的方法不能被重写,修饰的变量是基本数据类型则值不能改变,修饰的变量是引用类型则不能再指向其他对象。因此,final 关键字修饰的数组保存字符串并不是 String 不可变的根本原因,因为这个数组保存的字符串是可变的(final 修饰引用类型变量的情况)。
(3)String 真正不可变的原因如下:
① 保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法。
② String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 的不可变性。
2.字符串拼接用“+” 和 StringBuilder 有什么区别?
(1)Java 语言本身并不支持运算符重载,“+”和“+=”是专门为 String 类重载过的运算符,也是 Java 中仅有的两个重载过的运算符。
public static void main(String[] args) {String str1 = "he";String str2 = "llo";String str3 = "world";String str4 = str1 + str2 + str3;
}
上述代码对应的字节码如下:
可以看出,字符串对象通过 “+” 的字符串拼接方式,实际上是通过 StringBuilder 调用 append() 方法实现的,拼接完成之后调用 toString() 得到一个 String 对象。不过在循环内使用“+”进行字符串的拼接的话,存在比较明显的缺陷:编译器不会创建单个 StringBuilder 以复用,会导致创建过多的 StringBuilder 对象,从而比较占用内存空间,并且效率较低。
public static void main(String[] args) {String[] arr = {"he", "llo", "world"};String s = "";for (int i = 0; i < arr.length; i++) {s += arr[i];}System.out.println(s);
}
上述代码对应的字节码如下所示:
(2)如果直接使用 StringBuilder 对象进行字符串拼接的话,就不会存在这个问题了。
public static void main(String[] args) {String[] arr = {"he", "llo", "world"};StringBuilder s = new StringBuilder();for (String value : arr) {s.append(value);}System.out.println(s);
}
上述代码对应的字节码如下所示:
如果在 IDEA 中使用 “+” 来拼接字符串的话,会出现建议使用 StringBuilder 的提示,如下图所示:
查看字节码的方式之一:
在控制台使用命令 javap -v xxx.class 即可,不过在此之前需要先将 xxx.java 进行编译得到 xxx.class 文件才行。
3.String、StringBuffer 和 StringBuilder 的区别是什么?
(1)底层数据结构
- String 是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个 final 类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对 String 的操作都会生成新的 String 对象。例如每次拼接操作(即两个字符串相加): 隐式地在堆上 new 了一个跟原字符串相同的 StringBuilder 对象,再调用 append() 拼接后面的字符。
private final char value[];
- StringBuffer 和 StringBuilder 都继承了 AbstractStringBuilder 抽象类,在 AbstractStringBuilder 中也是使用字符数组保存字符串,不过没有使用 final 和 private 关键字修饰(如下面的代码所示),最关键的是这个 AbstractStringBuilder 类还提供了很多修改字符串的方法,例如 append 方法。所以在进行频繁的字符串操作时,建议使用 StringBuffer 和 StringBuilder 来进行操作。
/**
* The value is used for character storage.
*/
char[] value;
(2)线程安全性
- String 中的对象是不可变的,也就可以理解为常量,所以是线程安全的、
- StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
- StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
(3)性能
- 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
- StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。
- 相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
- 性能:StringBuilder > StringBuffer > String
(4)使用场景
- 操作少量的数据:建议使用 String;
- 单线程操作字符串缓冲区下操作大量数据: 建议使用 StringBuilder;
- 多线程操作字符串缓冲区下操作大量数据: 建议使用 StringBuffer;
4.String 中的 equals() 和 Object 中的 equals() 有何区别?
String 中的 equals 方法是被重写过的,比较的是 String 字符串的值是否相等。Object 的 equals 方法是比较的对象的内存地址。
5.Object 类有哪些常用的方法?
(1)Object 是所有类的根,是所有类的父类,所有对象包括数组都实现了 Object 的方法。Object 类结构如下图所示:
(2)各种方法介绍如下:
① clone()
保护方法,实现对象的浅复制,只有实现了 Cloneable 接口才可以调用该方法,否则抛出 CloneNotSupportedException 异常,深拷贝也需要实现 Cloneable,同时其成员变量为引用类型的也需要实现 Cloneable,然后重写 clone()。
② finalize()
该方法和垃圾收集器有关系,判断一个对象是否可以被回收的最后一步就是判断是否重写了此方法。
③ equals()
该方法使用频率非常高。equals 和 == 的区别见上面的4.1题,但是在 Object 中两者是一样的。子类一般都要重写这个方法。
④ hashCode()
该方法用于哈希查找,重写了 equals() 一般都要重写 hashCode(),这个方法在一些具有哈希功能的 Collection 中用到。
⑤ notify()
配合 synchronized 使用,该方法唤醒在该对象上等待队列中的某个线程(同步队列中的线程是给抢占 CPU 的线程,等待队列中的线程指的是等待唤醒的线程)。
⑥ notifyAll()
配合 synchronized 使用,该方法唤醒在该对象上等待队列中的所有线程。
⑦ wait()
配合 synchronized 使用,wait() 就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait() 一直等待,直到获得锁或者被中断。wait(long timeout) 设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生:
- 其他线程调用了该对象的 notify 方法;
- 其他线程调用了该对象的 notifyAll 方法;
- 其他线程调用了 interrupt 中断该线程;
- 时间间隔到了。此时该线程就可以被调度了,如果是被中断的话就抛出一个 InterruptedException 异常。
6.如何获取当前系统的剩余内存、总内存及最大堆内存?
(1)可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存、总内存及最大堆内存。通过下面方法可以获取到堆使用的百分比及堆内存的剩余空间。
freeMemory() 方法返回剩余空间的字节数
totalMemory() 方法总内存的字节数
maxMemory() 返回最大内存的字节数
(2)示例如下:
class Solution {public static void main(String[] args) {System.out.println("JVM 从操纵系统那里挖到的最大的内存 maxMemory : " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "M");System.out.println("JVM 已经从操作系统那里挖过来的内存 totalMemory : " + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "M");System.out.println("JVM 从操纵系统挖过来还没用上的内存 freeMemory : " + Runtime.getRuntime().freeMemory() / 1024 / 1024 + "M");System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");byte[] b1 = new byte[3 * 1024 * 1024];System.out.println("JVM 从操纵系统那里挖到的最大的内存 maxMemory " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "M");System.out.println("JVM 已经从操作系统那里挖过来的内存 totalMemory : " + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "M");System.out.println("JVM 从操纵系统挖过来还没用上的内存 freeMemory : " + Runtime.getRuntime().freeMemory() / 1024 / 1024 + "M");}
}
输出结果如下:
JVM 从操纵系统那里挖到的最大的内存 maxMemory : 3154M
JVM 已经从操作系统那里挖过来的内存 totalMemory : 213M
JVM 从操纵系统挖过来还没用上的内存 freeMemory : 208M
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
JVM 从操纵系统那里挖到的最大的内存 maxMemory 3154M
JVM 已经从操作系统那里挖过来的内存 totalMemory : 213M
JVM 从操纵系统挖过来还没用上的内存 freeMemory : 205M
7.LocalDateTime & Calendar
7.1.如何取当前的年、月、日、时、分、秒、毫秒?
创建 java.util.Calendar 实例,调用其 get() 传入不同的参数即可获得参数所对应的值。
import java.util.Calendar;public class TestDateAndTime {public static void main(String[] args) {//获取当前的年、月、日、时、分、秒、毫秒Calendar calendar = Calendar.getInstance();//年System.out.println(calendar.get(Calendar.YEAR));//月,需要注意的是 Calendar.MONTH 是从 0 开始的System.out.println(calendar.get(Calendar.MONTH) + 1);//天System.out.println(calendar.get(Calendar.DATE));//时System.out.println(calendar.get(Calendar.HOUR));//分System.out.println(calendar.get(Calendar.MINUTE));//秒System.out.println(calendar.get(Calendar.SECOND));//毫秒System.out.println(calendar.get(Calendar.MILLISECOND));}
}
7.2.如何获取从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数?
import java.util.Calendar;public class TestDateAndTime {public static void main(String[] args) {Calendar calendar = Calendar.getInstance();//以下 2 种方法均可以获取从 1970 年 1 月 1 日 0 时 0 分 0 秒到现在的毫秒数System.out.println(System.currentTimeMillis());System.out.println(Calendar.getInstance().getTimeInMillis());}
}
7.3.如何获取某年某月的最后一天?
import java.time.LocalDate;
import java.util.Calendar;public class TestDateAndTime {public static void main(String[] args) {Calendar calendar = Calendar.getInstance();//某月最后一天//2018-05月最后一天,6月1号往前一天calendar.set(Calendar.YEAR, 2018);calendar.set(Calendar.MONTH, 5);calendar.set(Calendar.DAY_OF_MONTH, 1);calendar.add(Calendar.DAY_OF_MONTH, -1);System.out.println(calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1) + "-" + calendar.get(Calendar.DAY_OF_MONTH));//JDK 1.8 java.time 包LocalDate date = LocalDate.of(2019, 6, 1).minusDays(1);System.out.println(date.getYear() + "-" + date.getMonthValue() + "-" + date.getDayOfMonth());}
}
7.4.如何打印昨天的当前时刻?
import java.time.LocalDateTime;public class YesterdayCurrent {public static void main(String[] args) {LocalDateTime today = LocalDateTime.now();LocalDateTime yesterday = today.minusDays(1);System.out.println(yesterday);}
}
或者使用以下方式:
import java.util.Calendar;public class YesterdayCurrent {public static void main(String[] args) {Calendar cal = Calendar.getInstance();cal.add(Calendar.DATE, -1);System.out.println(cal.getTime());}
}
7.5.如何格式化日期?
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;public class TestDateAndTime {public static void main(String[] args) {Date date = new Date();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化日期System.out.println(simpleDateFormat.format(date));//JDK 1.8 java.time 包System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));}
}
相关文章:

Java 基础面试题——常见类
目录1.String 为什么是不可变的?2.字符串拼接用“” 和 StringBuilder 有什么区别?3.String、StringBuffer 和 StringBuilder 的区别是什么?4.String 中的 equals() 和 Object 中的 equals() 有何区别?5.Object 类有哪些常用的方法?6.如何获…...

Windows 系统从零配置 Python 环境,安装CUDA、CUDNN、PyTorch 详细教程
文章目录1 配置 python 环境1.1 安装 Anaconda1.2 检查环境安装成功1.3 创建虚拟环境1.4 进入/退出 刚刚创建的环境1.5 其它操作1.5.1 查看电脑上所有已创建的环境1.5.2 删除已创建的环境2 安装 CUDA 和 CUDNN2.1 查看自己电脑支持的 CUDA 版本2.2 安装 CUDA2.3 安装 CUDNN2.4 …...

[REDIS]redis的一些配置文件
修改配置文件 vim /etc/redis/redis.conf目录 protected-mode tcp-backlog timeout tcp-keepalive daemonize pidfile loglevel databases 设置密码 maxclients maxmemory maxmemory-policy maxmemory-samples 默认情况下 bind127.0.0.1 只能接受本机的访问请求。在不写的情况…...

Java反序列化漏洞——CommonsCollections4.0版本—CC2、CC4
一、概述4.0版本的CommonsCollections对之前的版本做了一定的更改,那么之前的CC链反序列化再4版本中是否可用呢。实际上是可用的,比如CC6的链,引入的时候因为⽼的Gadget中依赖的包名都是org.apache.commons.collections ,⽽新的包…...

下载网上压缩包(包含多行json)并将其转换为字典的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

【郭东白架构课 模块一:生存法则】11|法则五:架构师为什么要关注技术体系的外部适应性?
你好, 我是郭东白。 前四条法则分别讲了目标、资源、人性和技术周期,这些都与架构活动的外部环境有关。那么今天我们来讲讲在架构活动内部,也就是在架构师可控的范围内,应该遵守哪些法则。今天这节课,我们就先从技术体…...

Mindspore安装
本文用于记录搭建昇思MindSpore开发及使用环境的过程,并通过MindSpore的API快速实现了一个简单的深度学习模型。 什么是MindSpore? 昇思MindSpore是一个全场景深度学习框架,旨在实现易开发、高效执行、全场景覆盖三大目标。 安装步骤 鉴于笔者手头硬…...

C++010-C++嵌套循环
文章目录C010-C嵌套循环嵌套循环嵌套循环举例题目描述 输出1的个数题目描述 输出n行99乘法表题目描述 求s1!2!...10!作业在线练习:总结C010-C嵌套循环 在线练习: http://noi.openjudge.cn/ https://www.luogu.com.cn/ 嵌套循环 循环可以指挥计算机重复去…...

设计模式之迭代器模式与命令模式详解和应用
目录1 迭代器模式1.1 目标1.2 内容定位1.3 迭代器模式1.4 迭代器模式的应用场景1.5 手写字定义的送代器1.6 迭代器模式在源码中的体现1.7 迭代器模式的优缺点2 命令模式2.1 定义2.2 命令模式的应用场景2.3 命令模式在业务场景中的应用2.4 命令模式在源码中的体现2.5 命令模式的…...

【QA】[Vue/复选框全选] v-model绑定每一项的赋初值问题
发生场景:不只是复选框的状态改变,还有的功能要用到复选框的选中状态,比如:购物车计算总价,合计等等。 引入:复选框 checkbox 在使用时,需要用v-model绑定布尔值,来获取选中状态&…...

python基于django+vue微信小程序的校园二手闲置物品交易
在大学校园里,存在着很多的二手商品,但是由于信息资源的不流通以及传统二手商品信息交流方式的笨拙,导致了很多仍然具有一定价值或者具有非常价值的二手商品的囤积,乃至被当作废弃物处理。现在通过微信小程序的校园二手交易平台,可以方便快捷的发布和交流任何二手商品的信息,并…...

设计模式之观察者模式
什么是观察者模式 观察者模式定义了对象之间一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都能收到通知并自动刷新。 观察者模式主要包含以下几个角色: Subject(目标):指被观察的对…...

Java Lambda表达式
目录1 Lambda表达式1.1 函数式编程思想概括1.2 Lambda表达式标准格式1.3 Lambda表达式练习1(抽象方法无参无返回值)1.4 Lambda表达式练习2(抽象方法带参无返回值)1.5 Lambda表达式练习2(抽象方法带参带返回值ÿ…...
【1237. 找出给定方程的正整数解】
来源:力扣(LeetCode) 描述: 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子…...

java基础学习 day41(继承中成员变量和成员方法的访问特点,方法的重写)
继承中,成员变量的访问特点 a. name前什么都不加,name变量的访问采用就近原则,先在局部变量中查找,若没找到,继续在本类的成员变量中查找,若没找到,继续在直接父类的成员变量中查找,…...

【c语言进阶】深度剖析整形数据
🚀write in front🚀 📜所属专栏: 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大的激励…...
【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人)
【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人) 这里写目录标题【信息系统项目管理师】项目管理十大知识领域记忆敲出(采购风险沟通干系人)一.项目采购管理记忆敲出1.合同管理:2.规划采购管…...

[LeetCode 1237]找出给定方程的正整数解
题目描述 题目链接:[LeetCode 1237]找出给定方程的正整数解 给你一个函数 f(x, y) 和一个目标结果 z,函数公式未知,请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。满足条件的结果数对可以按任意顺序返回。 尽管函数的具体式子未知…...

6.2 构建 RESTful 应用接口
第6章 构建 RESTful 服务 6.1 RESTful 简介 6.2 构建 RESTful 应用接口 6.3 使用 Swagger 生成 Web API 文档 6.4 实战:实现 Web API 版本控制 6.2 构建 RESTful 应用接口 6.2.1 Spring Boot 对 RESTful 的支持 Spring Boot 提供的spring-boot-starter-web组件完全…...
20230218英语学习
How Italian Artist’s Mild Colors Dominate World of Design 温柔的“莫兰迪色”,如何引领设计时尚? The Morandi color scheme has become an across-the-board fashion that now prevails in the world of design.Soft and sophisticated Morandi c…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...