Java基础常见面试题(不定期更新)
1、java 的基本数据类型/有哪些?Java 的基本数据类型包括以下八种: boolean: 用于存储逻辑值,只能存储 true 和 false。 byte: 用于存储字节数据,占用 8 位(一个字节)内存空间。 short: 用于存储较短整数,占用 16 位(两个字节)内存空间。 int: 用于存储整数,占用 32 位(四个字节)内存空间。 long: 用于存储长整数,占用 64 位(八个字节)内存空间。 float: 用于存储单精度浮点数,占用 32 位(四个字节)内存空间。 double: 用于存储双精度浮点数,占用 64 位(八个字节)内存空间。 char: 用于存储单个字符,占用 16 位(两个字节)内存空间,采用 Unicode 编码。 2、java 为什么要有包装类型?主要原因包括以下几点: 处理基本数据类型的 null 值:基本数据类型(如 int,double 等)不能直接赋值为 null,而包装类型(如 Integer、Double)可以表示 null 值,这对于某些业务逻辑和数据处理来说非常有用。 提供额外功能:包装类型提供了一些额外的方法...
minIO图床配合el-upload和springboot实现后端签名前端直传
概述背景谷粒商城中有许多需要保存图片的场景,正规做法是在数据库中保存图片地址,文件则保存在对象存储服务(OSS)中,官方视频教学的是使用阿里云的OSS,这样还可以搭配spring boot cloud alibaba使用,但是本人希望能自己部署的环境尽量自己部署,查询后找到了minIO这款工具,可以实现OSS的大部分功能,使用docker部署也非常方便,这样的话就需要重构很多前后端代码 分析问题本来个人想要做成前端把文件传到后端,后端再上传到minIO图床,这套流程个人很熟悉。但是教程中使用的是签名直传的方案,想来少了一段文件传输的流程也确实速度更快也更稳定,这在minIO里也可以实现,只是需要一些技巧 签名直传方案的原理是,前端向后端发送请求,携带文件名参数,后端返回给前端一个直传地址,前端直接请求该地址即可上传文件,这样保证了既不会需要在前端填写图床信息(通过返回参数获得),还可以直接由前端上传文件 在el-upload中填入action参数是官方做法,这样该组件会自己调用封装好的post方法请求这个参数地址来直传文件 minIO这个软件给的api里,直传地址只能通过p...
Redis实现排行榜功能
背景 通常来说,榜单是指一定时间周期内以某个指标反序排列的 N 个元素 (id, score),即 topN 个元素,这里的 N,一般来说是个较小的常数,如 100。而根据时间周期的不同,可分为小时榜、日榜、周榜、月榜等。 以直播为例,在直播后端业务场景下,涉及榜单的包括但不限于直播间榜单、直播 PK 贡献榜单、粉丝团亲密度榜单、直播宠物好友榜单、直播宠物投喂饭团榜单、地区小时榜单。其中直播间榜单是日榜、直播 PK 贡献榜则是以 PK 时长为周期的榜单。 本文主要简述在不同需求场景下,如何使用 redis 对榜单数据进行存储,并尽可能保证榜单数据一致性。 概念 榜单,一系列榜单单元 <id, score> 构成,按 score 反序排列的有序列表。 榜单元素,id,用户于惟一标识榜单中某个数据单元,如用户 id;score,用于标识 id 的计分。 说明:后续示例中以 u 表示用户,topList 表示榜单,userScore 表示用户计分。 选择 redis 原因 redis 丰富的数据结构中 zset 就是有序列表。 redis zs...
Redis 实战:Redis 在 Java 中的基本使用
Redis 实战:Redis 在 Java 中的基本使用1、使用 jedis 操作 redis1.1、Jedis 简介Jedis 是 Java 语言开发的 Redis 客户端工具包,用于 Java 语言与 Redis 数据进行交互。 Jedis 在 github 官网地址:https://github.com/redis/jedis#readme Jedis 只是对 Redis 命令的封装,掌握 Redis 命令便可轻易上手 Jedis。 Jedis 遵循 RESP 协议规范开发,具有良好的通用性与可读性。 1.2、引入 jedis 的 Maven 依赖123456<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> ...
Java 锁介绍
乐观锁 乐观地认为并发访问不会造成数据冲突,只在更新时检查是否有冲突。乐观锁和 CAS 的关系可以用 “乐观锁是一种思想,CAS 是一种具体的实现” 来理解。 当使用 CAS 操作修改数据时,如果版本号不匹配或者其他线程已经修改了要操作的数据,CAS 会返回失败。这时候,程序可以再次尝试 CAS 操作,也就是进行自旋重试,直到 CAS 操作成功。 因此,CAS 操作已经内置了自旋重试的机制,避免了使用额外的自旋锁。 适用场景:适用于并发较低(高并发场景每次修改了去对比,还不如让加锁阻塞排队执行)、读多写少的场景,相信数据多数情况下不会发生冲突,只在更新时进行检查,以减少对共享资源的争用。 java 中常见悲观锁实现:可以使用 java.util. concurrent.atomic 包中的原子类,比如 AtomicInteger、AtomicLong 等,来实现 CAS 操作。 mysql 实现乐观锁:版本号、时间戳 悲观锁 悲观地认为并发访问会造成数据冲突,因此在访问共享资源之前就会进行加锁,确保同一时刻只有一个线程能够访问。 适用场景:适用于高并发、写多的场景,通过加锁保护共...
深入理解 Java 虚拟机:Jvm 性能调优
深入理解 Java 虚拟机:Jvm 性能调优一、Jvm 性能调优简介到目前为止,我们已经对 Jvm 进行了简单的了解,知道了 Jvm 运行时各种各样的内存结构,各种垃圾回收机制以及各种对应的垃圾收集器及其配置。而我们整个 Jvm 系列的最终目标不当仅仅以了解基础理论为终点,理论总应作为实践的工具。接下来,我们开始了解 Java 性能优化的最后一环:Jvm 性能调优。 我们常说的 Jvm 性能调优实际上有着三个以及的目的: 根据需求进行 Jvm 规划和预调优; 优化运行 Jvm 运行环境(慢,卡顿); 解决 Jvm 运行过程中出现的各种问题(OOM) 二、根据需求目标进行 Jvm 调优规划而这一性能调优基本的步骤就是明确优化目标、发现性能瓶颈、性能调优、通过监控及数据统计工具获得数据、确认是否达到目标。或者笼统的概括为 以业务场景开始压力测试监控,查看调优结果 两步。 1、调优的目标首先我们要明白 Jvm 性能调优的形式方案并不是固定的,不同的应用有着不同的目标与不同的问题。而根据需求进行 Jvm 规划和预调优最先要明确的就是调优的目标。 下面是 Jvm 常提到的性能指标 ...
深入理解 Java 虚拟机:Java 垃圾回收器
深入理解 Java 虚拟机:Java 垃圾回收器一、Jvm 垃圾回收器概述我们前面提到了,垃圾回收器的 回收的内容、回收的时机以及回收的方式,接下来我们来看 Java 垃圾回收器。如果垃圾回收算法是内存回收的方法论的话,那么垃圾回收器就是内存回收的具体实现了。 Jvm 的垃圾回收器根据场景和实现方式可以分为新生代回收器和老年代回收器,新生代回收器与老年代回收器可以搭配使用。 新生代回收器包括:Serial、ParNew 以及 Parallel Scavenge; 老年代回收器包括:Serial Old、Parallel Old 以及 CMS; 此外,Java7 update 4(第七版第四个更新升级包)之后引入了一个 G1 收集器。 Ps:不同垃圾回收器适合于不同的内存区域,有的两个垃圾回收器之间也可以配合使用! 二、新生代回收器1、Serial 收集器Serial 收集器是最基础且历史最悠久的垃圾收集器,作为单线程工作的收集器。Serial 会在它工作时要求暂停用户所有的其他线程(Stop-the-World 机制)。采用的是 “标记 - 复制” 算法。垃圾清理时,Ser...
深入理解 Java 虚拟机:Java 垃圾回收机制
深入理解 Java 虚拟机:Java 垃圾回收机制一、概述 Java 与 C++ 之间有一堵由内存动态分配和垃圾收集技术所围成的 “高墙”,墙外面的人想进去,墙里面的人却想出来 说起垃圾收集(Garbage Collection,下文简称 GC),有不少人把这项技术当作 Java 语言的伴生产物。事实上,垃圾收集的历史远远比 Java 久远,在 1960 年诞生于麻省理工学院的 Lisp 是第一门开始使用内存动态分配和垃圾收集技术的语言。 当 Lisp 还在胚胎时期是,其作者 John McCarthy 就思考过垃圾收集器需要完成的三件事情: 有哪些内存需要回收? 什么时候回收? 如何回收? 二、有哪些内存需要回收?——对象已死?在堆里面存放着 Java 世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还 “存活” 着,哪些已经“死去”(即不可能再被任何途径 使用的对象)。 1、引用计数算法引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象实例都有一个引用计数。当一个对象被创建时,就将该对象实例分配给一个变量,该变量计数设...
深入理解 Java 虚拟机:Java 运行内存结构
深入理解 Java 虚拟机:Java 运行内存结构一、JAVA 运行内存结构Jvm 执行 Java 程序时,会把它所管理的内存划分为若干个不同的数据区域。 其中一些数据区域是所有线程共享是,在 Jvm 启动时创建,在 Jvm 退出时销毁。如:方法区和堆。 还有一些数据区域是每个线程独有的,在线程启动时创建,在线程结束时销毁。如:程序计数器、虚拟机栈和本地方法栈。 下面介绍的是根据 Java 虚拟机规范定义的运行时数据区,单不同的虚拟机其运行时数据区定义也会有所不同。比如默认的 HotSpot在实现 JDK1.7 虚拟机规范时,其常量池的定义不在方法区中,而是移到了堆中;到了 HotSpot JDK1.8 中,则彻底移除了持久代(方法区)而使用 Metaspace(元数据区)来进行替代等等。 二、线程独有数据区域(Java 虚拟机规范定义的运行时数据区)1、程序计数器程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下...
深入理解 Java 虚拟机:Java 类的加载机制
深入理解 Java 虚拟机:Java 类的加载机制一、Java 类的加载机制1、 Jvm 结构组成Jvm 整体组成可分为四个部分:类加载器、运行时数据区(Runtime Data Area)、执行引擎(Execution Engine)、本地库接口(Native Interface) 类加载器:负责从字节码(Class)文件中,加载 class 信息到运行时数据区的方法区; 运行时数据区:存放 Jvm 在执行 Java 程序时相关数据的区域; 执行引擎:将字节码翻译成底层系统指令再交由 CPU 去执行; 本地库接口:执行过程中可能需要调用到其他语言(比如 C 语言)的本地接口。 PS:Javac 是收录于 Jdk 中的 Java 语言编译器。该工具可以将后缀名为 .java 的源文件编译为后缀名为 .class 的可以运行于 Java 虚拟机的字节码。 程序在被执行之前, Java 代码会被先转换成字节码(.class 文件), Jvm 首先通过一定的方式类加载器①(ClassLoader)把字节码文件加载到内存中运行时数据区②(Runtime Data Area),而字节码...





