零零散散的在编码过程中犯过一些错误,所以打算专门写一篇总结,持续记录这些错误,以便知错能改。
1 work一直良好的系统中,明显的错误不要改,例如:
private int age; public void setAge(int age){ age = age; }
有些功能实际上错上加错的结果,当纠正一个错误的时候,结果就变成了错误。
2 理所当然的思维惯性。
下面的结果是什么?是不是true?
Properties properties = new Properties(); properties.put("key",true); String valueStr = properties.getProperty("key"); System.out.println(valueStr); System.out.println(Boolean.TRUE.toString().equalsIgnoreCase(valueStr));
源码分析:
实际上设置的是boolean型的值,然后getProperty返回的是null:
public String getProperty(String key) { Object oval = super.get(key); String sval = (oval instanceof String) ? (String)oval : null; return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval; }
3 针对接口编程和误用方法:
下面的写法试图cache一个值,当不存在对应的value时,自动加载一个值,那下面的值返回什么?
cache loader
CacheLoader<String, String> loader = new CacheLoader<String, String>() { @Override public String load(String key) throws Exception { return key + "'s value"; } };
使用:
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(10_000).expireAfterWrite(15, TimeUnit.MINUTES).build(loader); String value = cache.getIfPresent("key1");
实际正确的写法
LoadingCache<String,String> cache = CacheBuilder.newBuilder().maximumSize(10_000).expireAfterWrite(15, TimeUnit.MINUTES).build(loader); String value = cache.get("key1");
问题出在,一定要仔细阅读API的文档,不要想当然,同时针对接口编程,不定是针对顶层接口编程,如果上来就赋予给顶层接口,则后面的方法选择范围就比较小,可能就不假思考。
4 不假思索的认为某种类型是枚举
在判断响应是否是JSON body时,误以为MediaType.APPLICATION_JSON_TYPE肯定被定义成枚举,所以直接用==判断。
MediaType.APPLICATION_JSON_TYPE == response.getMediaType();
修改:不定是每个感觉应该定义成枚举类型的就会定义成枚举类型,另外没有搞清楚状况前,用equals肯定比==更安全,
MediaType.APPLICATION_JSON_TYPE.equals(response.getMediaType())
5 Arrays.aslist返回的list?
下面的代码能编译,但是有没有问题?
List<String> asList = Arrays.asList("123", "456"); asList.removeIf(string -> string.equalsIgnoreCase("123"));
结果:
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.remove(AbstractList.java:161) at java.util.AbstractList$Itr.remove(AbstractList.java:374) at java.util.Collection.removeIf(Collection.java:415) at com.github.metrics.Metric.main(Metric.java:29)
源码解析:
@SuppressWarnings("varargs") public static <T> List<T> asList(T... a) { return new ArrayList<>(a); //此处返回的list是java.util.Arrays.ArrayList<E>,而并不是普通的java.util.ArrayList<E> }
而这种list的一些实现并未实现:
public E remove(int index) { throw new UnsupportedOperationException(); }
思考:可以调用的方法不见得可以work,返回看起来名字一样的,但是不见得是一个。
6 当从list删除元素时,如果从前往后删,则注意有元素删除后,改元素后面的索引以及总的size都已经发生了变化
for (int i = 1; i < list.size(); i++) { Element element = list.get(i); if(element.getValue()>1){ list.remove(i); } }
或者:
for (int i = 1; i < list.size(); i++) { Element element = list.get(i); if(element.getValue()>1){ list.remove(element); } }
都是坑,所以从后往前删除则没有这个问题。
7 关于lombok的builder注解,成员变量即使设置了默认值,如果builder没有显示设置的话,也不起作用。
@Builder public class IvrCall extends DataTransferObject { private List<Step> executeTimeStatistics = new ArrayList<>();
当使用builder构建时,没设置executeTimeStatistics,则默认值为null,并不是new ArrayList<>()
8 package.toString vs package.getName 不同
String packageStr = ZZZ.class.getPackage().toString(); String packageName = ZZZ.class.getPackage().getName(); System.out.println(packageStr); System.out.println(packageName); package com.xxx.yyy com.xxx.yyy
8 Path大小写问题
9 https://segmentfault.com/q/1010000019170109