如何定义一个可以在java中获取任意参数的方法?

时间:2010-03-21 08:55:32

标签: java

如何定义一个可以在java中获取任意参数的方法?有演示吗?

6 个答案:

答案 0 :(得分:10)

Java 5中引入了

varargs

例如:

public String join(String... parts);

这实际上是:

的快捷方式
public String join(String[] parts);

parts参数用作方法中的数组,但可以在不构造数组的情况下调用该方法(如obj.join(new String[] {part1, part2, part3})

但是要非常小心,因为可能会出现歧义。例如:

public void write(String author, String... words);
public void write(String... words);

如果obj.write("Mike", "jumps"),将调用哪种方法?编译器足够聪明,可以检测到歧义,但是我遇到过一些编译器没有发现这些问题的情况(不能完全回忆起来)

当对象属于同一类型或至少具有相同的功能目标时,使用varargs是实用的。如果你想要不同的论点。例如:

public String publishBook(String title, [String author], 
      [String isbn], [boolean hardcover]); // [..] would mean optional

然后你需要overload your method

答案 1 :(得分:3)

答案 2 :(得分:2)

在一般情况下不起作用。即使您将方法定义为:

    @SafeVarargs
    public void callMe(Object... args) { ... }

当您致电callMe(1, "hallo", 3.14159, new Object())时,这将有效。但是,如果要在接口上使用类似的方法,则不能使用@SafeVarargs,因为它只能添加到最终方法中(以免它们被不安全的实现覆盖)。

在这种情况下,您可以做的最好的事情是在界面中定义:

    @SuppressWarnings("unchecked")
    public <T> void callMe(T... args);

当使用相同运行时类型的对象调用callMe时,这至少会省略警告,例如`callMe(“a”,“b”,“c”)。但是,当您使用不同类型调用时会出现警告,如上例所示:

    ArbitraryCallable x = new ArbitraryCallableImplementation();
    x.callMe("a", "b"); // no warning
    x.callMe(1, "x", 3.14159); // warning

不要忘记,因为Object...只不过是Object[]的语法糖,你不能简单地调用`callMe(new Object [] {“a”}),因为这会造成一种模糊的情况:你想用一个Object(恰好是一个数组)或者使用数组的元素来调用callMe吗?

答案 3 :(得分:0)

这是关于变量参数的简单tutorial。示例代码:

public void foo (ParamType ... name) { 

}

答案 4 :(得分:0)

对于传递可变数量的参数,您可以使用varargs语法(指定一个类型后跟省略号,并且所谓的参数是指定类型的数组,Java将添加一些语法糖,以便你可以传入任何类型的列表,它会自动放入数组中。

对于传递任意类型,可以使用Java泛型来允许任意类型,或者可以使用类型Object。通常使用泛型更好,因为你会得到更多的类型检查,但两者都可以。

以下是varargs的一个示例:

public static void printAll(String... args){
   for (String str : args ){
       System.out.println(str);
   }
}
// Now can write printAll("Hello", "world", "etc", "etc");

以下是泛型的示例:

public static <T> void print(T obj){
    System.out.println(obj.toString());
}

答案 5 :(得分:0)

我担心即使你考虑varargs(因为它们只是一种类型),java还不能开箱即用(与其他一些语言相比)。 但是,OO模式是您的朋友,您可以使用Builder模式来完成您的需求。一个简短的例子(从Effective Java 2nd Edition中窃取改编和缩短版)

 public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;

    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default values
        private int calories = 0;
        private int fat = 0;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }

        public Builder calories(int val) {
            calories = val;
            return this;
        }

        public Builder fat(int val) {
            fat = val;
            return this;
        }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }

    }

    private NutritionFacts(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
    }

}

有了这个,你可以做类似

的事情
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8). 
calories(100).fat(35).build(); 

现在真正酷的是,您可以添加实际采用的方法 varargs也是如此,这使得这种特殊模式非常强大。这种模式也有 您的对象不可变,并使您免于编写telescoping构造函数。它不会做的是你的菜肴,但我生活在希望中;)