本文,我会先放出类,放出截图,可能还会写出我自己的看法。
以后,我也可以以此为鉴。
方法名驼峰+下划线并用
为什么要这样呢?
红线驼峰,绿色下划线。
我理解,某种情况下,可以提高可读性。
多个方法内容重复
为什么要这样呢?
我唯一能想到的,就是不确定代码会不会变,不会变的抽成方法,会变的,流程可能会改动的,暂时不进行公用。
1 | 2022-04-28 13:58:14 补充 |
catch块里写分号
org.slf4j.helpers.Util#safeGetSystemProperty
为什么要这样呢?
为了可读性,大可加一行注释即可。没必要加引号的。我也是第一次见到。
下面我演示了一下,实时证明,编译会进行去除。
case加大括号
2021-11-09 14:35:25
原来 case 也可以加大括号,学到了~
静态变量的描述
2021-11-30 11:47:11org.assertj.core.presentation.StandardRepresentation
写的非常清楚明了,让不知道这个类是干什么的,也可以看懂这些变量做什么的。
继承接口(向上扩展)
2021-11-30 11:49:02java.io.Closeable
在 1.5 只有 Closeable 接口。在 1.7 的时候新加了一个接口 AutoCloseable,让 Closeable 继承 AutoCloseable。
(原本 1.5 的时候,Closeable 接口是底层功能。在 1.7 的时候,把底层功能拓展了,加了 AutoCloseable 接口)
Function.identity()
package java.util.function;
虽然这个并没有什么,写 t -> t
也是可以的(我之前就是这么写的)。但毕竟写Function.identity()
更好看一些。
这里体会到封装的特性。就感觉很舒服,很漂亮的code~
接口默认方法抛异常
2022-01-12 18:37:04
为什么要这么做呢?
假设一种情况,A、B、C、D、E都实现这个接口。
A、B、C 无需对这个接口进行实现。
D、E 需要对这个接口进行实现。
设置 remove() 默认方法的话,避免了 A、B、C 要对此方法进行空实现。
嵌套延迟任务
2022-01-17 12:03:35嵌套延时任务 => 定时任务
关于:线程池之ScheduledThreadPoolExecutor 可参考 23. 线程池之ScheduledThreadPoolExecutor
初始化容量 1024
2022-01-17 15:17:06
ConcurrentHashMap<Service, Service>
=> 应该是想当 并发 Set 来使用的。
好家伙,直接初始化 1024,这个应该是注册中心的服务单例仓库,不知道为什么要搞得那么的大。
(2022-07-18 10:16:16 补:搞那么大,是因为初始化启动的时候,不想后续再进行频繁扩容,先把坑位搞大,也方便分散均匀)
代码为什么没注释
2022-01-17 15:38:03
真正的代码,只有类和方法有注释。其他地方都是没有注释的。
因为好的代码,方法和变量,以及类、接口。它们就是最好的注释。如果不是,说明你定义的具有二义性。
(2022-09-26 08:14:26 补:因为好的代码都是高内聚、低耦合设计,代码方法内注释很少,但是文档注释却补充的很完善。
但我们平时开发恰恰相反,文档注释很多,甚至不写,代码中写的注释有很多。)
(后来我在此篇文章中也提到了,我对“牛逼代码的思考”。)
关于 Nacos config 长轮询的源码
多Map嵌套的可读性
2022-01-17 15:55:33
雪花id i++
2022-01-18 15:22:14
它应该只是想表明:我的id也是不唯一的。(不是只有雪花算法生成的id才能称之为雪花id,只要不重复就是雪花id)
常量值重复,名不一致
2022-01-18 15:29:22
当然了,这样写,同样也是为了区分可读性。虽然值相同,根据常量的名称不同,而适用于不同的场景。
饿汉单例放内部类中
》》》第一次理解
2022-01-21 08:29:42
这个单例为什么不直接放外部类中呢,而要放在内部类中。这个我不太明白。
猜测:我才猜不出来。。。我只能说私有静态内部类会加载一次,然后它的静态成员变量也会加载一次。保证只有一次创建对象。
但是你放在外部也是只有一次初始化呀,即使外部的类不是 static。我不太理解。
》》》第二次理解
2022-01-22 18:14:46
我又发现了一个。但是我看源码的时候也发现有很多直接放在了外部类中private static final
修饰的啊。还是搞不懂为什么要这样写。
》》》第三次理解
2022-04-22 02:04:08
高兴!!!
我发现了这个原因的奥秘。其实我在第一次的时候就已经说了。
(现在是上海疫情期间,此时我在家里学习,真的是上头了,现在都夜里2点了。)
1 | // 它利用了关于【类初始化的语言保证】,因此可以在所有符合 Java 的编译器和虚拟机中正常工作。 |
迭代器使用 for
2022-01-22 21:25:34
迭代器使用 for 来写,而不是 while
这样可以我是知道的,只是因为我从来没这样用过,我都是用 while。
使用起来也是差不多的,只是我第一次见到这样写,仅此而已。
List封装为对象
2022-01-25 09:42:16
不直接用 List<Instance>
来进行传参,而是把这个集合封装为一个对象 Instances(多了一个s)。
而在这个对象里面提供一些方法,供外部使用。(非常好的面向对象思想,值得借鉴。)
Retransmitter,最大重试次数,ack,耗时
2022-01-25 15:19:39
Retransmitter 从翻译可以了解到:转播发射器,中继发射器。
(也就是重新进行发射的意思)。
下面是 Nacos udp 数据包发送的一个使用场景。
最大重试次数,和 ack。
耗时
List Map.Entry
2022-01-25 17:24:11
不使用 List<Map<String, Instance>>
,却使用 List<Map.Entry<String, Instance>>
,…
1 | 2022-02-09 11:26:39 |
面向对象的思想
2022-02-07 08:47:35
案例1、使用这个类来继承 Date,就可以直接使用它的格式。不用 new Date 然后再转一次,这里直接 new 即可。
案例2:使用多级继承的结构。符合依赖倒置。这个如果加功能的话,更方便一些。
1 | 面向对象的三大特性:封装、继承、多态 |
static 加 synchronized
2022-02-07 09:37:33
避免还未初始化完成 (init 未执行完成),就执行了 shutdown 方法。
为了使这两个不能同时进行,所以上锁。
特权线程工厂 Executors.privilegedThreadFactory
2022-02-07 10:55:20
只是说与父线程具有相同的权限。设置 ac(访问控制器) 与 cl(类加载器)。
(暂时还不知道这两个有什么特别用途,看这个方法也没有在其他地方用到过。)
委托的好处
2022-02-07 10:24:38
一开始,我一直没想懂 delegate 委托的好处。后来我总结了有两个地方。(依照下面图示,我称为 “外”、“内”)
1、增减方法(扩展功能、减少功能)
原本“内”有 10个方法,但是我在“外”中只定义 3个方法。把其他方法不对外提供。同理,也可以在 10个方法上,提供额外的方法。
2、扩展功能
例如在下面图示,原本“内”只拥有②级功能。现在我让“外”继承了③级功能,这样就变相的让“内”拥有了③级功能。(也就是为了扩展功能)。
3、代码易维护
例如在下面图示,我为了使用“内”的execute方法,我把“外”也定义了一个execute方法。我的程序中到处用的都是“外”.execute,即使“内”.execute 方法改名了,改为 “内”.run 了,我只需要改“外”.execute 方法一处即可,不用修改多处。
总结:委托的本质,就是为了扩展功能、和 减少功能。
其实,我当时看到上面图示这些代码瞬间惊了,为什么这样???
心想:“不行,我一定要搞清楚为什么。”
然后我百度搜索了一堆,其实都没看太懂。
直接看到了一篇:设计模式-代理模式(delegate)
而此时的 CharacterProxy 类,只能对外提供 toString() 方法。这样即使外部想使用 CharSequence 的其他方法,也使用不到了。
(于是,这里我想到了《大话设计模式》里面的一句话:大致意思是说 想扩展功能可以使用代理,不想对外提供一些功能也可以使用代理。个人理解:委托也算是代理的一种。)
1 | public class CharacterProxy { |
2022-02-07 11:15:04 再举个栗子:
是不是一眼就看出来为什么了???
让④变相的增加了③⑤功能。
Class#getPrimitiveClass
2022-02-10 09:28:16
八大基本类型算是八种。
但是原生这个方法获取,却是 9 种。多了一个 void。
枚举单例,枚举实现接口,监听器
2022-02-11 08:05:50
第一次见到单例这么来用的,直接把枚举当做 Object 来使用。
这才是我见过最好的枚举单例。即使它不算是规规矩矩的枚举。
枚举是天生单例的,众所周知。而且枚举是不可以反射进行创建实例的,其他都可以调用反射来创建实例。
所以,真实的情况是,安全的单例:只有枚举一种。
这里使用枚举的属性来控制,线程是否继续执行。这里我还测试了一把,枚举是单例的,但它的属性可以修改吗???是可以修改的。
下面是:“测试枚举的成员变量是否可以修改???”
其实用枚举就是为了不可变,所以,一般建议枚举是不要用可变成员变量的。
而且 sonar (代码扫描工具)建议枚举不要提供 setter 方法。只需要提供 getter 来获取属性值即可。
(所以,上面的使用并不是规范的用法,一般可以采用其他的方式来使用单例。这里就不说了。)
关于 hutool 监听器:
下面会存在一个问题,一旦阻塞 sync=true,这个线程就一直处于 wait(0) 状态了。
方法返回值泛型问题
2022-02-11 11:49:06
这个是使用的时候,我们不加类型强转。
这个是编译器自己加的。
静态代码块可以写多个
2022-02-18 18:01:39
第一次见到,原来还有写多个的。实际上,它们还是会被编译到一起去(从上到下编译)。
接口定义 @override 重写接口方法
2022-02-24 11:34:22
实现方法上面写 @override 是经常见到的,接口上面重新我是第一次见到。
没想懂为什么,要重新写一遍这个方法。不写也是可以的啊。
可能是开发者内部的一种规范吗???
ConcurrentHashMap 上synchronized锁
2022-02-25 17:13:12
我不明白为什么,右边的 1、3 都是 ConcurrentHashMap,但是中间还要上synchronized锁(this是单例的)。
即使 2 上了锁,3依然会被覆盖掉的。2好像是多于的。3也只是占个坑。
线程中断异常,再中断
2022-02-25 17:19:28
wait 是忽略了中断异常,而 sleep 是又中断了一次。
Math.random,Random,ThreadLocalRandom
2022-03-23 09:19:42
为什么要定义一个私有静态不可继承类呢?直接定义一个成员变量它不好吗? 还要多写一个类。
在 Math 类中定义一个成员变量也可以,但是这个东西貌似不属于 Math,体现了不单一。
单写一个类,体现了 类的可读性以及单一原则。
包括一些单例的时候,有的人也会定义一个私有类,在之前也写过。
直接在类中写单例行不行,也可以的。
后续思考。
可以看到方法上面,说到了这个方法生成一个 double 值:大于等于 0.0,小于 1(并且是伪随机的偏向于均匀分布的算法)。
并且它说这个方法是线程安全的 synchronized,但是你要告诉进行生成,会产生线程的争用。
我们来进一步分析:
对于以上随机生成效率不高,解决方案是什么呢?
》》》类似于 ThreadLocal 思想的,基于 Thread 类的成员变量,来做到线程隔离来避免争用。
内部类调用外部类
2022-03-24 18:53:20
以前我没注意过这个问题。
今天突然想到。
答案可参考:深入理解Java中为什么内部类可以访问外部类的成员
两个准则:
1、内部类对象的创建依赖于外部类对象。
2、内部类对象持有指向外部类对象的引用(参考下面编译后的图片)。
异常单例
2022-03-25 17:15:02
某些异常是可以实现单例的。例如下面的警告。
当然,还是传入指定场景信息最好,对吧。
do{…}while(true);
2022-03-25 17:27:49
这样写,适用于必须要走一次。(while true 在前面,好像也能表达这个意思。)
单例池
2022-04-30 06:41:24
原因是我看到一个方法被废弃了,我看了一下。雪花对象应为单例。
下面我又看了一下单例的实现,这个时候我发现了 lambda函数表达式的一个用途(防止参数下传)。
之前没发现,现在突然悟到了,就是参数不下传,可以使用回调。
异常定义
2022-05-11 08:55:51
无论怎么样,在能复用的情况下,最好定义异常对象。
这样使代码更友好。例如:你的权限校验异常在哪些地方会用到。一眼便知。
SPI机制的数据提供者
2022-05-11 08:58:55
我的天呐,这是缘分吗。怎么会那么的巧呢。
前两天我在写预警中心,发送服务逻辑的时候。
正好我最近在看 datart 的取数逻辑。
虽然都是一样的,但是实现方式是完全不同的,而且我的逻辑相对来说比较单一,直接用类进行区分。这里使用SPI机制来设计,分module 来设计,完全的解耦了。可选择性依赖。插件式扩展服务。
(2022-06-18 21:18:19 其实网上大部分说的SPI都是jdbc,以及Dubbo)
Exceptions.throw
2022-05-23 18:50:42
1 |
|
1 |
|
枚举$数字开头
2022-06-08 07:59:19
插入、更新数据
2022-06-12 18:15:08
Map 语法糖
2022-06-28 09:47:00
1 | Map {{}} 语法糖 |
2022-07-06 17:07:48 什么鸡儿语法糖,这就是匿名内部类,可以在 {} 里面重写方法,只不过在 {} 里面写了一个构造代码块而已。
日志本地彩色,文件非彩色
2022-07-05 15:01:10
一开始,我设置了彩色,本地很漂亮,发布测试环境上去发现显示不友好,我就把彩色去除了。
我忘记了,本地彩色,测试环境非彩色。
测试 Kafka
2022-07-05 15:47:55
我都是用kafka那个脚本测试,第一次见到有人代码这样单元测试来搞。
记录异步
2022-07-09 20:08:35
来一张图片理解一下:
第一次见到这种注释
2022-07-16 16:53:51
Lambda函数的柯里化
2022-07-16 18:48:07
下面演示一下: 4+2=6
1 | // 2022-07-16 19:29:39 Lambda函数的柯里化 |
Lambda函数的 & ZAM接口
2022-07-18 10:13:17
记忆化的实现我知道,下面也很容易理解,就是绿色的部分,实现懒加载,但是红色的部分更是让我很好奇。
我在 JavaSE 官方文档 —> 泛型 —> 多重有界的类型参数中,找到了答案。
我们来实现一个标签化
1 | // java中的lambda,需要先定义一个 只有一个抽象方法的接口,称为SAM类型, |
Lambda的方法引用类型问题
2022-07-18 10:13:52
Lambda 表达式 — Oracle 官方文档 — Lambda Expressions (The Java™ Tutorials > Learning the Java Language > Classes and Objects) 2022-07-16 18:00:29
Lambda 表达式 方法引用 — Oracle 官方文档 — Method References (The Java™ Tutorials > Learning the Java Language > Classes and Objects) 2022-07-16 18:05:41
先把官方文档放在上面。
下面这个文档注释中的type3 表达的意思是什么,我到现在还不清楚。
1 | // 2022-07-18 10:25 方法引用测试 |
对了,方法引用还可以这样。
常量字段引用问题
2022-07-18 10:42:47
去年我拿着这个问题,我问了我同事 孙凯隆,但是他也似懂非懂,也没说出来什么所以然。
今天我看了一下注释,难道我当初没看注释吗?对于这个我没有实际的例子,如果你有很好的案例请发给我,谢谢你。
在刚才邹俊问的我的时候,很庆幸,我突然领悟到了,并且示出了demo。
枚举单例应用
2022-07-22 20:31:37
真正意义上的单例。我知道有这么一种,但是在JDK源码中还是第一次见到这种写法。
方法里面代码块的变量名重复问题
2022-07-27 18:50:34
枚举不大写
2022-08-05 18:21:19
代码是你的,你爱怎么玩就怎么玩。写出来的东西,用的人多,大家认可你的产品才是最好的,代码规范次要。
ArrayList 数组是 transient
2022-09-02 15:38:06
优化做到极致,假设数组 length 是 10,里面只有1个元素(size=1),那么我就只序列化这一个元素。
类里面 ThreadLocal
2022-09-16 14:44:11
不单独写一个类了,直接写在自己类里面。
这样也比较方便,感觉这样挺好的,即使类没有分离。
使用静态获取Bean中的DAO
2022-09-15 10:23:04
1 | 关于更新插入的问题之前已经讨论过了。上次看到的是 Quartz 心跳检测这一块。 |
2022-09-23 18:29:24 这里我们是可以玩一个骚的。
所有类都不要任何注入,所有的类全部注入到一个类中。
使用一个类的静态方法来进行调用那些注入的成员变量。
使用:$.beanName()
来进行调用,这样有什么好处呢?不用每个类都要写 @Autowired Xxx xxx;
1 | package com.amoros.hawkeye; |
静态注入
2022-10-13 14:23:58
我之前都是实现 InitializingBean 接口来实现,今天看到这个实现方式。
也就是 setter 来实现静态注入。
of泛型数组
2022-10-20 09:31:47
获取Main方法所在的Class类
2022-11-08 09:41:00
1 | 我想在 D.d() 方法中获取 main方法所在的Class类,应该怎么办? |
@Deprecated 已弃用 版本升级问题
2022-11-08 14:37:55
异常处理 — 应该永远不要到这里
2022-11-08 16:01:52
哈哈哈,代码是你的,这样也没毛病,纯粹是语法问题
单例内部类
2022-11-09 09:26:38
记得以前也记录过单例内部类,这里再记录一次吧。因为我看到了,hutool 上面的详细注释。
1 | // cn.hutool.core.convert.ConverterRegistry |
Type 和 Class 为什么并存???
2022-11-09 09:01:50
1 | 看到 Spring事件推送的时候,使用 ResolvableType来管理,事件类型对应的 ApplicationListener监听器。 |
1 | // 2022-11-09 09:01 TypeReference Type 类型引用问题 => Json 字符串转换 |
isAssignableFrom 与 instanceof
2022-11-14 08:35:01
Class 使用 isAssignableFrom,实例化对象使用 instanceof
德摩根公式
2023-01-11 09:48:15
具体可参考:德摩根定律
异常的再次思考
2023-03-23 14:22:41
原本我认为 throw e; 如果e不属于RuntimeException的话,必须要处理或者在方法加 throws 扔出去。
案例1、e1()方法,catch 住,可以 throw 非RuntimeException。
案例2、e2()方法,catch 住,不可以 throw 非RuntimeException(必须要处理 或 包装为 RuntimeException 或 throws 出去)。
泛型方法匹配问题
首次碰到这个问题是 datart 中 2022-09-16 18:49
恰好 ck 又支持 IN 中有大括号(下面两种写法在 ck中都可以)
1 | AND store_id IN (1,4) |
留稿(之前也写过一次,但不知道放在了哪里了)
也可参考:Java基础总结 - 泛型
1 | // 2023-03-23 14:44 ? extends super 泛型方法匹配问题 再回顾 |
泛型feign调用问题
传入保证类型只要是集合就没问题,因为 feign会被序列化/反序列化。
(A调用 B.b(T t) 假设参数 T是个 List
1 | // 2023-03-23 15:59 泛型feign调用问题 |
抽象方法 getSelf
2023-06-06 10:19:18
一开始看到这个抽象类,并且还说 getSelf,而继承这个抽象类的呢,重写返回 this。
这有什么用呢,再仔细一看,大有道理。
“抽象方法 getSelf,而非this” 这样可以使具体的实现类,可以调用基础方法并返回自己,实现链式调用,并且返回的是实现类。
让我想到了之前我重写了 Row 继承了 Dict 使用其中的 set 返回的是 Dict 而非 Row。因此我又重写了一个 set方法。
GetMapping路径参数映射对象问题
2023-12-20 18:14:51
这是 springboot一直支持的,但这是我第一次见到这种用法。
vite前端代理解决跨域问题
2023-12-20 15:22:42
原来前端也可以做代理,这样浏览器还不会拦截到。
(可简单理解为一个隐藏的 nginx)
(好比,你请求了 3000端口的 controller, controller 内部发送 http 到 8080端口到别的服务,把结果返回给 3000端口。)
Func0 throws Exception
2024-03-28 11:50:31
Func0 throws Exception(只有使用的时候才会抛出异常,并且可以包装为 RuntimeException 方法)
多个静态代码块 静态变量写在一起
2024-04-11 11:42:41
第一次见到 这种写法,看着挺舒服的,不用找这个 静态变量在哪里初始化的了。(可以借鉴)
if break问题
2024-04-29 10:44
if break 问题,我第一次在这里见到。
这次研究后,我才知道: continue a; break a; 是跳出 a 这段代码,而不是从 a 继续往下执行。
1 | // 2024-04-29 10:44 再研究 continue a; break a; |
Thread.sleep(0)问题
2024-06-21 14:34
参考 ===> 没有二十年功力,写不出这一行“看似无用”的代码!
2024-07-10 补:在jvm中,周志明也有提到此问题。
1 | // 2024-06-21 14:34 Thread.sleep(0) ===> https://mp.weixin.qq.com/s/NdlkSRTEthMi8OmFu4PbfQ |
finalize 方法自救
2024-07-08
1 | static class FinalizeEscapeGC { |
static非初始化问题
2024-07-10
1 | static class NotInitialization {// 非主动使用类字段演示 |
static代码块修改问题
2024-07-10
1 | static class TestStaticBlock { |
自定义类加载器 instanceof问题
2024-07-10
1 | static class ClassLoaderTest {// 类加载器与instanceof关键字演示 |
数组负索引编译问题
2024-07-10
1 | static class ArrayNegativeIndex { |
字段不参与多态
2024-07-10
1 | static class FieldHasNoPolymorphic {// 字段不参与多态 |
调用爷爷的方法
2024-07-10
1 | static class GrandFather_thinking { |
多线程顺序打印AB问题
2024-07-11
1 | 邹俊遇到了一个问题,写不出来。 |
我写的四种
1 | import cn.hutool.core.lang.Console; |
Kimi 写的三种
1 | import java.util.concurrent.CountDownLatch; |