faults on coding (to be continued)

零零散散的在编码过程中犯过一些错误,所以打算专门写一篇总结,持续记录这些错误,以便知错能改。

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

发布者

傅, 健

程序员,Java、C++、开源爱好者. About me

发表评论