Java基础快速入门: 可变参数与不可变集合

本文纲要

  1. 可变参数
    1.1 需求引入:固定参数的方法
    1.2 JDK 1.5 之前的解决方案:数组传参
    1.3 可变参数语法与底层原理
    1.4 可变参数的注意事项
  2. 创建不可变的集合
    2.1 List.of() – 不可变的 List
    2.2 Set.of() – 不可变的 Set
    2.3 Map.of() – 不可变的 Map
    2.4 Map.ofEntries() – 提高可读性的变体
    2.5 结合集合构造器实现批量添加

可变参数

项目代码结构

myparameter/src/com/wb/variableparameter/
├── MyVariableParameter1.java 
├── MyVariableParameter2.java 
├── MyVariableParameter3.java 
└── MyVariableParameter4.java 

1 ) 需求引入:固定参数的方法

先从一个简单需求开始:定义一个方法,求两个数的和;再定义一个方法,求三个数的和。
这是我们最直观的写法 —— 重载多个不同参数数量的方法。

package com.wb.variableparameter;
 
public class MyVariableParameter1 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 30;
 
        int sum1 = getSum(a, b);
        System.out.println(sum1);  // 30 
 
        int sum2 = getSum(a, b, c);
        System.out.println(sum2);  // 60 
    }
 
    public static int getSum(int a, int b) {
        return a + b;
    }
 
    public static int getSum(int a, int b, int c) {
        return a + b + c;
    }
}

但是,如果要计算 N 个数的和,N 不确定,形参的个数就无法事先定义。

2 ) JDK 1.5 之前的解决方案:数组传参

在 JDK 1.5 之前,想实现“参数个数可变”,只能把所有数据封装到一个数组中,方法接收一个数组参数。

package com.wb.variableparameter;
 
public class MyVariableParameter2 {
    public static void main(String[] args) {
        // 在JDK5之前,会把所有的数据都先放到一个数组中 
        // 我们自己定义的方法,形参只要写一个数组就可以了。
        int[] arr = {1, 2, 3, 4, 5};
        int sum1 = getSum(arr);
        System.out.println(sum1);  // 15 
    }
 
    private static int getSum(int[] arr) {
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum = sum + arr[i];
        }
        return sum;
    }
}

这种方式可以解决问题,但是每次调用都需要手动创建数组并填充数据,代码比较繁琐。

3 ) 可变参数语法与底层原理

可变参数(Variable Arguments) 又称“变长参数”,它可以让我们在调用方法时传入任意个该类型的实参,而无需提前封装数组。

语法格式:

数据类型... 变量名 

例如:int... arr

可变参数底层其实就是一个数组,接收的所有实参都会被自动封装到一个对应类型的数组中。
它省去的是我们手动 new 数组、放数据的步骤。

package com.wb.variableparameter;
 
/*
需求:定义一个方法求N个数的和 
可变参数实现 
 */
public class MyVariableParameter3 {
    public static void main(String[] args) {
        // 验证数组直接打印的格式 
        // int[] arr = {1,2,3,4,5};
        // System.out.println(arr);   // [I@...  和可变参数内部数组格式一致 
 
        int sum1 = getSum(1, 2, 3, 4, 5);   // 直接传多个参数 
        System.out.println(sum1);          // 15 
    }
 
    public static int getSum(int... arr) {
        // 拿到 arr 就是数组,可以随意遍历 
        // System.out.println(arr);  // 验证底层是数组 
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum = sum + arr[i];
        }
        return sum;
    }
}

4 ) 可变参数的注意事项

  1. 可变参数在底层就是数组,可以用任何遍历数组的方式操作它。
  2. 如果一个方法有多个参数且包含可变参数,可变参数必须放在最后。
    否则前面的其他参数就无法接收到数据,所有实参都会被可变参数“吃掉”。

错误写法:

public static int getSum(int... arr, int number) { // 编译错误!
}

正确写法:

public static int getSum(int number, int... arr) {
    // number 接收第一个参数,arr 接收后面所有参数 
}

示例代码(修改自 MyVariableParameter3,添加额外参数):

public static int getSum(int number, int... arr) {
    int sum = number;          // 先加上第一个固定参数 
    for (int i = 0; i < arr.length; i++) {
        sum = sum + arr[i];
    }
    return sum;
}

创建不可变的集合

从 JDK 9 开始,ListSetMap 接口中都增加了名为 of() 的静态工厂方法,它可以快速创建不可变(Immutable)的集合。
不可变集合:一旦创建,不能添加、删除、修改任何元素。

所有 of 方法的参数都是可变参数,使用起来非常方便。
项目代码结构

这一部分对应的是项目中的 MyVariableParameter4.java,包含 4 个演示方法。

myparameter/src/com/wb/variableparameter/
└── MyVariableParameter4.java 

1 ) List.of() – 不可变的 List

// 创建不可变 List 
List<String> list = List.of("a", "b", "c", "d");
System.out.println(list);  // [a, b, c, d]

验证不可变性

// 以下任何修改操作都会抛出 UnsupportedOperationException 
list.add("Q");
list.remove("a");
list.set(0, "A");

运行时会直接报错,例如:

Exception in thread "main" java.lang.UnsupportedOperationException 

2 ) Set.of() – 不可变的 Set

// 创建不可变 Set 
Set<String> set = Set.of("a", "b", "c", "d");
System.out.println(set);  // [a, b, c, d]

特别注意:
Set 本身不允许重复元素,所以在使用 Set.of() 时若传入重复元素会直接抛出 IllegalArgumentException

// 错误示例:包含重复元素 "a"
Set<String> set = Set.of("a", "b", "c", "d", "a"); // 抛出异常 

3 ) Map.of() – 不可变的 Map

Map.of() 的参数需要按照 key1, value1, key2, value2, … 的形式依次传入。

Map<String, String> map = Map.of(
    "zhangsan", "江苏",
    "lisi",     "北京",
    "wangwu",   "天津"
);
System.out.println(map); // {zhangsan=江苏, lisi=北京, wangwu=天津}

底层会将 “zhangsan” 和 “江苏” 视为一个键值对,依次类推。

4 ) Map.ofEntries() – 提高可读性的变体

当键值对较多时,Map.of() 的参数平铺写法可读性较差。
Map.ofEntries() 可以将每个键值对先封装成 Map.Entry 对象,再传入变长参数中,代码结构更清晰。

Map<String, String> map = Map.ofEntries(
    Map.entry("zhangsan", "江苏"),
    Map.entry("lisi", "北京")
);
System.out.println(map); // {zhangsan=江苏, lisi=北京}

Map.entry(k, v) 是一个静态方法,返回一个不可变 Entry 对象

5 ) 结合集合构造器实现批量添加

不可变集合虽然不能修改,但它可以配合集合的有参构造器,实现批量添加数据到可变集合中。
比如我们以前往 ArrayList 中添加多个元素,需要写很多行的 add()

// 传统方式:逐个添加,代码冗长 
ArrayList<String> list2 = new ArrayList<>();
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add("ddd");

借助 List.of()ArrayList 的构造器,可以一行搞定:

// 批量添加:先创建不可变集合,再传给 ArrayList 构造器 
ArrayList<String> list3 = new ArrayList<>(List.of("a", "b", "c", "d"));
System.out.println(list3); // [a, b, c, d]

工作原理:

  1. List.of("a", "b", "c", "d") 创建一个不可变的 List(底层使用可变参数,想传多少元素都可以)。
  2. new ArrayList<>(不可变List) 通过构造器将这个集合中的所有元素一次性复制到新的 ArrayList
  3. 最终得到一个可以自由增删改查的普通 ArrayList,同时代码量大幅减少。

同样的技巧也适用于 HashSetHashMap 等其他集合。

Set<String> set = new HashSet<>(Set.of("x", "y", "z"));
Map<String, Integer> map = new HashMap<>(Map.of("one", 1, "two", 2));

总结

知识点关键要点
可变参数格式 数据类型…,底层是数组,必须放在参数列表末尾
不可变集合List.of / Set.of / Map.of / Map.ofEntries
不可变集合的特点创建后不能增、删、改,任何修改操作都会抛出异常
Set.of 限制参数中不能有重复元素,否则抛异常
批量添加技巧使用 new ArrayList<>(List.of(...)) 等,简化集合初始化

通过可变参数和不可变集合的配合使用,可以让 Java 代码更加简洁易读,尤其在集合初始化场景下效果显著。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值