方法原型中的可变参数有多种对象类型?

问题描述 投票:0回答:6

我正在尝试编写一个可以用任意数量的整数和字符串调用的 Java 函数的原型:

myMethod(1, 2, 3, "Hello", "World"); // Valid call
myMethod(4, "foo", "bar", "foobar"); // Valid call

理想情况下,我希望整数和字符串以任何顺序给出(并且可能是混合的):

myMethod(1, "Hello", 2, "World", 3); // Valid call

我想过使用varargs,但是原型中只能有一个。我的另一个想法是使用以下原型:

public void myMethod(Object ... objs) { [...] }

...但我觉得如果使用预期类型以外的类型调用它,应该会出现编译错误。当然,可以执行运行时检查(

instanceof
),但这不是一个非常优雅的解决方案,不是吗?

你会怎么做?

java variadic-functions
6个回答
11
投票

如果你希望它类型安全,我会这样做:

public myMethod(Thing<?>... thing) { ... }

然后创建您的 Thing 类:

public interface Thing<T> {
    public T value();
}

public class IntThing implements Thing<Integer> {
    private final int value;

    public IntThing(int value) {
        this.value = value;
    }

    public Integer value() {
        return value;
    }
}

我将让您发挥想象力来弄清楚如何编写 StringThing。显然,使用一个比“Thing”更好的名字,但我无法帮助你。

然后创建两个静态方法:

public static Thing<Integer> thing(int value) {
    return new IntThing(value);
}

public static Thing<String> thing(String value) {
    return new StringThing(value);
}

然后将每个对象包装在对

thing
:

的调用中
myMethod(thing(1), thing(2), thing(3), thing("Hello"), thing("World"));

凌乱?是的。不幸的是,Java 没有能力像其他语言一样隐藏这些东西。 Scala 的隐式定义可以在这里帮助您,但这会带来很多其他问题。就我个人而言,我会进行

instanceof
检查,但这将确保您的代码在编译时是安全的。


10
投票

Java 编程语言中没有办法让它工作,以便您可以传递任意数量的字符串和整数,并且当您传递字符串或整数以外的其他内容时,编译器会给出错误。


4
投票

没有办法使用泛型来匹配两种类型,例如

// This does NOT compile
public <T extends String | Integer> void myMethod(T... objs);

1
投票

您所描述的问题的唯一可能的解决方案是已经声明的解决方案,其中该函数采用

Object
类型的 varargs 参数。这是由于 Java 中的限制,方法签名中只能有一个 vararg,并且它必须是最后一个参数。

如果不知道您想要

myMethod
做什么的细节,很难说另一种优雅的解决方案是什么。


0
投票

(解决方法)

添加到您的库:

package mylib;

public class Lang {
    public static <T> T[] varargs (T...ts) {
        return ts;
    }
}

在你的程序中:

package myprog;

import static mylib.Lang.*;

public class MyProg {

    public static void testfunc (Integer[] ints, String[] strs) {

        for (int i : ints)
            System.out.println(i);

        for (String s : strs)
            System.out.println(s);
    }

    public static void main (String[] args) {
        testfunc(
            varargs(1,2,3),
            varargs("Sophia", "Jacob")
        );
    }
}

(打破了许多编码风格规则)


0
投票

允许使用语法

public class Foo<T extends Number & List> {
  ...
}

类型变量

T
允许属于同一类型的
Number
List
的子类型(例如,实现多个接口的类型)。

© www.soinside.com 2019 - 2024. All rights reserved.