本地编译调试JDK源码
一、下载源码实际上源码就在这里,不用下载 手动滑稽
二、新建项目新建普通的 Java 项目即可,将上一步的 src.zip 解压,里面的内容复制到项目中的 src 目录中(比较耗时和CPU)
另外 新建一个测试包,切记不要以 java 开头,会报错,在里面新建测试类
三、新建测试类、编译源码个人编译的是 Java8,其它版本可能略有不同。
编译前可以选择性地删掉一些不想看的包,前提保证不报错。
本来不想删的,但这里由于编译时还是报了错,所以我删掉了 com.sun.java.swing 和 com.sun.source
在测试包下新建测试类:
12345678910111213package learn.java.util;import java.util.HashMap;import java.util.Map;public class HashMapTest { public static void main(String[] args) { Map<String, Object> map = new HashMap<&g ...
Mybatis-自定义TypeHandler
前言TypeHandlerTypeHandler 是 Mybatis 中的类型处理器,用于 JavaType 和 JdbcType 之间的切换
1234567891011public interface TypeHandler<T> { void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; T getResult(ResultSet rs, String columnName) throws SQLException; T getResult(ResultSet rs, int columnIndex) throws SQLException; T getResult(CallableStatement cs, int columnIndex) throws SQLException;}
BaseTypeHandlerBaseTypeHandler 是在 TypeHandler 的基础上做的一层封 ...
类加载机制
虚拟机把Class文件加载到内存,并且对数据进行校验、转换解析和初始化,形成虚拟机能够直接使用的 Java 类型,java.lang.Class
(1) 装载
查找和导入 class 文件
类加载机制 ClassLoader:双亲委派机制
(2) 链接
(3) 初始化
记录Long类型在对接时的坑
问题在最近的一次前后端对接的时候,我向前端传递了一个用雪花算法生成的 Long 类型的字段,该字段在数据库中的值如下:
1224972467449012226
直到自己用 swagger 测试了一下,发现结果如下:
1224972467449012200
原因大致的原因显然是因为丢精
在Java中,Long 类型的最大值是 2^63-1 (9223372036854775807)
而在JS中,Number 类型的最大值为 2^53 (9007199254740992)
因此当Long类型的表示的数字过大时,就会出现丢精的问题,后面的数字用0填充
解决方案解决 Long 类型与 Number 类型的精度问题,大致方案就是将 Long 类型转换为 String 类型,这样不管多长的数字,前端也都能够兼容。
一、修改get方法1234private Long id;public String getId(){ return ""+id;}
这是相对于比较简单粗暴好理解的方法,缺点是对于使用 lombok 的懒癌程序员有点麻烦。
二、通过注解的方式改 ...
collection.toArray传入泛型
今天发现一段源码,大概是这个样子的:
123List<Method> methods = new ArrayList();......return methods.toArray(new Method[0]);
我明白大致意思应该是要通过一个Collection集合返回一个Method类型的数,但是下面的几个问题不禁让我思考。
为什么要传入一个new Method[0]这样长度为0的数组Collection类中有两个 toArray 方法
12Object[] toArray();<T> T[] toArray(T[] a);
从方法签名可以看出第一个方法是返回Object类型的数组,而第二个方法返回泛型数组。
也就是说 T[] a 的作用仅仅是规定返回类型?
如果只是返回泛型的话为什么不直接 <T> T[] toArray(Class<T> clazz);
先查看ArrayList的源码:
1234567891011public <T> T[] toArray(T[] a) { // a的长度不足集合中 ...
源码分析gateway限流
前段时间在使用 springcloud gateway 的时候,发现 gateway 自带了限流功能,下面先介绍如何使用
使用方法gateway提供了以下几种限流方式
1. 根据IP限流1234@Beanpublic KeyResolver ipKeyResolver() { return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest() .getRemoteAddress()).getHostName());}
2. 参数限流(这里演示为以 userId 参数限流)1234@Beanpublic KeyResolver userKeyResolver() { return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest() ...
记一次group by的坑
今天在使用 MySQL 的 GROUP BY 的时候报了个错,心想这个 SQL 怎么看都不应该报错才对啊。
以下内容只适用于 MySQL 5.7 及以上的版本
示例为了方便举例子,这里先建两张简单的表
用户表:user(id, name, password)
房产表:house(id, username, address)
其中用户表用来存储用户信息,房产表存储用户的房产信息,那么显示每个人的信息以及拥有的房产信息:
12345SELECT DISTINCT u.*, h.*FROM `user` AS u LEFT JOIN house AS h ON u.`name` = h.username GROUP BY u.`name`
1055 - Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘learning.h.id’ which is not functionally dependent ...
AQS
AQS 是用来为Java的并发同步组件提供统一的底层支持
AQS有2个重要组成部分:
state 同步状态,int 类型
一个同步队列
在基于AQS构建的同步器类(如 ReentrantLock,CountDownLatch)中,最基本的操作包括各种形式的获取操作和释放操作。获取操作是一种依赖状态的操作,并且通常会阻塞。释放操作并可非阻塞的操作,当执行释放操作时,所有在请求时被阻塞的线程都会开始执行。
如果一个类想成为状态依赖的类,那么它必须拥有一些状态。AQS负责管理同步器类中的状态,它管理了一个整数状态信息,可以通过 getState,setState,compareAndSetState 等protected 类型方法来进行操作。
这个整数可以用于表示任意状态。例如 ReentrantLock 用它来表示所有者线程已经重复获取该锁的次数,Semaphore 用它来表示剩余的许可数量,FutureTask 用它来表示任务的状态(尚未开始、正在运行、已完成以及已取消)。在同步器类中还可以自行管理一些额外的状态变量,例如,ReentrantLock 保存了锁的当前所有者的信息,这样 ...
Dockerfile常用语法
格式
指令 参数
Dockerfile 无视大小写,但是代码规范中要求指令名大写,参数小写
Dockerfile是按顺序执行的
Dockerfile中第一个有效指令必须为 From,用来指定基础镜像
常用指令FROMFROM 指令是最为重要的一个,并且必须为 Dockerfile 文件开篇的第一个非注释行,用于为镜像文件构建过程指定基础镜像,后续的指令运行于此基础镜像提供的运行环境
这个镜像可以是任何可用镜像,默认情况下 docker build 会从本地仓库找指定的镜像文件,如果不存在就会从 Docker Hub 上拉取
语法:
1234# 不指定版本的情况下默认为 latestFROM <image>FROM <imgae>:<tag>FROM <image>@<digest>
MAINTAINER(弃用)Dockerfile 的制作者提供的本人详细信息
Dockerfile 不限制 MAINTAINER 出现的位置,但是推荐放到 FROM 指令之后
语法:
1MAINTAINER <name>
na ...
布隆过滤器
应用场景在了解什么是布隆过滤器之前,先了解布隆过滤器能做什么,有什么应用场景。
1、缓存穿透一些用户经常访问的热点数据,我们通常将它们放进缓存(例如Redis)中,获取数据时先从缓存中获取,若缓存中不存在,则访问数据库。但是,当某些用户恶意的传递一些不会存在的数据,例如传递id=-1 或者随便传递一个UUID,这个时候数据库中没有这个数据,缓存当中自然也不存在。倘若用户连续访问,大量的请求可能会造成数据库崩溃。而通过布隆过滤器,则能够过滤掉一些不存在的数据(不能保证全部过滤),拦截掉一些恶意请求。
2、海量数据,判断给定的数据是否存在对于判断一个数据是否存在,我们通常会想到 HashMap,但是对于大量的数据,HashMap 会占用大量的内存。这个时候可以使用 布隆过滤器 来解决这个问题,但是基于布隆过滤器本身的原理,会存在一定的误判率(如果无法接受误判率,bitMap也许是个不错的选择)。
什么是布隆过滤器布隆过滤器的原理与 bitMap 有些类似。它实际上是一个很长的二进制向量和一系列随即映射函数。 布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一 ...