java方法可变参数研究

1 问题引出

(1)缘由

最近在研究如何在项目中引入Redis缓存,于是遇到可变参数这个疑惑点,之前没有好好研究过,为了避免项目后期出现问题。

(2)项目相关技术

  • SpringBoot
  • Redis
  • Kryo(数据存储使用二进制)

(3)疑惑点:

  • 概述:Redis设置List时,如果rightPushAll方法,可能发生空指针异常

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Test
public void test(){
    // 发生空指针异常
    redisTemplate.opsForList().rightPushAll("test",null);
}
  • 源码

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
	
    public ListOperations<K, V> opsForList() {
		if (listOps == null) {
			listOps = new DefaultListOperations<K, V>(this);
		}
		return listOps;
	}
    
}

class DefaultListOperations<K, V> extends AbstractOperations<K, V> implements ListOperations<K, V> {
    
	public Long rightPushAll(K key, V... values) {
		final byte[] rawKey = rawKey(key);
		final byte[][] rawValues = rawValues(values);
		return execute(new RedisCallback<Long>() {
			public Long doInRedis(RedisConnection connection) {
				return connection.rPush(rawKey, rawValues);
			}
		}, true);
	}
    
}
abstract class AbstractOperations<K, V> {
    
    byte[][] rawValues(Object... values) {
        final byte[][] rawValues = new byte[values.length][];
        int i = 0;
        for (Object value : values) {
        	rawValues[i++] = rawValue(value);
        }
        return rawValues;
    }
    
}

2 可变参数简单研究

(1)概述

  • 可变参数能够接受0个参数
  • 可变参数能够接受1个参数
  • 可变参数能够接受多个参数

(2)DEMO

  • 0个参数

public static void main(String[] args) {
    test();
}

private static void test(Object... values) {
    System.out.println(values.getClass()); // class [Ljava.lang.Object;
    System.out.println(values.length); // 0
}
  • 1个参数

// test1
public static void main(String[] args) {
    test(1); // 1
}

// test2
public static void main(String[] args) {
    test(null); // Exception in thread "main" java.lang.NullPointerException
}

// test3:这种
public static void main(String[] args) {
    Object[] objects = new Object[]{null};
    test(objects); // 1,不报异常了
}

private static void test(Object... values) {
    System.out.println(values.getClass()); // class [Ljava.lang.Object;
    System.out.println(values.length); 
}
  • 多个参数

public static void main(String[] args) {
    test(1,2,3,"Test"); // 打印输出:1 2 3 Test
}

private static void test(Object... values) {
    int length = values.length;
    if (values == null && length == 0) return;
    Object[] localValues = new Object[length];
    System.arraycopy(values, 0, localValues, 0, length);
    for (Object obj : localValues) {
        System.out.println(obj);
    }
}

3 结论

  • 使用可变参数需要检查参数是否为null
  • 可变参数内部使用数组实现
  • 多个参数时,最好在方法内部复制一份副本,防止外部修改了参数

注:以后把字节码打印出来补充

posted @ 2018-10-25 14:50  月下小魔王  阅读(1767)  评论(0编辑  收藏  举报