将可变参数转发给 Java 中的其他函数,就像在 C++ 中一样
Forwarding variadic parameters to other function in Java like in C++
是否可以像C++那样在Java中完成参数转发:
template <typename ...Params>
void f(Params&&... params)
{
y(std::forward<Params>(params)...);
}
例如在我想要一个工厂函数的情况下:
public static MyClass create( < parameter pack > )
{
return new MyClass(< forward >);
}
有多个构造器?
值得注意的是,参数包可以包含不同类型的参数。
重新编辑:
It is worth noting that the parameter pack can contain parameters of different types.
这完全改变了问题。反思是实现这一目标的唯一途径。下面是反射示例的示例,但是从传入参数值 (live example) 的实际 类 中获取参数类型:
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");
}
}
显然这是一个非常基础、不完整的示例,但希望它能让您走上正确的道路。更多:
原回答:
Java 中的可变参数是数组的语法糖。任何可以提供可变参数列表的地方,都可以提供一个数组:
public static MyClass create(SomeType... args)
{
return new MyClass(args);
}
这是一个完整的例子 (runnable copy):
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");
}
}
having multiple constructors
如果你的意思是没有可变参数的多个构造函数,你将不得不分支或使用反射; 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);
}
}
反思(live example):
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");
}
}
是否可以像C++那样在Java中完成参数转发:
template <typename ...Params>
void f(Params&&... params)
{
y(std::forward<Params>(params)...);
}
例如在我想要一个工厂函数的情况下:
public static MyClass create( < parameter pack > )
{
return new MyClass(< forward >);
}
有多个构造器?
值得注意的是,参数包可以包含不同类型的参数。
重新编辑:
It is worth noting that the parameter pack can contain parameters of different types.
这完全改变了问题。反思是实现这一目标的唯一途径。下面是反射示例的示例,但是从传入参数值 (live example) 的实际 类 中获取参数类型:
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");
}
}
显然这是一个非常基础、不完整的示例,但希望它能让您走上正确的道路。更多:
原回答:
Java 中的可变参数是数组的语法糖。任何可以提供可变参数列表的地方,都可以提供一个数组:
public static MyClass create(SomeType... args)
{
return new MyClass(args);
}
这是一个完整的例子 (runnable copy):
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");
}
}
having multiple constructors
如果你的意思是没有可变参数的多个构造函数,你将不得不分支或使用反射; 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);
}
}
反思(live example):
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");
}
}