2010-07-11 73 views
5

在Java中是否有一个构造函数可以接受数组或集合?我一直在摆弄这一段时间,但我认为这是不可能的。Java:一个构造函数或方法将接受数组或列表或...?

我希望能够初始化MyClass,像这样:

MyClass c = new MyClass({"rat", "Dog", "Cat"}); 

而且这样的:

LinkedList <String> l = new <String> LinkedList(); 
l.add("dog"); 
l.add("cat"); 
l.add("rat"); 
MyClass c = new MyClass(l); 

这是MyClass的样子。我可以做什么XXX以便这能起作用?我知道我可以重载构造函数,但是如果我可以最小化代码,这将是非常棒的权利?

public class MyClass{ 

    private LinkedHashSet <String> myList; 

    public MyClass(XXX <String> input){ 
     myList = new LinkedHashSet <String>(); 
     for(String s : input){ 
      myList.put(s); 
     } 

    } 

} 

回答

19

可以申报两个构造和第一第二个电话:

class MyClass { 
    public MyClass(String... x) { 
     // for arrays 
     // this constructor delegate call to the second one 
     this(Arrays.asList(x)); 
    } 
    public MyClass(List<String> x) { 
     // for lists 
     // all logic here 
    } 
} 

电话看起来像

new MyClass(new ArrayList<String>()); 
new MyClass("dog", "cat", "rat"); 
new MyClass(new String[] {"rat", "Dog", "Cat"}); 

由于只有一个行中第一个构造函数的代码,这是很简约。

+0

不错的一个。我可能会这样做,因为从'List '中获取'String []'比基于'String []'构造'List '更便宜。 – BalusC 2010-07-11 01:01:21

+2

BalusC - 你错了。 Arrays.asList(..)返回与不可变列表相同数组的视图。几乎没有成本。另一方面,转到String []需要将所有引用复制到新分配的数组中 – user44242 2010-07-11 09:26:38

+1

@usersmarvin:感谢您的支持!顺便提一下,为了通知用户关于不属于他们自己的问题/回答的评论,在昵称的前面放置一个“@”,例如, '@ BalusC'。为了找到一个匹配,至少需要名字前3个字符。 – BalusC 2010-07-14 14:54:50

1

公共类MyClass1的{

public MyClass1(final String... animals) { 
     for (final String animal : animals) { 
      System.out.println("eat " + animal); 
     } 
    } 

    public static void main(final String[] args) { 
     new MyClass1(); 
     new MyClass1("dog", "cat", "rat"); 
     new MyClass1(new String[] { "dog", "cat", "rat" }); 
    } 
} 

public class MyClass2 { 

    public MyClass2(final Iterable<String> animals) { 
     for (final String animal : animals) { 
      System.out.println("eat " + animal); 
     } 
    } 

    public static void main(final String[] args) { 
     new MyClass2(Arrays.asList("cat", "rat", "dog", "horse")); 
     final LinkedList<String> animals = new LinkedList<String>(); 
     animals.add("dog"); 
     animals.add("house"); 
     animals.addAll(Arrays.asList("cat", "rat")); 
     new MyClass2(animals); 
    } 
} 
0

如果你真的想要一个构造函数可以使用Arrays.asList,然后有构造带覆盖List和Set集合。

我个人会有两个构造函数。

1

看起来数组并不是可迭代的,所以没有办法做到这一点。有一个接受数组和其他迭代器的构造函数是不可能的。这是特别讨厌的,因为我们可以做到这一点:

Foo[] foos = ... 
for (Foo foo : foos) 

看到这个职位的详细信息:Why is an array not assignable to Iterable?

1

从理论上讲,你可以声明构造是这样的:

MyClass(Object args) { 
    if (args instanceof List) { 
     ... 
    } else if (args instanceof Set) { 
     ... 
    } else if (args.getClass().isArray()) { 
     ... 
    } else { 
     thrown new IllegalArgumentException("arg's type is wrong"); 
    } 
} 

但IMO ,那将是一个糟糕的API设计,因为它会将所有类型的检查都运行到运行时。 (有没有其他方式使用单个构造函数来做到这一点。数组类型的唯一共同的超类型和Collection接口Object

这是远远更好地使用构造函数重载如其他答案描述。

顺便提及,下面的(来自实施例)的一个Java语法错误,而不管构造所申报参数类型:

MyClass c = new MyClass({"rat", "Dog", "Cat"}); 

数组初始化的那形式只能在一个变量声明被使用;例如

String[] foo = {"rat", "Dog", "Cat"}; 

作为数组创建表达式一部分;例如

String[] foo = new String[]{"rat", "Dog", "Cat"}; 
String[][] bar = new String[][]{{"rat", "Dog", "Cat"}, /* ... */}; 
相关问题