Java: один конструктор или метод, который будет принимать массив или набор или список или ...? - PullRequest
5 голосов
/ 11 июля 2010

Есть ли в 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. Что я могу сделать, чтобы ХХХ был таким, чтобы это работало? Я знаю, что могу перегрузить конструктор, но если я смогу минимизировать код, это будет здорово

public class MyClass{

   private LinkedHashSet <String> myList;

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

   }

}

Ответы [ 5 ]

20 голосов
/ 11 июля 2010

Вы можете объявить два конструктора и вызывать секунду сначала:

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"});

Поскольку в первом конструкторе есть только одна строка кода, это довольноминималистичный.

1 голос
/ 11 июля 2010

Теоретически, вы могли бы объявить конструктор примерно так:

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"}, /* ... */};
1 голос
/ 11 июля 2010

Похоже, что массивы не повторяемы, поэтому сделать это невозможно.Невозможно иметь один конструктор, который принимает массивы И другие итерируемые.Это особенно раздражает, так как мы можем сделать это:

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

Подробнее об этом см. В этом посте: Почему массив нельзя назначить для Iterable?

1 голос
/ 11 июля 2010

открытый класс 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 голосов
/ 11 июля 2010

Если вы действительно хотите один конструктор, вы можете использовать Arrays.asList, а затем заставить конструктор взять коллекцию, которая охватывает List и Set.

У меня лично было бы два конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...