首页 > 解决方案 > 在 Java 中实例化大量子类的最有效方法是什么?

问题描述

我正在做一个项目,该项目需要使用大量扩展特定抽象类的类对象。手动实例化需要调用每个对象的单独构造函数,这开始污染我的客户端类。

该项目的原始代码太长,无法在此站点上发布,因此我在下面提供了一个简化示例:

假设有一个名为 Letter 的抽象类:

public abstract class Letter{
    String letter;
}

以及扩展 Letter 抽象类的 26 个单独的字母类:

public class A extends Letter{
    this.letter = "A";
}

public class B extends Letter{
    this.letter = "B";
}
... and so on

这是我寻求帮助的地方 - 有一个名为 Alphabet 的客户端类:

public class Alphabet{
    public List<Letter> getLetters(){
        List<Letter> letters = new ArrayList<>();
        A a = new A();
        B b = new B();
        C c = new C();
        list.add(a);
        list.add(b);
        list.add(c);
        ...the list goes on

        return letters;
    }
}

如您所见,手动实例化每个字母并不理想。我正在寻找一种在运行时动态创建类对象列表的方法。

也许与此类似:

public class Alphabet{
    public List<Letter> getLetters(){
        List<Letter> letters = getAllClassesExtending(Letter.class);
        return letters;
        //list would then contain A,B,C,D,E,F,G, etc.
    }
}

我最终希望能够创建一个新类并将其自动添加到客户端类中的对象列表中,而无需修改客户端类(例如,我不想显式引用客户端类中的每个字母类) .

标签: javaclassdynamicreflectionloading

解决方案


这听起来像是enum. an 的常量enum可以有一个带有代码的类主体,覆盖基类型的方法,甚至声明新字段。

获取所有子类型的实例的任务意味着一组封闭的子类型,它与enum类型的行为相匹配。

public enum Letter {
    A {
        @Override
        public boolean isVowel() {
            return true;
        }
    },
    B, C, D,
    E {
        @Override
        public boolean isVowel() {
            return true;
        }
    },
    F, G, H,
    I {
        @Override
        public boolean isVowel() {
            return true;
        }
    }, J, K, L, M, N,
    O {
        @Override
        public boolean isVowel() {
            return true;
        }
    }, P, Q, R, S, T,
    U {
        @Override
        public boolean isVowel() {
            return true;
        }
    }, V, W, X, Y, Z;
    ;
    String letter = name();

    public static List<Letter> getLetters() {
        return Arrays.asList(values());
    }

    public boolean isVowel() {
        return false;
    }
}

这表明覆盖方法是可能的,而且获取所有实例(作为数组)的方法也是免费的。此外,名称本质上是指定的,没有冗余。

如果您希望拥有一组开放的子类,以便在编译代码后进行潜在扩展,您应该查看Service Provider 概念ServiceLoader类。这种机制不会自动找到子类,而只会找到那些在文件中META-INF或通过模块声明声明为服务提供者的子类,另一方面,它为您提供了一个健壮的、已建立的解决方案,该解决方案将由 Java 开发人员维护甚至发展与平台一样,融入新的模块概念。


推荐阅读