Java基础知识扫盲

目录

Arrays.sort的底层实现

BigDecimal(double)和BigDecimal(String)有什么区别

Char可以存储一个汉字吗 

Java中的Timer定时调度任务是咋实现的

Java中的序列化机制是咋实现的

Java中的注解是干嘛的

Arrays.sort的底层实现

Arrays.sort是Java中提供的对数组进行排序的方法,根据参数类型不同,它提供了很多重载方法:

public static void sort(Object[] a)
public static void sort(byte[] a)
public static void sort(float[] a)
public static void sort(int[] a)

因此对于不同的数据类型,底层采用的排序算法也是不同的

如果是基本数据类型(int、double、char等)的数组,则采用的是“双轴快速排序”算法来实现的

public static void sort(int[] a) {DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);}

双轴快速排序是对传统快速排序的改进,它通过选择两个轴值来划分数组,并在每个划分区域中进行递归排序。这种算法通常比传统的快速排序更快,特别是在大量重复元素的情况下。双轴快速排序算法是在JDK7中引入的,并在后续版本中进行了优化和改进。

而对象数组类型的话,则采用的就是归并排序和TimSort

// 1.7以前
public static void sort(Object[] a) {Object[] aux = (Object[])a.clone();mergeSort(aux, a, 0, a.length, 0);
}// 1.7以后
public static void sort(Object[] a) {if (LegacyMergeSort.userRequested)legacyMergeSort(a);elseComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}/** To be removed in a future release. */
private static void legacyMergeSort(Object[] a) {Object[] aux = a.clone();mergeSort(aux, a, 0, a.length, 0);
}

TimSort 是一种混合排序算法,结合了归并排序(Merge Sort)和插入排序(Insertion Sort)的特点。

BigDecimal(double)和BigDecimal(String)有什么区别

首先我们来看一下阿里巴巴Java开发手册的提示

其实我们可以看到,double本身就是不准确的表示一个值,取得是一个近似值,例如,new BigDecimal(0.1)  但是创建出来的值并不是0.1,而是0.100000000000000000055555555......等,但是new BigDecimal("0.1")时,创建出来的值正是0.1值是很准确的。当我们去看BigDecimal源码时可以发现,他的实现主要是用的是个无标度值标度来表示的。所以在使用double时创建的是一个不准确的值,那么如何创建一个准确的小数值呢?采用的就是BigDecimal(String),它可以完整的表示一个小数的精度

但是需要注意的是,new BigDecimal("0.10000")和new BigDecimal("0.1")这两个数的标度分别是5和1,如果使用BigDecimal的equals方法比较,得到的结果是false。

public class BigDecimal extends Number implements Comparable<BigDecimal> {private final BigInteger intVal;private final int scale; private final transient long intCompact;
}

因为计算机采用二进制处理数据,但是很多小数,如0.1的二进制是一个无限循环小数,而这种数字在计算机中是无法精确表示的。所以,人们采用了一种通过近似值的方式在计算机中表示,于是就有了单精度浮点数和双精度浮点数等。所以,作为单精度浮点数的float和双精度浮点数的double,在表示小数的时候只是近似值,并不是真实值。

所以,当使用BigDecimal(Double)创建一个的时候,得到的BigDecimal是损失了精度的。而使用一个损失了精度的数字进行计算,得到的结果也是不精确的。

想要避免这个问题,可以通过BigDecimal(String)的方式创建BigDecimal,这样的情况下,0.1就会被精确的表示出来。

Char可以存储一个汉字吗 

在Java中,使用的是编码时Unicode,因此char类型使用16位来表示,可以存储任何在Unicode字符集出现的字符。Unicode字符集包含了几乎所有的字符,包括常见字符、生僻字、罕见字以及其他语言的字符。所以,用char类型其实是可以存储生僻字的。

Java中的Timer定时调度任务是咋实现的

在JDK源码中是这样定义Timer类的

public class Timer {/*** The timer task queue.  This data structure is shared with the timer* thread.  The timer produces tasks, via its various schedule calls,* and the timer thread consumes, executing timer tasks as appropriate,* and removing them from the queue when they're obsolete.*/private final TaskQueue queue = new TaskQueue();/*** The timer thread.*/private final TimerThread thread = new TimerThread(queue);
}

可以看到,最主要的是两个变量TaskQueueTimerThread 

  1. TaskQueue:一个任务队列,用于存储已计划的定时任务。任务队列按照任务的执行时间进行排序,确保最早执行的任务排在队列前面。在队列中的任务可能是一次性的,也可能是周期性的。
  2. TimerThread:Timer 内部的后台线程,它负责扫描 TaskQueue 中的任务,检查任务的执行时间,然后在执行时间到达时执行任务的 run() 方法。TimerThread 是一个守护线程,因此当所有非守护线程完成时,它会随之终止

任务调度的核心代码如下:

class TimerThread extends Thread {boolean newTasksMayBeScheduled = true;/*** 存储 TimerTask 的队列*/private TaskQueue queue;TimerThread(TaskQueue queue) {this.queue = queue;}public void run() {try {mainLoop();} finally {synchronized (queue) {newTasksMayBeScheduled = false;queue.clear(); }}}/*** 主要的计时器循环。 */private void mainLoop() {while (true) {try {TimerTask task;boolean taskFired;synchronized (queue) {// 等待队列变为非空while (queue.isEmpty() && newTasksMayBeScheduled)queue.wait();if (queue.isEmpty())break; // 队列为空,将永远保持为空;线程终止// 队列非空;查看第一个事件并执行相应操作long currentTime, executionTime;task = queue.getMin();synchronized (task.lock) {if (task.state == TimerTask.CANCELLED) {queue.removeMin();continue;  // 无需执行任何操作,再次轮询队列}currentTime = System.currentTimeMillis();executionTime = task.nextExecutionTime;if (taskFired = (executionTime <= currentTime)) {if (task.period == 0) { // 非重复,移除queue.removeMin();task.state = TimerTask.EXECUTED;} else { // 重复任务,重新安排queue.rescheduleMin(task.period < 0 ? currentTime   - task.period: executionTime + task.period);}}}if (!taskFired) // 任务尚未触发;等待queue.wait(executionTime - currentTime);}if (taskFired)  // 任务触发;运行它,不持有锁task.run();} catch (InterruptedException e) {}}}
}

TimerThread的实际是在运行mainLoop方法,这个方法一进来就是一个while(true)的循环,他在循环中不断地从TaskQueue中取出第一个任务,然后判断他是否到达执行时间了,如果到了,就触发任务执行。否则就继续等一会再次执行。如此往复的重复,执行。

使用 Timer定时调度有哪些优缺点呢?

优点:实现简单啊,因为是JDK内置的定时调度任务,因此体量是比较小的,只需要在需要使用的地方调用方法即可

缺点:

1、Timer内部是单线程执行任务的,如果某个任务执行时间较长,会影响后续任务的执行。
2、如果任务抛出未捕获异常,将导致整个 Timer 线程终止,影响其他任务的执行。
3、Timer 无法提供高精度的定时任务。因为系统调度和任务执行时间的不确定性,可能导致任务执行的时间不准确。因此需要准时和高性能的定时任务采集时常采用xxl-job定时任务框架来完成。
4、虽然可以使用 cancel 方法取消任务,但这仅仅是将任务标记为取消状态,仍然会在任务队列中占用位置,无法释放资源。这可能导致内存泄漏。
5、当有大量任务时,Timer 的性能可能受到影响,因为它在每次扫描任务队列时都要进行时间比较。
6、Timer执行任务完全基于JVM内存,一旦应用重启,那么队列中的任务就都没有了

Java中的序列化机制是咋实现的

序列化是将对象转换为可传输格式的过程。 是一种数据的持久化手段。一般广泛应用于网络传输,RMI和RPC等场景中。 几乎所有的商用编程语言都有序列化的能力,不管是数据存储到硬盘,还是通过网络的微服务传输,都需要序列化能力。

在Java的序列化机制中,如果是String,枚举或者实现了Serializable接口的类,均可以通过Java的序列化机制,将类序列化为符合编码的数据流,然后通过InputStream和OutputStream将内存中的类持久化到硬盘或者网络中;同时,也可以通过反序列化机制将磁盘中的字节码再转换成内存中的类。

**如果一个类想被序列化,需要实现Serializable接口。**否则将抛出NotSerializableException异常。Serializable接口没有方法或字段,仅用于标识可序列化的语义。

自定义类通过实现Serializable接口做标识,进而在IO中实现序列化和反序列化,具体的执行路径如下:

#writeObject -> #writeObject0(判断类是否是自定义类) -> #writeOrdinaryObject(区分Serializable和Externalizable) -> writeSerialData(序列化fields) -> invokeWriteObject(反射调用类自己的序列化策略)

其中,在invokeWriteObject的阶段,系统就会处理自定义类的序列化方案。这是因为,在序列化操作过程中会对类型进行检查,要求被序列化的类必须属于Enum、Array和Serializable类型其中的任何一种。

Java中的注解是干嘛的

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

Java的注解,可以说是一种标识,标识一个类或者一个字段,常常是和反射,AOP结合起来使用。中间件一般会定义注解,如果某些类或字段符合条件,就执行某些能力。

元注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

这里面的@Target,@Retention就是元注解。
元注解有四个:@Target(表示该注解可以用于什么地方)、@Retention(表示在什么级别保存该注解信息)、@Documented(将此注解包含在javadoc中)、@Inherited(允许子类继承父类中的注解)。

一般@Target是被用的最多的。

@Retention:指定被修饰的注解的生命周期,即注解在源代码、编译时还是运行时保留。它有三个可选的枚举值:SOURCE、CLASS和RUNTIME。默认为CLASS。

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)
public @interface MyRuntimeAnnotation {// some elements and values
}

@Target:指定被修饰的注解可以应用于的元素类型,如类、方法、字段等。这样可以限制注解的使用范围,避免错误使用。

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyTargetAnnotation {// some elements and values
}

@Documented:用于指示注解是否会出现在生成的Java文档中。如果一个注解被@Documented元注解修饰,则该注解的信息会出现在API文档中,方便开发者查阅。

import java.lang.annotation.Documented;@Documented
public @interface MyDocumentedAnnotation {// some elements and values
}

@Inherited:指示被该注解修饰的注解是否可以被继承。默认情况下,注解不会被继承,即子类不会继承父类的注解。但如果将一个注解用@Inherited修饰,那么它就可以被子类继承。

import java.lang.annotation.Inherited;@Inherited
public @interface MyInheritedAnnotation {// some elements and values
}

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

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

相关文章

动态规划11,完全背包模板

NC309 完全背包 问题一&#xff1a;求这个背包至多能装多大价值的物品&#xff1f; 状态表示&#xff1a;经验题目要求 dp[i][j] 表示 从前i个物品中挑选&#xff0c;总体积不超过j&#xff0c;所有选法中&#xff0c;能选出来的最大价值。 状态转移方程 根据最后一步的状态&a…

harmonyOS ArkTS最新跳转Navigation

文章目录 取消标题栏初始页面(load)设置为竖屏 自定义标题Tabs&TabContentTabs通过divider实现了分割线各种属性 图片下载 官方文档 Entry Component struct Index {State message: string Hello WorldState djs:number 5build() {Column(){Navigation(){}.title("g…

达梦-华为鲲鹏ARM架构下性能测试最佳实践

一、测试综述 1.1 测试目的 本次测试的目的是验证达梦数据库&#xff0c;在鲲鹏服务器下&#xff0c;不同服务器参数基于sysbench性能压力测试的表现。本次参数是根据为华为鲲鹏arm服务器调优十板斧内建议值调整 成长地图-鲲鹏开发套件开发文档-鲲鹏社区 1.2 通用指标 指标…

基于STM32的点滴输液报警器-设计说明书

设计摘要&#xff1a; 本文介绍了基于STM32微控制器的点滴输液报警器的设计与实现。点滴输液是医疗领域中常见的治疗方式&#xff0c;但输液速度的控制对患者的安全和治疗效果至关重要。因此&#xff0c;设计一种能够监测输液速度并在异常情况下发出警报的系统显得十分必要。基…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)2.3-2.4

目录 第四门课 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第二周 深度卷积网络&#xff1a;实例探究&#xff08;Deep convolutional models: case studies&#xff09;2.3 残差网络(ResNets)(Residual Networks (ResNets))2.4 残差网络为什么有用&am…

JavaEE: 深入探索TCP网络编程的奇妙世界(一)

文章目录 TCPTCP协议段落格式TCP相关机制TCP核心机制一: 确认应答32位序号32位确认序号后发先至问题 TCP TCP要比UDP更复杂一些~ TCP的全称为"传输控制协议".他负责对数据的传输进行一个详细的控制. TCP协议段落格式 源/目的端口号: 表示数据是从哪个进程来.到哪个…

Python 如何处理大文件的读取

Python 如何处理大文件的读取 在日常的开发工作中&#xff0c;我们经常会遇到处理大文件的需求。无论是读取日志文件、处理数据集&#xff0c;还是分析超大文本文件&#xff0c;大文件操作都是一个非常常见的挑战。尤其是在内存有限的环境中&#xff0c;直接将整个文件加载到内…

Docker配置代理解决pull超时问题

操作系统: CentOS Linux 8 Docker版本: 26.1.3 前置&#xff1a;你需拥有&#x1f431; 1. 配置 proxy.conf 1.1 创建配置文件目录 创建 docker.service.d&#xff0c;进入到 docker.service.d 中打开 proxy.conf (没有文件打开会自动创建)。 注意&#xff1a;每个人的路径可…

深度学习|误差逆传播:梯度速解

文章目录 引言链式法则误差逆传播加法的逆传播乘法的逆传播逆传播求梯度 SoftmaxWithLoss 层正向传播逆传播代码实现参考 结语 引言 我们知道训练神经网络模型的核心是以损失函数为基准来调整优化网络参数&#xff0c;使得网络的输出尽可能接近真实标签。在神经网络中&#xf…

Vue使用qrcodejs2-fix生成网页二维码

安装qrcodejs2-fix npm install qrcodejs2-fix核心代码 在指定父view中生成一个二维码通过id找到父布局 //通过id找到父布局let codeView document.getElementById("qrcode")new QRCode(codeView, {text: "测试",width: 128,height: 128,colorDark: #00…

Fyne ( go跨平台GUI )中文文档-小部件 (五)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

LeetcodeTop100 刷题总结(二)

LeetCode 热题 100&#xff1a;https://leetcode.cn/studyplan/top-100-liked/ 文章目录 八、二叉树94. 二叉树的中序遍历&#xff08;递归与非递归&#xff09;补充&#xff1a;144. 二叉树的前序遍历&#xff08;递归与非递归&#xff09;补充&#xff1a;145. 二叉树的后序遍…

移动数组中数字的方法(c语言)

1.移动一维数组中的内容;若数组中有n个整数&#xff0c;要求把下标从0到p(含p&#xff0c;p小于等于n-1&#xff09;的数组元素平移到数组的最后。 例如&#xff0c;一维数组中的原始内容为:1,2,3,4,5,6,7,8,9,10;p的值为3。 移动后&#xff0c;一维数组中的内容应为:5,6,7,8…

qm 命令:管理PVE虚拟机

一、命令简介 ​qm​ 是 Proxmox Virtual Environment (PVE) 中用于管理虚拟机的命令行工具。它允许用户创建、启动、停止、删除虚拟机&#xff0c;以及管理虚拟机的配置和状态。 ‍ 介绍 PVE Proxmox Virtual Environment (PVE) 是一个开源的虚拟化管理平台&#xff0c;专…

设计模式 享元模式(Flyweight Pattern)

享元模式 简绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;它的目的是通过共享技术来有效地支持大量细粒度的对象。享元模式可以极大地减少内存的使用&#xff0c;从而提高程序的性能。它特别适用于需要创建大量相似对象的场景&#…

QT 数据加密

一.使用环境 应该是通用的,此测试版本为如图 二.使用代码 1. 运行代码 QString data = "123abcAbc.-+";qDebug() << "加密:" << QAESEncryption::encodedText(data, "填入自己秘钥");qDebug() << "解密:" <…

C++STL的Stack的使用:STL栈和队列的使用介绍、leecode---最小栈、nowcoder---栈的压入、弹出序列等的介绍

文章目录 前言一、STL栈和队列的使用二、leetcode---最小栈三、nowcoder---栈的压入、弹出序列四、逆波兰表达式求值总结 前言 CSTL的Stack的使用&#xff1a;STL栈和队列的使用介绍、leecode—最小栈、nowcoder—栈的压入、弹出序列等的介绍 一、STL栈和队列的使用 #include …

服务器安装pytorch_geometric torch_scatter踩坑记录

conda create -n pyg python3.8.12 pip install torch1.13.0安装的版本如下 pip install torch-scatter pip install torch-sparse pip install torch-cluster pip install torch-spline-conv pip install torch-geometric2.2.0 pip install ipykernel python -m ipykernel i…

Adobe Illustrator吸管工具提取的颜色与原色之间存在色差

问题原因&#xff1a; 被提取颜色的对象是外部链接图片&#xff0c;对其提取的颜色会与AI中看到的颜色不同 如下图所示&#xff0c;中间的矩形与外部矩形的内部颜色存在色差 解决办法&#xff1a; 方法一&#xff1a;将该外部图片利用屏幕截图的形式&#xff0c;粘贴到AI中。…

2.以太网

局域网 局域网: Local Area Networks (LAN) 网络大小分类 局域网园区网(可以理解为企业网)城域网 广域网是一个网络连接的技术&#xff0c;并非多大范围的网络 网关 为局域网内的用户提供了一扇门&#xff0c;通过网关可以访问到别的网络。这个门&#xff0c;就叫网关 以…