1. 文档
- 写接口文档,把对接人当 SB 看待,一定要写的很详细,防止后续扯皮、甩锅。
- 文档后续变更,要同步 添加/更新 文档中的 变更记录,方便日后溯源。同时也方便自己迅速回忆。
2. 沟通
2.1. 客户沟通
在与客户沟通预期时几个原则:
- 一定要给客户选择权,永远不要说不,要有条件地说是。
- 降低期望的同时给予其他的补偿。
- 提高期望的同时附加更多的条件。
- 对于比较大的期望要分步骤达到客户的期望。
- 不要帮客户做决定,而是给客户提供尽可能多的选项,然后引导客户做决定。
3. IntelliJ IDEA
3.1. Java: 找不到符号
关键词:IntelliJ IDEA、lombok、maven
现象:build编译项目时,总是出现java:找不到符号
这个错误提示,导致编译中断。
解决方案:settings -> Build,Exection,Deployment -> Compiler -> Shared build process VM options 输入框。
添加如下配置:-Djps.track.ap.dependencies=false
4. WebStorm
4.1. debug模式
项目正常启动后,按住 command + shift
,然后点击local#url,自动开启debug模式。
注意:只对localhost地址有效,对Network地址无效。
4.2. Live Template
4.2.1. function
1 | function $NAME$(): $TYPE$ { |
4.2.2. 箭头函数
1 | () => { |
5. Java
5.1. API
5.2. @GetMapping 指定多个URL路径
在网上看资料时,看到 @GetMapping
注解的另一种用法,即:指定多个URL路径,这个之前并没有注意到过。
1 |
|
5.3. Spring 项目 PR
5.3.1. 提高Map遍历性能
- spring-framework pr:SPR-17074 Replace iteration over Map::keySet with Map::entrySet #1891
1 | // --before update |
5.3.2. StringJoiner
- spring-framework pr:Use StringJoiner where possible to simplify String joining #22430
- spring-framework pr:Use StringJoiner where possible to simplify String joining #22539
Java 8 中的 StringJoiner
,可以设置连接符,还可以设置前置符和后置符。
5.3.3. ArrayList 初始化
- spring-framework pr:Some very simple improvements regarding usage of ArrayList #22418
1 | // --before update |
1 | // --before update |
new ArrayList<>(Arrays.asList(array1))
与 Collections.emptyList()
都是一些值得关注的代码小技巧。
在第二个修改片段中,提前进行空值判断,提前中断,可以减少下面代码的括号嵌套层数。
5.3.4. 数组填充
- spring-framework pr:Use Arrays::fill instead of hand-written loop #22595
1 | // --before update |
5.3.5. Comparator
- spring-framework pr:Simplify comparison of primitives #23098
1 | // --before update |
Contributor 使用 Integer.compare(int, int)
来简化比较代码。以后比较整数可以使用 Integer.compare(int, int)
。
5.3.6. 数组克隆
- spring-framework pr:Use array.clone() instead of manual array creation #23986
1 | // --before update |
5.4. Java注释
备忘源码中注释样式的各种写法,提高注释水平。
5.4.1. 列表
关键词:<ul></ul>
、<li></li>
5.4.2. 注释中包含代码
关键词:<pre></pre>
、{@code}
5.4.3. 注释继承
接口的实现类,使用 {@inheritDoc}
注解,在阅读模式下,显示接口方法中的注释。
5.4.4. 直接引用变量值
关键词:{@value}
5.4.5. package-info.java
pacakge-info.java 是一个Java文件,可以添加到任何的Java源码包中。pacakge-info.java 的目标是提供一个包级的文档说明或者是包级的注释。
如 spring-boot 源码中的示例:
1 | /* |
在 IDEA 中 package-info.java 文件不能随便被创建,会出现 This is not a valid Java qualified name
错误,可以通过创建一个普通的文件来变相创建 pacakge-info.java
文件。
5.5. 工具方法
5.5.1. Stream
List 转换 Array
1
2
3
4
5
6
7
8
9
10
11// String
List<String> list = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5"));
String[] array = list.toArray(new String[0]);
System.out.println(Arrays.toString(array));
// output: [1, 2, 3, 4, 5]
// Integer
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
System.out.println(Arrays.toString(arr));
// output: [1, 2, 3, 4, 5]Array 转 List
1
2
3
4
5
6
7
8
9
10
11// String
String[] arr2 = {"1", "2", "3", "4", "5"};
List<String> collect = Arrays.stream(arr2).collect(Collectors.toList());
System.out.println(collect);
// output: [1, 2, 3, 4, 5]
// Integer
int[] arr2 = {1, 2, 3, 4, 5};
List<Integer> collect = IntStream.of(arr2).boxed().collect(Collectors.toList());
System.out.println(collect);
// output: [1, 2, 3, 4, 5]
5.5.2. JSON
字符串数组转换数组
1
2
3
4
5
6import com.alibaba.fastjson.JSON;
String data = "[\"123\",\"456\",\"789\"]";
String[] toArray = JSON.parseArray(data, String.class).toArray(new String[0]);
System.out.println("toArray:" + Arrays.toString(toArray));
// toArray:[123, 456, 789]
5.5.3. Guava
Guava 版本升级兼容性不太好,升级需要谨慎!
Collections2.filter: 自定义过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28List<String> list = Arrays.asList(null, "123", "456", "789", "", "112233");
System.out.println(list); // [null, 123, 456, 789, , 112233]
// 过滤 null
Collection<String> collection = Collections2.filter(list, Predicates.notNull());
System.out.println(collection); // [123, 456, 789, , 112233]
// 过滤空字符串
collection = Collections2.filter(list, Predicates.not(StringUtils::isBlank));
System.out.println(collection); // [123, 456, 789, 112233]
// 筛选出元素中包含7的
List<String> list = Arrays.asList("123", "456", "789", "", "112233");
Collection<String> collection = Collections2.filter(list, Predicates.containsPattern("7"));
System.out.println(collection); // [789]
// --------------------
// 多个过滤条件
List<String> list = Arrays.asList(null, "123", "456", "789", "", "112233", "");
Collection<String> collection = Collections2.filter(list,
Predicates.and(Predicates.not(StringUtils::isBlank), Predicates.containsPattern("7")));
System.out.println(collection); // [123, 112233]
List<String> list = Arrays.asList(null, "123", "456", "789", "", "112233", "");
Collection<String> collection = Collections2.filter(list,
Predicates.and(Predicates.not(StringUtils::isBlank), Predicates.containsPattern("1|6")));
System.out.println(collection); // [123, 456, 112233]Ordering.natural:从小到大排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// int
List<Integer> data = new ArrayList<>(Arrays.asList(7, 1, 5, 2, 8, 22));
data.sort(Ordering.natural());
System.out.println(data);
// [1, 2, 5, 7, 8, 22]
// double
List<Double> data = new ArrayList<>(Arrays.asList(1d, 5d, 2d, 7d, 9.9d, 8d, 22d));
data.sort(Ordering.natural());
System.out.println(data);
// [1.0, 2.0, 5.0, 7.0, 8.0, 9.9, 22.0]
// date
// 2020-10-21 22:09:44
long time3 = 1603289384000L;
// 2020-10-01 22:09:44
long time1 = 1601561384000L;
// 2020-10-02 22:09:44
long time2 = 1601647784000L;
List<Date> dates = new ArrayList<>(Arrays.asList(new Date(time2), new Date(time3), new Date(time1)));
dates.sort(Ordering.natural());
dates.forEach(date -> System.out.println(DateUtil.Format.formatTime(date)));
// 2020-10-01 22:09:44、2020-10-02 22:09:44、2020-10-21 22:09:44reverse:从大到小
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// int
List<Integer> data = new ArrayList<>(Arrays.asList(7,1, 5, 2 , 8, 22));
data.sort(Ordering.natural().reverse());
System.out.println(data);
// [22, 8, 7, 5, 2, 1]
// double
List<Double> data = new ArrayList<>(Arrays.asList(1d, 5d, 2d, 7d, 9.9d, 8d, 22d));
data.sort(Ordering.natural().reverse());
System.out.println(data);
// [22.0, 9.9, 8.0, 7.0, 5.0, 2.0, 1.0]
// date
// 2020-10-21 22:09:44
long time3 = 1603289384000L;
// 2020-10-01 22:09:44
long time1 = 1601561384000L;
// 2020-10-02 22:09:44
long time2 = 1601647784000L;
List<Date> dates = new ArrayList<>(Arrays.asList(new Date(time2), new Date(time3), new Date(time1)));
dates.sort(Ordering.natural().reverse());
dates.forEach(date -> System.out.println(DateUtil.Format.formatTime(date)));
// 2020-10-21 22:09:44、2020-10-02 22:09:44、2020-10-01 22:09:44
5.5.4. Spring Framework
5.5.4.1. StringUtils
org.springframework.util.StringUtils
方法 | 含义 |
---|---|
boolean endsWithIgnoreCase(String str, String suffix) | 字符串是否以指定内容结束,忽略大小写。 |
boolean startsWithIgnoreCase(String str, String prefix) | 字符串是否以指定内容开头,忽略大小写。 |
boolean containsWhitespace(CharSequence str) | 字符串中是否包含空白、空格字符 |
boolean substringMatch(CharSequence str, int index, CharSequence substring) | 字符串指定索引处是否包含一个子串 |
int countOccurrencesOf(String str, String sub) | 字符串中指定子串出现的次数 |
String delete(String inString, String pattern) | 从字符串中删除所有出现的子串 |
String[] trimArrayElements(String[] array) | 对数组中的每个元素执行trim()方法 |
String uriDecode(String source, Charset charset) | 对URL字符串解码 |
String getFilenameExtension(String path) | 解析出文件后缀名 |
String stripFilenameExtension(String path) | 删除文件路径名中的后缀部分 |
String trimTrailingCharacter(String str, char trailingCharacter) | 去除尾部的特定字符 |
String trimLeadingCharacter(String str, char leadingCharacter) | 去除头部的特定字符 |
String trimAllWhitespace(String str) | 删除开头、结尾和中间的空白符 |
5.5.4.2. ClassUtils
org.springframework.util.ClassUtils
方法 | 含义 |
---|---|
String getPackageName(String fqClassName) | 确定给定类的包名称。 |
String getPackageName(Class<?> clazz) | 确定给定完全限定类名的包名称。 |
5.5.5. sun(JDK)
ORBUtility.compareVersion: 比较两个字符串版本号。
如果v1大于、等于或小于v2,则返回1、0或-1。
1
2
3
4
5
6
7
8
9
10
11
12
13String version = "5.1.6.RELEASE";
int i = ORBUtility.compareVersion("5.4.6.RELEASE", version);
System.out.println(i); // 1
i = ORBUtility.compareVersion("5.1.6.RELEASE", version);
System.out.println(i); // 0
i = ORBUtility.compareVersion("4.1.6.RELEASE", version);
System.out.println(i); // -1
i = ORBUtility.compareVersion("4.1.6.release", version);
System.out.println(i); // -1
5.5.5.1. Collections
java.util.Collections
方法 | 含义 |
---|---|
<T> Set<T> unmodifiableSet(Set<? extends T> s) | 获取一个不可修改的 Set 集合。 如果试图修改这个集合时,就会抛出 UnsupportedOperationException 异常。 |
5.6. JVM
5.6.1. import 避免使用通配符
当代码中出现 import xxx.*
时,Java虚拟机会加载 xxx
包下的所有类到 MetaSpace(Java 8+) 或者 PermGen(Java 8之前) 区域中,哪怕这些类在当前代码中并没有被使用,从而浪费内存空间。
5.7. SpringBoot
5.7.1. 配置
项目开发时会把一些变量放到yml配置文件中,例如下面这样:
1 | # application.yml |
使用 @ConfigurationProperties
代替 @Value
。
1 |
|
需要使用时,注入 DeveloperProperty:
1 |
|
Spring 注入 Bean 有三种方式:set注入、构造器注入、注解注入。Spring 推荐使用构造器的方式注入 Bean。
@RequiredArgsConstructor
注解由 lombok 提供,用于代替 @Autowired
,编译后如下:
1 |
|