Создание объектов внутри цикла - это общий подход каждого разработчика.

Мы создаем экземпляры разных объектов с разными универсальными типами и типами коллекций внутри циклов, что не представляется возможным. Определение частного метода для получения экземпляра может решить проблему. Но я ищу общий подход для достижения того же.

Пример: в приведенном ниже коде

if (CollectionUtils.isNotEmpty(xList)) {
        for (final X x : xList) {
        final List<Y> yList = new ArrayList<Y>();
        final Z z = new Z();
        populateYList(yList);
        if (CollectionUtils.isNotEmpty(yList)) {
           // do something
        }
    }

Когда мы идем по общему пути, безопасен ли объект? Мало из моих усилий ниже

private <T> List<T> getCollectionIntializer(Class<T> type) {
        return new ArrayList<T>();
    }


private <T> T getIntializer(Class<T> clazz) {
        T c = null;
        try {
            c = (T) clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return c;
    }

Наконец мой код выглядит

if (CollectionUtils.isNotEmpty(xList)) {
        for (final X x : xList) {
        final List<Y> yList = getCollectionIntializer(Y.class);
        final Z z = getIntializer(Z.class);
        populateYList(yList);
        if (CollectionUtils.isNotEmpty(yList)) {
           // do something
        }
    }

Это безопасный способ разделения этих методов в отдельный статический класс, чтобы его можно было использовать во всех классах. Создание объектов вне области видимости?

Поделитесь мыслью и заранее спасибо

1
Gopi 23 Мар 2017 в 17:13

2 ответа

Лучший ответ

Все зависит от того, что вы делаете с коллекцией или объектом, который вы получаете этими методами. Если кто-то может вызывать его с типами, которых вы не ожидаете, и это может привести к ошибке, я думаю, было бы лучше как-то ограничить доступ к этим методам или классам.

Если вы ожидаете только подклассы с определенным суперклассом в этих методах, вы можете использовать подстановочные знаки. Например:

private <T extends Number> List<T> getCollectionIntializer(Class<T> type) {
        return new ArrayList<T>();
    }

И если я вызову метод getCollectionIntializer следующим образом:

SomeClass someClass = new SomeClass();
List<SomeClass> list = someClass.getCollectionIntializer(someClass.getClass());

Я получу ошибку компиляции:

Error:(27, 41) java: method getCollectionIntializer in class SomeClass cannot be applied to given types;
  required: java.lang.Class<T>
  found: java.lang.Class<capture#1 of ? extends SomeClass>
  reason: inferred type does not conform to upper bound(s)
    inferred: capture#1 of ? extends SomeClass
    upper bound(s): java.lang.Number

Может быть, это будет полезно.

1
DontPanic 23 Мар 2017 в 17:44

Следует избегать отражения, если это вообще возможно. Здесь нет ничего, что, кажется, требует этого.

Обычно для коллекций достаточно параметра типа, поэтому нам не нужно делать ничего слишком сложного.

    final List<Y> yList = new ArrayList<>();

Для создания объекта обычно применяется шаблон Абстрактная фабрика. java.util.function.Supplier предоставляет общий интерфейс. Supplier можно получить, используя ссылку на метод в синтаксисе конструктора.

    myCode(MyZ::new);

[ ... ]

    public static <Z> List<Z> myCode(Supplier<Z> supplier) {
        List<Z> zList = new ArrayList<>();
        zList.add(suppler.get());
        return zList;
    } 
1
Tom Hawtin - tackline 24 Мар 2017 в 14:54