Проверить экземпляр T и вызвать соответствующий конструктор условно - PullRequest
0 голосов
/ 20 апреля 2019

Я использую этот код ниже, но позвольте мне сначала объяснить, чего я хочу достичь.У меня есть 3 класса, Publisher, Consumer и Broker.Я хочу создать статический метод, который принимает аргументы от CLI и возвращает список каждого класса в зависимости от того, что я указываю.Пример ниже является полностью функциональным, но работает только для класса Publisher.У меня вопрос, как я могу изменить приведенный ниже код, чтобы принимать несколько классов и возвращать List< T > вместо List< Publisher >.Я пытался использовать дженерики, но таким образом я не могу вызвать конструктор для создания нового объекта.Не беспокойтесь о разбиениях String, это не имеет никакого отношения к проблеме, основное внимание уделяется циклу while, где я создаю экземпляр Object.Моя цель - использовать этот класс таким образом

ArgParser.< Publisher >fetchEntitiesFromCommandLine(args)

ArgParser.< Broker > fetchEntitiesFromCommandLine(args)

ArgParser.< Consumer > fetchEntitiesFromCommandLine(args)

Заранее спасибо!

public class ArgParser {
    public static List<Publisher> fetchPublishersFromCommandLine(String[] args) throws IllegalArgumentException {
        List<Publisher> publishers = new ArrayList<>();
        int position = -1;
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-p")) {
                position = i;
            }
        }
        if (position == -1)
            throw new IllegalArgumentException();
        try {
            while (args[++position] != null) {
                String[] data = args[position].split(":");
                Publisher publisher = new Publisher(data[0], Integer.parseInt(data[1]));
                publishers.add(publisher);
            }
            // This line never executes, however compiler warned me.
            throw new IndexOutOfBoundsException();
        } catch (IndexOutOfBoundsException err) {
            return publishers;
        }
    }
}

1 Ответ

0 голосов
/ 21 апреля 2019

Чтобы список содержал несколько типов, они должны иметь общий суперкласс или интерфейс (если вы не хотите возвращаться к List<Object>).
Относительно создания нового экземпляра универсального типа T: Вы должны получить конкретный класс экземпляра.Если я правильно понимаю, конкретный тип можно определить по аргументам времени выполнения.Здесь есть два варианта

  1. после того, как вы проанализировали аргументы и определили конкретный тип, используйте коммутатор и запрашивайте каждое возможное значение.Код ниже предполагает интерфейс Person, который реализуют все возможные конкретные типы:

    List<? extends Person> returnList = new ArrayList<>();
    String personType = determinePersonTypeFromArgs(args);
    Person person = null;
    switch (personType) {
        case "publisher" :
            person = new Publisher(...);
        case "bromer" :
            person = new Broker(...);
        case "consumer" :
            person = new Consumer(...);
    }
    if (person != null) returnList.add(person);
    return returnList;
    

    Это относительно простое решение.Однако введение нового типа Person требует изменения кода, и есть больше шансов ошибок из-за опечаток и тому подобного.

  2. Использование отражения для создания экземпляра бетона Person.В этом случае строка должна содержать точное полное имя класса (включая пакет), и вы должны получить конструктор в соответствии с типами arg.Короче - более сложный шаблонный код.Тем не менее, он является более расширяемым и упругим.

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