文章来源:http://33h.co/kntu3

前几天空闲时间写了一遍关于平时自己写代码的一些习惯,这里跟大家分享一下。

定义配置文件信息

有时候我们为了统一管理会把一些变量放到 yml 配置文件中。

例如:

用 @ConfigurationProperties 代替 @Value。

使用方法:

定义对应字段的实体:

@Data
// 指定前缀
@ConfigurationProperties(prefix = "developer")
@Component
public class DeveloperProperty {private String name;private String website;private String qq;private String phoneNumber;
}

使用时注入这个 bean:

@RestController
@RequiredArgsConstructor
public class PropertyController {final DeveloperProperty developerProperty;@GetMapping("/property")public Object index() {return developerProperty.getName();}
}

用@RequiredArgsConstructor代替@Autowired

我们都知道注入一个 bean 有三种方式哦(set 注入,构造器注入,注解注入),spring 推荐我们使用构造器的方式注入 Bean。

我们来看看上段代码编译完之后的样子:

RequiredArgsConstructor:lombok 提供。

代码模块化

阿里巴巴 Java 开发手册中说到每个方法的代码不要超过 50 行(我没记错的话)。

在实际的开发中我们要善于拆分自己的接口或方法,做到一个方法只处理一种逻辑,说不定以后某个功能就用到了,拿来即用。

抛异常而不是返回

在写业务代码的时候,经常会根据不同的结果返回不同的信息,尽量减少返回,会显得代码比较乱。

反例:

正例:

减少不必要的db

尽可能的减少对数据库的查询。

举例子:删除一个服务(已下架或未上架的才能删除),之前有看别人写的代码,会先根据 id 查询该记录,然后做一些判断。

反例:

正例:

不要返回null

反例:

正例:

别处调用方法时,避免不必要的空指针。

if else

不要太多了 if else if,可以试试策略模式代替。

减少controller业务代码

业务代码尽量放到 service 层进行处理,后期维护起来也好操作而且美观。

反例:

正例:

利用好Idea

目前为止市面上的企业基本都用 idea 作为开发工具了吧。

举一个小例子:idea 会对我们的代码进行判断,提出合理的建议。

例如:

它推荐我们用 lanbda 的形式代替。

点击 replace:

阅读源码

一定要养成阅读源码的好习惯包括优秀的开源项目 GitHub上stars:>1000,会从中学好好多知识包括其对代码的设计思想以及高级 API,面试加分(好多面试官习惯问源码相关的知识)。

设计模式

23 种设计模式,要尝试代码中运用设计模式思想,写出的代码即规范又美观还高大上,哈哈。

拥抱新知识

像我们这种工作年限少的程序员,我觉得要多学习自己认知之外的知识,不能每天 crud,有机会就多用用有点难度的知识,没有机会(项目较传统),可以自己下班多些相关 demo 练习。

基础问题

map 遍历:

HashMap<String, String> map = new HashMap<>();map.put("name", "du");for (String key : map.keySet()) {String value = map.get(key);}map.forEach((k, v) -> {});// 推荐for (Map.Entry<String, String> entry : map.entrySet()) {}

optional 判空:

//获取子目录列表public List<CatalogueTreeNode> getChild(String pid) {if (V.isEmpty(pid)) {pid = BasicDic.TEMPORARY_DIRECTORY_ROOT;}CatalogueTreeNode node = treeNodeMap.get(pid);return Optional.ofNullable(node).map(CatalogueTreeNode::getChild).orElse(Collections.emptyList());}

递归

大数据量的递归时,避免在递归方法里 new 对象,可以试试把对象当作方法参数进行传递使用

注释

类、接口方法、注解、较复杂的方法,注释都要写而且要写清楚,有时候写注释不是给别人看的,而是给自己看的

判断元素是否存在

hashSet 而不是 list

list 判断一个元素是否存在的代码:

ArrayList<String> list = new ArrayList<>();// 判断a是否在list中for (int i = 0; i < list.size(); i++)if ("a".equals(elementData[i]))return i;

由此可见其复杂度为 On

而 hashSet 底层采用 hashMap 作为数据结构进行存储,元素都放到 map 的 key(即链表中)

HashSet<String> set = new HashSet<>();// 判断a是否在set中int index = hash(a);return getNode(index) != null

由此可见其复杂度为 O1。

统一管理线程池

有的会在用到多线程的地方就创建一个线程池,为了统一管理,建议建立一个线程池,统一管理,统一设置非核心线程数,拒绝策略等等。

private static volatile ThreadPoolExecutor threadPoolExecutor = null;private static final int CORE_POOL_SIZE = 0;private static final int MAX_MUM_POOL_SIZE = 1000;private static final long KEEP_ALIVE_TIME = 2;private static final TimeUnit UNIT = TimeUnit.MINUTES;private static final int CAPACITY = 1;private static final RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();private static final BasicThreadFactory factory =new BasicThreadFactory.Builder().namingPattern("aiserviceplatform-util-thread-pool-%d").build();private ThreadPoolFactory() {}public static ThreadPoolExecutor getInstance() {if (threadPoolExecutor == null) {synchronized (ThreadPoolFactory.class) {if (threadPoolExecutor == null) {threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_MUM_POOL_SIZE, KEEP_ALIVE_TIME, UNIT, new ArrayBlockingQueue<>(CAPACITY), factory, HANDLER);}}}return threadPoolExecutor;}

大量数据同步

在同步大数据量的信息时(常用多线程方式:如果表里有唯一索引或者对表进行 update 操作那么就会经常锁表),优先考虑添加临时表的方式。

String realTabelName = ....;
String tempTableName = realTableName + "_temp";createTable(tempTableName); // 创建临时表
boolean flag = sync(tempTableName); // 同步数据// 根据结果
if(flag) {dropTable(realTabelName);alterTabelName(realTableName, tempTableName); // 临时表改名 实际表
}else {// 同步失败 删除临时表dropTabel(tempTableName)
}

实测:比对一张表做处理会快很多而且不会出问题。

接口入参

定义接口的方法时,如接受一个集合类型,尽可能的用 Collection<T>,因为其他业务场景可能会穿一个 list 有的会传一个 hashSet,用起来还要改,Map 也是。

正例:

Collection<String> getNodeIds(Collection<String> ids);

锁的颗粒度

同步方法直接在方法上加 synchronized 实现加锁,同步代码块则在方法内部加锁,很明显,同步方法锁的范围比较大,而同步代码块范围要小点,一般同步的范围越大,性能就越差,一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好

我一般使用 lock:ReentrantLock,ReentrantReadWriteLock,减少锁的颗粒度,提高系统的并发能力。

缓存名称

简短,精练,以文件夹形式保存,xxx:xxx:xxx,以:隔开。

方便查看缓存信息。

@Cacheable

使用 Cacheable 做缓存时,也要加上缓存失效时间。

之前提出疑问怎么有的缓存没有失效时间,看代码使用 Cacheable 缓存的,不会添加就没加(???)。

@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {return new RedisCacheManager(RedisCacheWriter.lockingRedisCacheWriter(factory),this.getRedisCacheConfigurationWithTtl(1),this.getRedisCacheConfigurationMap());}private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer hour) {Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofHours(hour));}public static final String REGION_LIST_BY_CODE_CACHE_KEY = "region:list";public static final String REGION_NAME_BY_CODE_CACHE_KEY = "region:name";/*** 已知缓存名称的映射以及用于这些缓存的配置*/private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();// 自定义缓存名称对应的配置redisCacheConfigurationMap.put(REGION_LIST_BY_CODE_CACHE_KEY, this.getRedisCacheConfigurationWithTtl(24));redisCacheConfigurationMap.put(REGION_NAME_BY_CODE_CACHE_KEY, this.getRedisCacheConfigurationWithTtl(120));redisCacheConfigurationMap.put(RedisKey.MARK_SERVICE_RENEW, this.getRedisCacheConfigurationWithTtl(-1));redisCacheConfigurationMap.put(RedisKey.MARK_ORGAN_RENEW, this.getRedisCacheConfigurationWithTtl(-1));redisCacheConfigurationMap.put(RedisKey.MARK_SERVICE_STREAM, this.getRedisCacheConfigurationWithTtl(-1));redisCacheConfigurationMap.put(RedisKey.MARK_ORGAN_STREAM, this.getRedisCacheConfigurationWithTtl(-1));return redisCacheConfigurationMap;}

异步任务

为了提高接口的响应速度,我们会把比较耗时的操作异步处理。例如异步任务,消息队列等。

同事说,我写Java代码像写诗相关推荐

  1. Jupyter 配置 Java环境,写Java代码,测试成功

    本次简单诉说下怎么通过jupyter安装iJava,写Java代码. 安装Java的不说了 我使用的是Java15 然后去:https://github.com/SpencerPark/IJava/r ...

  2. java el表达式 导航规则_诺禾:在jsp里面如何不写java代码展示数据(EL表达式的使用)...

    EL表达式可以简化jsp中写的java代码 在jsp里面如何不写java代码展示数据(EL表达式的使用) 在jsp里面如何不写java代码展示数据(EL表达式的使用) 在jsp里面如何不写java代码 ...

  3. 写java代码时的注意事项_从方法返回Java 8的可选项时的注意事项

    写java代码时的注意事项 Java 8引入的Optional类一直是该语言版本引入的最具争议的功能之一. 尽管我喜欢这个新的Java类的东西比不喜欢的东西多,但在Java方法中将其用作return类 ...

  4. vscode写java没有提示_VS Code报错Language Support for Java(TM)插件显示需要JDK11 写java代码没有提示...

    鉴于IDEA的打开速度(电脑的垃圾),平常刷LeetCode都是在VSCode上,结果这几天老是打开给我报错 Java 11 or more recent is required to run. Pl ...

  5. 如何在jsp里面写java代码

    jsp和html相比,最显著的优势就在于,jsp里面可以写java代码,但是html中不能. 那么如何在jsp中写java代码呢! jsp中写java代码有如下三种方式: <%! %>,这 ...

  6. Eclips写Java代码和CSS、Javascript、Html代码设置代码自动提示功能

    按照我的方法设置后用Eclipse编写Java代码和前端代码(Html.CSS.JS)都可以自动提示代码.赶紧去试试吧. 1.打开Eclipse软件,点击Windows→Preferences→Jav ...

  7. jsp里写java代码报错,jsp里写java代码报错

    jsp里写java代码报错 [2021-02-11 06:42:03]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace("/ ...

  8. vim java 编程_你也用Vim写Java代码?

    献给所有曾试图写Java而痛苦挣扎的Vimers, 请不要害怕, 我也是你们的一员 序 文章源起于segmentfault论坛中的一个问题, 由于回答的有点尽性, 便转为文章. 题主应该是个Vim初学 ...

  9. 如何写出同事看不懂的Java代码?

    壹.瞒天过海 我打赌你肯定想不到,有人居然会在注释里下了毒.看看下面的代码,简单到main方法中只有一行注释. public static void main(String[] args) {// \ ...

最新文章

  1. debounce实现 js_javascript防抖函数debounce详解
  2. SQL How to get the current day month and year
  3. 经典shell面试题整理
  4. jQuery的push
  5. Android隐藏标题栏,全屏显示
  6. lengthOfLongestSubstring
  7. 让代码看起来更舒服(1):选择适合的配色方案 (转)
  8. Python装饰器几个有用又好玩的例子
  9. 【李宏毅2020 ML/DL】补充:Support Vector Machine (SVM)
  10. MySQL - 常见SQL笔试题整理(长期更新)
  11. CAPL可以读写的几种文件
  12. 解析数论引论 第2章 数论函数和狄利克雷乘积
  13. requests+正则表达式爬取豆瓣读书top250
  14. Radasm 配置goasm
  15. 布局改变时的过场动画
  16. 计算机电缆一般用在哪里,计算机电缆的型号有哪些,它们的用途是什么
  17. Docker硬盘空间使用分析与清理
  18. Java8新特性-Optional类
  19. 在MAC下解决MAC unable to execute sex :GC overhead limit exceeded GC overhead的问题
  20. OpenGL 与显卡

热门文章

  1. 荒岛余生最后一个包裹_豆瓣评分8.5,一个人撑起整部电影,最后的彩蛋让人无语...
  2. 何为Java 中的多态?
  3. php 去掉img,php怎样去掉img标签
  4. 怎么把文字变成图形_PPT 中实现文字矢量化
  5. java864位官网_jdk8 64位下载-jdk8 64 bit windows官方版 - 极光下载站
  6. jfinal js 拦截_jfinal全局数据拦截器
  7. 求n!(n的阶乘)和1!+2!+....n! (阶乘求和) ----C语言实现
  8. PTA基础编程题目集-6-8 简单阶乘计算
  9. SP10628 COT - Count on a tree (树剖+可持久化线段树)
  10. GCD or LCM ---- 处理gcd和lcm同时出现的情况 1499D - The Number of Pairs