将可变参数转发到Java中的其他函数,就像在C++中一样

K. *_*sky -2 java variadic-functions

是否可以像在C++中一样在Java中完成参数转发:

template <typename ...Params>
void f(Params&&... params)
{
    y(std::forward<Params>(params)...);
}
Run Code Online (Sandbox Code Playgroud)

例如,在我想要一个工厂功能的情况下:

public static MyClass create( < parameter pack > )
{
    return new MyClass(< forward >);
}
Run Code Online (Sandbox Code Playgroud)

有多个构造函数?

值得注意的是,参数包可以包含不同类型的参数.

T.J*_*der 6

重新编辑:

值得注意的是,参数包可以包含不同类型的参数.

这完全改变了这个问题.反思是实现这一目标的唯一方法.这是下面的反射示例的示例,但是从传入的参数值的实际类中获取参数类型(实例):

import java.lang.reflect.Constructor;
import java.util.Arrays;

class Example
{
    public Example(String a) {
        System.out.println("(String): " + a);
        // ...
    }

    public Example(int a, String b) {
        System.out.println("(int, String): " + a + ", " + b);
        // ...
    }

    public Example(String a, String b) {
        System.out.println("(String, String): " + a + ", " + b);
        // ...
    }

    static Example create(Object... params) {
        try {
            Class[] paramTypes = new Class[params.length];
            for (int n = 0; n < params.length; ++n) {
                Class cls = params[n].getClass();
                if (cls.equals(Integer.class)) { // You may need this (for int and other primitives)
                    paramTypes[n] = Integer.TYPE;
                } else {
                    paramTypes[n] = cls;
                }
            }
            Constructor ctor = Example.class.getConstructor(paramTypes);
            return (Example)ctor.newInstance(params);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace(System.out);
            throw new IllegalArgumentException("parameters not supported");
        }
    }

    public static void main(String[] args)
    {
        Example e1 = Example.create("foo");
        Example e2 = Example.create(1, "foo");
        Example e3 = Example.create("foo", "bar");
    }
}
Run Code Online (Sandbox Code Playgroud)

显然是一个非常基本的,不完整的例子,但希望它能让你以正确的方式前进.更多:


原始答案:

Java中的变量参数是数组的语法糖.您可以在任何地方提供变量参数列表,您可以提供一个数组:

public static MyClass create(SomeType... args)
{
    return new MyClass(args);
}
Run Code Online (Sandbox Code Playgroud)

这是一个完整的例子(可运行的副本):

import java.util.Arrays;

class Example
{
    Example(String... strings) {
        System.out.println("strings = " + Arrays.toString(strings));
        // Obviously, in the normal case, a constructor actually does something
        // with the parameters...
    }

    static Example create(String... strings) {
        return new Example(strings);
    }

    public static void main(String[] args)
    {
        Example e = Example.create("a", "b", "c");
    }
}
Run Code Online (Sandbox Code Playgroud)

有多个构造函数

如果你的意思是没有可变参数的多个构造函数,你将不得不分支或使用反射; 除了可以执行此操作的反射之外,Java没有内置机制.(我理解C++的机制,这很酷.)这可能是一个合并它们并使一个可变构造函数加入的论据.

分枝:

class Example
{
    Example(int a) {
        System.out.println("one param: " + a);
        // ...
    }

    Example(int a, int b) {
        System.out.println("two params: " + a + ", " + b);
        // ...
    }

    Example(int a, int b, int c) {
        System.out.println("three params: " + a + ", " + b + ", " + c);
        // ...
    }

    static Example create(int... ints) {
        switch (ints.length) {
            case 1:
                return new Example(ints[0]);
            case 2:
                return new Example(ints[0], ints[1]);
            case 3:
                return new Example(ints[0], ints[1], ints[2]);
            default:
                throw new IllegalArgumentException("Only 1-3 ints allowed");
        }
    }

    public static void main (String[] args)
    {
        Example e = Example.create(1, 2, 3);
    }
}
Run Code Online (Sandbox Code Playgroud)

反思(实例):

import java.lang.reflect.Constructor;
import java.util.Arrays;

class Example
{
    public Example(String a) {
        System.out.println("one param: " + a);
        // ...
    }

    public Example(String a, String b) {
        System.out.println("two params: " + a + ", " + b);
        // ...
    }

    public Example(String a, String b, String c) {
        System.out.println("three params: " + a + ", " + b + ", " + c);
        // ...
    }

    static Example create(String... strings) {
        try {
            Class[] paramTypes = new Class[strings.length];
            Arrays.fill(paramTypes, String.class);
            Constructor ctor = Example.class.getConstructor(paramTypes);
            return (Example)ctor.newInstance((Object[])strings);
        } catch (Exception e) {
            throw new IllegalArgumentException(strings.length + " strings not supported");
        }
    }

    public static void main (String[] args)
    {
        Example e = Example.create("a", "b", "c");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然我认为这是关于你没有反思的最好的东西(这里不太吸引人),但值得注意的是,它并不适用于所有方面的C++版本.只要参数在最后匹配,C++就允许构造函数拥有它需要的任何参数列表.这些参数和参数也可以是不同的类型,并在整个过程中保留其特定类型,而不包含运行时信息. (3认同)