java基础
文章平均质量分 63
一入java深似海
爱琴孩
扫盲+科普+解惑,愿天下程序员每天少掉头发
展开
-
五年经验,连个文件下载方法都写不好
在java web开发中,我们经常遇到浏览器文件下载的功能,看似很简单的功能,有些几年经验的老鸟,都写不好,大家遇到这种功能,都是直接Ctrl+C一下代码,具体代码估计都没看。下面有两种写法对比,很多初学者都没注意,甚至有几年开发的经验的老鸟也时候也会犯错。原创 2024-03-31 13:41:33 · 299 阅读 · 0 评论 -
彻底理解IO模型
IO,英文全称是Input/Output,翻译过来就是输入/输出。平时我们听得挺多,就是什么磁盘IO,网络IO。那IO到底是什么呢?是不是有种懵懵懂懂的感觉呀,好像大概知道它是什么,又好像说不清楚。IO,即输入/输出,到底谁是输入?谁是输出呢?IO如果脱离了主体,就会让人疑惑。转载 2024-03-26 22:40:31 · 44 阅读 · 1 评论 -
为什么在高并发场景下,推荐使用 LongAdder
在分布式系统中,计数器是一个常见的需求。为了实现高并发、高可用的计数器,我们需要选择一个合适的实现方式。在 Java 中,有两种常见的计数器实现方式:AtomicLong 和 LongAdder。阿里巴巴在一份技术报告中推荐使用 LongAdder ,而不是 AtomicLong。本文将介绍这两种计数器的原理和优缺点,并分析为什么阿里巴巴推荐使用 LongAdder。LongAdder是JDK1.8由Doug Lea大神新增的原子操作类,位于。转载 2023-12-23 16:54:28 · 99 阅读 · 1 评论 -
java日志系统深度解析
前段时间爆出的log4j安全漏洞,想必大家都紧急对项目中的log4j进行升级了,对于日志产品,log4j只是其中的一种,这里来和大家一起深入学习下日志系统的演变历史。原创 2022-01-22 16:34:52 · 1438 阅读 · 0 评论 -
还在用contains进行List去重?
定义Student对象初始化包含重复元素的集合List。原创 2023-06-17 17:30:54 · 89 阅读 · 0 评论 -
Stream流sorted的多级排序问题(巨坑)
之前在给一个List集合中对象进行多属性排序,比如先根据对象中的A属性正序排序,若两个对象的A属性值相同,再根据对象的B属性进行正序排序。这种排序在实际开发中比较常见,但是这里面有个坑。原创 2023-06-11 14:23:22 · 2475 阅读 · 0 评论 -
一文搞懂布隆过滤器
布隆过滤器是一个很长的二进制向量和一系列随机映射函数,用于检索一个元素是否在一个集合中。它的空间效率和查询时间都远远超过一般的算法,但是有一定的误判率 (函数返回 true , 意味着元素可能存在,函数返回 false ,元素必定不存在)。转载 2023-05-13 10:56:56 · 274 阅读 · 3 评论 -
五年经验,不知道SOLID原则?
在软件架构设计领域,有一个大名鼎鼎的设计原则——SOLID原则,它是由由Robert C. Martin提出的,指导我们写出可维护、可以测试、高扩展、高内聚、低耦合的代码。转载 2023-01-27 14:52:34 · 120 阅读 · 1 评论 -
为什么不推荐使用BeanUtils属性转换工具
这就导致在使用很多属性映射工具时,编译时不容易明显的错误。首先公司内部就遇到过 commons 包的 BeanUtils 进行属性拷贝性能较差的真实案例,然后该同事换成了 Spring 的 BeanUtils 性能好了很多,感兴趣大家可以使用性能测试框架或者基准测试框架去对比,这里就不对比了。因此慎用属性转换工具,如果可能建议自定义转换类,使用IDEA插件自动填充,效率也挺高, A 或 B 中任何属性类型不匹配,甚至删除一个属性,编译阶段即可报错,而且直接调用 get set 的效率也是非常高的。转载 2023-01-08 22:36:43 · 175 阅读 · 0 评论 -
五年经验,接口设计还返回Long类型字段?
前段时间有个同事问,集成环境服务是不是有bug,操作过程中提示音频不存在,后来经过排查发现是接口返回的Long音频id,js对Long类型有精度丢失问题。之前audioId是数据库的自增id,后来因为数据库分库分表,audioId采用了雪花算法生成,生成的audioId是17位,js中数字超过16位就会有精度丢失问题。可以看看数据库里面的audioId再看看前端展示的audioId。原创 2022-12-28 21:25:22 · 371 阅读 · 2 评论 -
导出功能,文件名中文乱码问题(兼容多浏览器)
一般在TOC的PC项目中,我们在浏览器的导出功能,经常会遇到浏览器中文乱码问题,所以在服务端文件名编码就需要考虑浏览器兼容问题。原创 2022-10-07 17:34:56 · 1076 阅读 · 0 评论 -
notepad++ \r\n替换成回车换行
之前排查字幕订单结果丢失问题,下载下来的结果中包含\r\n来换行的,在txt文本中查看不方便,原始文档如下想要把字符串中的\r\n展示成换行,便于阅读。替换操作: 全部替换之后的效果如下 日常工作的小技巧......原创 2022-07-10 13:35:44 · 8266 阅读 · 0 评论 -
Unrecognized SSL message, plaintext connection?
在排查问题的时候,经常会出现偶现问题,这时候就要考虑环境的是否有多节点,节点环境、配置是否一致。之前还出现过mq配置错的,测试环境的mq消费了集成环境的消息问题,所以在排查问题的时候要冷静,要看异常日志的实际报错信息,从而再排查问题。......原创 2022-07-02 07:56:51 · 3437 阅读 · 0 评论 -
Stream中的map和peek,你用废了么?
前言Stream中的map,我们在开发中经常使用,但是有时候IDEA推荐我们把map换成peek使用在将map替换为peek之后,IDEA放心了,不提示了,执行结果如下,可以看到student对象的age都被修改为18了。[姓名=海洋,年龄:18, 姓名=胖虎,年龄:18, 姓名=陆敏,年龄:18, 姓名=姚君,年龄:18]但是下面这种使用peek方式,结果却和预期不一样执行结果如下[a, b, c, d]上面执行的结果,output并没有被转换成大写。这又是咋回事.原创 2022-05-22 12:56:40 · 5835 阅读 · 1 评论 -
Predicate那点事
前言Predicate在开发中我们可能用到的不多,但是有些场景,我们可还用一下,提高代码的可读性 @Test public void testPredicate() { List<Student> students = new ArrayList<Student>() {{ add(new Student("爱琴孩风", 20)); add(new Student("蒋墨风", 21));原创 2022-05-01 19:36:59 · 361 阅读 · 1 评论 -
用了Stream 流,代码更优雅了?
Java8 的 Stream 流,加上 Lambda 表达式,可以让代码变短变美,已经得到了广泛的应用。我们在写一些复杂代码的时候,也有了更多的选择。代码首先是给人看的,其次才是给机器执行的。代码写的是否简洁明了,是否写的漂亮,对后续的 Bug 修复和功能扩展,意义重大。很多时候,是否能写出优秀的代码,是和工具没有关系的。代码是工程师能力和修养的体现,有的人,即使用了 Stream,用了 Lambda,代码也依然写的像屎一样。不信,我们来参观一下一段美妙的代码。好家伙,filter 里面竟然带着潇洒的逻转载 2022-04-28 21:42:16 · 411 阅读 · 0 评论 -
SpringBootTest那点事
前言前段时间胖虎同学问我这边是怎么做的代码自测,想了下,代码自测?想必很多小伙伴说直接用postman测不就ok了么?但是我个人还是比较倾向于在项目中写单元、功能测试用例,测试代码也需要提交到git上,这样后续维护起来比较方便,postman测试团队合作效果较差,目前我这边团队没有代码自测的规范,有的用postman,有的jmeter,有的写单元测试,一个模块功能后续需求有变更,换个同学开发,那之前的测试数据都没有了,需要重新对接口进行配置测试。我还是比较喜欢在项目的Test目录去写相关测试代码,这里来原创 2022-03-26 20:44:10 · 1607 阅读 · 0 评论 -
3年经验,还纠结值传递、引用传递?
前言之前做codeReview的时候,有个同事对传入方法的Integer做修改,在方法外层还判断Integer 值是否更新了,不知道大家在日常开发是否也遇到这种情况。想必大家也背过java方法入参是值传递还是引用传递的面试宝典。但是在实际编码的时候还是需要多注意这些小细节。值传递 or 引用传递值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。引用传递(pass by reference)是指在调用函数时原创 2022-02-26 13:19:35 · 991 阅读 · 0 评论 -
缓冲流那点事
前言使用FileInputStream、FileOutputStream实现文件读写功能,是没有什么问题的。但是呢,可以使用缓冲流BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream等,减少IO次数,提高读写效率。如果是不带缓冲的流,读取到一个字节或者字符的,就会直接输出数据了。而带缓冲的流,读取到一个字节或者字符时,先不输出,而是等达到缓冲区的最大容量,才一次性输出。反例: public void n原创 2021-10-25 22:59:16 · 133 阅读 · 0 评论 -
快速获取一天的开始时间和结束时间
前言在日常开发中,我们经常需要获取某一天的开始时间和结束时间,然后再去做一些逻辑处理。这里提供两种demo。java8之前这种是采用收到设置日期的时分秒为需要的格式,具体代码如下 @Test public void getLastDayTime() { Date date = new Date(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date原创 2021-10-24 09:58:22 · 5288 阅读 · 4 评论 -
3年经验,还不知道Collections.singletonList
前言Collections是java集合中的静态方法类,类中定义了集合中常用方法。这里来和大家一起看看里面常用的方法。Collections.singletonList()这个方法主要用于只有一个元素的优化,减少内存分配,无需分配额外的内存,可以从SingletonList内部类看得出来,由于只有一个element,因此可以做到内存分配最小化,相比之下ArrayList的DEFAULT_CAPACITY=10个。 /** * Returns an immutable lis原创 2021-09-01 22:31:56 · 9354 阅读 · 3 评论 -
Java BigDecimal 如何去掉末尾多余的 0
前言在日常项目中,我们经常会和价格啥的打交道,这时候为了保证数据的准确性,我们一般会用BigDecimal来定义字段属性。BigDecimal有很多坑,平时开发中一定多注意,小细节要多注意,不小心就是一个现网事故啊。BigDecimal的导致的科学计数法展示问题No BB,直接上demo @Test public void testBidDecimal() { //未设置小数位数,直接去掉了后面的小数0 BigDecimal test = new B原创 2021-08-06 23:09:32 · 10358 阅读 · 5 评论 -
小小Array.asList,恐怖如斯
前言日常开发中,我们会经常用到Arrays.asList将数组转换成集合,这里一起总结下开发中遇到的小问题。定义数组尽量不要用基础类型下面就是常见的将数组转换成集合List,废话不多说,代码如下 @Test public void testAsList() { //数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在 long[] audioIdArray = {111, 222, 333}; long audioI原创 2021-07-18 09:29:30 · 95 阅读 · 0 评论 -
深度解析SPI之Dubbo SPI
前言Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。接下来,我们先来了解一下 Java SPI 与 Dubbo SPI 的用法,然后再来分析 Dubbo SPI 的源码。DubboSPIDubbo 中实现了一套新的 SPI.转载 2021-07-08 22:01:35 · 176 阅读 · 0 评论 -
深度解析SPI之JDK SPI
前言前面我们在深度解析SPI之SPI 有什么用?中简单举了个栗子,显然我们想拓展一个YAML,需要重新修改代码,这种做法是不便于拓展的。这里我们一起看看JDK如何通过SPI去处理这种问题。JDK SPIJDK 中 提供了一个 SPI 的功能,核心类是 java.util.ServiceLoader。其作用就是,可以通过类名获取在"META-INF/services/"下的多个配置实现文件。为了解决上面的扩展问题,现在我们在META-INF/services/下创建一个com.github.k转载 2021-07-07 23:22:35 · 184 阅读 · 0 评论 -
深度解析SPI之SPI 有什么用?
何为SPISPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。使用SPI之前的痛举个栗子,现在我们设计了一款全新的日志框架:super-logger。默认以XML文件作为我们这款日志的配置文件,并设计了一个配置文件解析的接口:package com..转载 2021-07-07 23:06:58 · 2650 阅读 · 0 评论 -
枚举类邂逅设计模式
前言日常开发中我们会经常用到枚举类,这里枚举类分别邂逅了策略模式和单例模式,会擦出怎样的火花呢?邂逅策略模式策略模式想必大家都熟悉,这里不过多解释了,这里通过枚举类来简单实现过策略模式public enum StrategyPatternEnum { PAPER(1) { @Override String getTitle() { return "长贴标题"; } }, VIDEO_TWEET(原创 2021-07-01 20:16:17 · 214 阅读 · 0 评论 -
java自定义注解
前言注解是一种能被添加到java源代码中的元数据,方法、类、参数和包都可以用注解来修饰。注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理。元注解JDK中有一些元注解,主要有@Target,@Retention,@Document,@Inherited用来修饰注解。@Target表明该注解可以应用的java元素类型@Retention表明该注解的生命周期@Document表明该注解标记的元素可...原创 2021-06-27 12:13:22 · 192 阅读 · 1 评论 -
二维码扫码登录的原理
二维码登录的本质二维码登录本质上也是一种登录认证方式。既然是登录认证,要做的也就两件事情!告诉系统我是谁 向系统证明我是谁比如账号密码登录,账号就是告诉系统我是谁, 密码就是向系统证明我是谁; 比如手机验证码登录,手机号就是告诉系统我是谁,验证码就是向系统证明我是谁;那么扫码登录是怎么做到这两件事情的呢?我们一起来考虑一下手机端应用扫 PC 端二维码,手机端确认后,账号就在 PC 端登录成功了!这里,PC 端登录的账号肯定与手机端是同一个账号。不可能手机端登录的是账号 A,而扫码登录以后,PC转载 2021-05-09 16:24:29 · 366 阅读 · 0 评论 -
偶遇java.lang.UnsatisfiedLinkError异常
前言最近在和第三方联调接口,接口签名算法需要使用Hmac签名算法,本来服务已经在拦截器中写了一套签名校验逻辑,正在和第三方联调,但是由于中台组计划做个一个通用的API网关,所以服务本身的签名校验规则需要和API网关保持一致,按照中台组提供的Hmac算法需要依赖dll动态库,中台组提供了dll文件,这边现在本地进行调试。调试过程中出现下面这货解决思路由于之前没有使用过java调用DLL动态库,所以遇到这个异常也是一头雾水,在网上查了,有类似问题,说DLL文件位置不对。但是中台组提供的调用.原创 2021-04-24 13:29:11 · 972 阅读 · 0 评论 -
最透彻解析try-with-resource
前言Try-with-resources是java7中一个新的异常处理机制,它能够很容易地关闭在try-catch语句块中使用的资源。jdk7之前下面是按行读取txt的小demo,数据处理之后需要在finally中关闭流 public void handleResourceBeforeJdk7() { String encoding = "utf-8"; File file = new File("e:/1/test.txt"); In原创 2021-02-06 22:11:34 · 3587 阅读 · 7 评论 -
邮件发送工具类
前言日常开发中,经常有发送邮件的需求,这里整理了下邮件发送的工具类,方便后续ctrl+c,ctrl+v。引入依赖目前项目中使用的是这个版本,具体的版本号,小伙伴可以自行决定哈,能用就行 <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId>原创 2021-01-26 22:17:25 · 1203 阅读 · 0 评论 -
stream中的map和flatMap
前言对于刚刚接触stream中的小伙伴,可能都有个疑惑,那就是map和flatMap到底有啥区别,这里来和大家一起简单复习下。举个小栗子public class StreamTest { private static List<Student> computerClub = Arrays.asList( new Student("2015134001", "小明", 15, "1501"), new Student("2015原创 2021-01-19 20:37:12 · 4016 阅读 · 0 评论 -
并发重复请求的优雅处理方式
前言对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,例如交易的接口如果重复请求可能会重复下单。利用唯一请求编号去重你可能会想到的是,只要请求有唯一的请求编号,那么就能借用Redis做这个去重——只要这个唯一请求编号在redis存在,证明处理过,那么就认为是重复的。String KEY = "REQ12343456788";//请求唯一编号long expireTime = 1000;// 1000转载 2021-01-17 14:04:16 · 332 阅读 · 0 评论 -
java -jar 报错 没有主菜单属性
前言今天因为需求原因,翻开一个老组件,打成jar包之后用exe4j生产exe文件的老是报错,后来直接在本地java -jar那jar也报错,报错没有主菜单属性,显然是构建的jar有问题的。对于"没有主菜单属性",熟悉springboot的小伙伴估计都会去找一下Manifest.mf文件。打开傻眼了,就这Manifest-Version: 1.0Archiver-Version: Plexus ArchiverBuilt-By: aiqinhaiCreated-By: Apache Maven原创 2021-01-08 22:42:17 · 529 阅读 · 0 评论 -
Java异常处理的正确打开方式
前言我们在日常开发中,对于异常的处理也是很有讲究的,并不是逮到异常,一段try、catch、finally。实际异常也有自己的处理最佳原则,这里列举下异常处理的最佳实践。线上代码 No printStackTrace()写完代码后请一定要检查下,代码中千万不要有printStackTrace()。因为printStackTrace()只会在控制台上输出错误的堆栈信息,他只适合于用来代码调试。真正需要记录异常,请使用日志记录。目前成熟的日志框架有很多,logback、log4j、slf4j-sim原创 2020-09-27 22:53:24 · 228 阅读 · 0 评论 -
Dubbo框架中SPI机制分析
前言前面我们在策略模式配置化之-SPI源码解析中学习了SPI机制,和大家一起看了下ServiceLoader类中如何通过配置实例化接口的实现类,这里再和大家一起看下Dubbo中的是如何通过SPI来拓展配置的。dubbo 的 spi 思想虽然Java 提供了对SPI机制的默认实现支持,但是并不表示所有的框架都会默认使用这种Java自带的逻辑,SPI机制更多的是一种实现思想,而具体的实现逻辑,则是可以自己定义的。例如我们说Dubbo框架中大量使用了SPI技术,但是Dubbo并没有使用JDK原生的Se原创 2020-09-04 22:22:17 · 217 阅读 · 0 评论 -
java8中的Stream,呸,真香!
前言Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。直接上demopackage com.example.study;i原创 2020-07-30 22:55:11 · 212 阅读 · 0 评论 -
Optional的正确打开方式
前言Optional类是Java 8新增的一个类,用以解决程序中常见的NullPointerException异常问题。本篇文章将详细介绍Optional类,以及如何用它消除代码中的null检查。避免使用null检查作为Java开发人员,几乎所有人都遇到过NullPointerException异常,大多数人遇到NullPointerException异常时都会在异常出现的地方加上if代码块来判断值不为空,比如下面的代码:public void bindUserToRole(User us转载 2020-07-30 13:31:21 · 515 阅读 · 1 评论 -
BigDecimal的正确打开方式
前言项目中明确规定,凡是涉及到金额的属性定义都必须使用BigDecimal类型,这里来和大家一起学习下BigDecimal的正确打开方式。先来个错误的示范话不多说,直接上demo @Test public void wrongUseDecimal() { BigDecimal test1 = new BigDecimal(1.745); BigDecimal test2 = new BigDecimal(0.745); test原创 2020-06-18 22:40:56 · 363 阅读 · 0 评论