避免在循环中实例化对象 - SONAR抱怨

时间:2017-03-23 14:13:59

标签: java generics

在循环中实例化对象是每个开发人员都会采用的常用方法。

我们在循环内实例化具有不同泛型和集合类型的不同对象,这是不可建议的。定义获取实例的私有方法可以解决问题。但我正在寻找达到同样目标的通用方法。

示例:在以下代码中

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

这是一种在单独的静态类中隔离这些方法的安全方法,以便可以在所有类中使用它。实例化超出类范围的对象?

提前分享想法和感谢

2 个答案:

答案 0 :(得分:1)

这完全取决于你使用这些方法获得的集合或对象做了什么。如果有人可能用类型来调用它而你没有预料到这会导致错误,我认为最好限制对这些方法或类的访问。

如果您希望这些方法中只有具有特定超类的子类,则可以使用通配符。例如:

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 :(得分:1)

如果可能的话,应该避免反思。这里似乎没有任何东西需要它。

通常对于集合,类型参数就足够了,所以我们不必做太多困难。

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