专栏原创出处:github-源笔记文件 (opens new window)github-源码 (opens new window),欢迎 Star,转载请附上原文出处链接和本声明。

Java 核心知识专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Java 核心知识 (opens new window)

# 一、可变长参数的定义

使用 类型... 名称 定义为可变长参数(Varargs),一个方法只能有一个可变长参数并且必须是方法最后一个参数。

void method(String... args) // 可变长参数

void method(String first, String... args)   // args 为可变长参数
    
void method(String... args, String s) // 编译不通过

从本质上理解,我们可以把可变长参数当成一个语法糖,最终它是由数组表示的。 可变长参数可以看做是一个不需要显示的创建数组就能使用的「数组」,创建数组由虚拟机编译时自动完成。

# 二、可变长参数特性

  1. 可变长参数底层使用数组实现

[Ljava/lang/String; 表示是一个字符串数组([ 表示数组,L 表示引用类型)。

public static void method(java.lang.String, java.lang.String...);
编译后描述符 : (Ljava/lang/String;[Ljava/lang/String;)V
  1. 不指定可变长参数时,默认会创建一个长度为 0 的空数组传入
public class A {
    public static void method(String... args) {}

    public static void main(String[] args) {
        A.method();
    }
    Code:
      stack=1, locals=1, args_size=1
         0: iconst_0         // 将 0 压入栈顶 (数组长度为 0)
         1: anewarray     #2 // 创建一个引用类型为 String 的数组并将其引用值压入栈顶
         4: invokestatic  #3 // 调用 method(String... args) 方法,将数组传入
         7: return
}
  1. 能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法
public class A {

    public static void method(String first, String second) {
        System.out.println("first,second");
    }
    public static void method(String first, String... args) {
        System.out.println("first,args");
    }

    public static void main(String[] args) {
        A.method("a", "b"); // first,second
    }
}
  1. 重写可变长参数的方法时,最好子方法也用可变长参数表示
    static class Base {
        void print(String... args) {
            System.out.println("Base");
        }
    }

    static class Sub extends Base { // 子类,覆写父类方法
        @Override void print(String[] args) {
            System.out.println("Sub");
        }
    }
    
    // 静态类型为 Base,直接查找 Base 的 print 方法
    Base base = new Sub();
    base.print("hello");

    // 静态类型为 Sub,直接查找 Sub 的 print 方法,因为是数组格式,编译不通过
    Sub sub = new Sub();
    sub.print("hello"); // 编译不通过
        

对于重载重写及编译期间的静态分派参考 从方法调用的角度分析重载、重写的本质 (opens new window)

# 三、应用场景

  • 参数具体个数未知,使用可变长参数

  • 使用集合代替不确定长度的数组时,考虑性能情况,使用可变长参数代替集合

  • 提供更快捷方便的 API,比如 LOG public void info(String format, Object... arguments);

# 总结

  • 可变长参数底层是数组,一个方法只能有一个可变长参数并且是方法参数的最后一个位置

  • 可变长参数如果没有传入任何值,默认会传入一个空数组

  • 能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法

  • 重写可变长参数的方法时,最好子方法也用可变长参数表示(用数组表示可能会有编译问题)

# 专栏更多文章笔记

最后修改时间: 2/17/2020, 4:43:04 AM