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

   }

}
5
задан sixtyfootersdude 11 July 2010 в 00:45
поделиться

5 ответов

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

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

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

20
ответ дан 18 December 2019 в 06:49
поделиться

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

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

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

1
ответ дан 18 December 2019 в 06:49
поделиться

public class 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);
    }
}
1
ответ дан 18 December 2019 в 06:49
поделиться

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

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

но ИМО, это было бы плохим дизайном 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
ответ дан 18 December 2019 в 06:49
поделиться

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

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

0
ответ дан 18 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: