具有初始值的 Class 实例的静态数组列表

static arraylist with instances of Class with initial values

我正在用一个静态数组列表制作硬币 class,它存储创建的 class 的每个实例,但是我需要用一个初始实例启动该列表,但我还没有弄清楚如何不添加两次(因为冗余代码),有什么建议吗?

public class Coin {
    private static ArrayList<String> coinNames = new ArrayList<>();
    private static ArrayList<String> coinAbbreviations = new ArrayList<>(Arrays.asList("CLP"));
    private static ArrayList<Coin> coins =
            new ArrayList<>(Arrays.asList(new Coin("Pesos chilenos", "CLP", 1f, "CLP")));
    private static HashMap<String,Float> exchangeRates;
    private String coinName;
    private String coinAbbreviation;
    private Float coinValue;
    private String unit;


    public Coin(String coinName, String coinAbbreviation, Float coinValue, String unit) {
        assert !coinAbbreviations.contains(coinAbbreviation) : "Coin abbreviation already used";
        assert coinAbbreviations.contains(unit) : "Coin unit non existent.";
        assert !coinNames.contains(coinName) : "Coin name already used.";
        this.coinName = coinName;
        this.coinAbbreviation = coinAbbreviation;
        this.coinValue = coinValue;
        this.unit = unit;

        coins.add(this);
    }
}

如果您坚持使用可变静态变量——这样做通常根本不是一个好主意——您可以这样做

private static ArrayList<Coin> coins =
        new ArrayList<>();

static {
  new Coin("Pesos chilenos", "CLP", 1f, "CLP");
}

...立即将元素添加到列表中。

是什么阻止了您在声明中初始化列表,然后在构造函数中将每个实例添加到列表中?

您也可以使用一些最佳实践模式来设计您的应用程序。你想保留所有创建的硬币的注册表。最好将其保存在 Coin class 本身之外。你可以有一个 class 来管理硬币的创建并保留它创建的列表。如果您愿意,Coin class 本身可以是一个接口,因为这样可以确保它不能由 CoinFactory 以外的其他人创建。

public interface Coin {
    String name();
    String abbreviation();
    BigDecimal value();
    String unit();
}

和硬币工厂class:

public class CoinFactory {

    // Concrete coin is an internal implementation class whose details don't
    // need to be known outside of the CoinFactory class.
    // Users just see it as interface Coin.
    private static class ConcreteCoin implements Coin {
        private final String name;
        private final String abbreviation;
        private final BigDecimal value;
        private final String unit;

        ConcreteCoin(String name, String abbreviation, BigDecimal value, String unit) {
            this.abbreviation = abbreviation;
            this.name = name;
            this.value = value;
            this.unit = unit;
        }

        public String name() { return name; }
        public String abbreviation() { return abbreviation; }
        public BigDecimal value() { return value; }
        public String unit() { return unit; }
    }

    // Sets for enforcing uniqueness of names and abbreviations
    private Set<String> names = new HashSet<>();
    private Set<String> abbreviations = new HashSet<>();

    // All coins must have one of the following ISO currency codes as the 'unit' field.
    private final Set<String> allIsoCurrencyCodes =
            Set.of("CLP", "GBP", "EUR", "CAD", "USD", "XXX" /* , ... */);

    private List<Coin> allCoins = new ArrayList<>(
            List.of(createCoin("Pesos chilenos", "CLP", BigDecimal.ONE, "CLP")));

    private List<Coin> unmodifiableListOfAllCoins =
            Collections.unmodifiableList(allCoins);


    public Coin createCoin(String name, String abbreviation, BigDecimal value, String unit) {
        if (!names.add(name))
            throw new IllegalArgumentException("Name already exists: " + name);
        if (!abbreviations.add(abbreviation))
            throw new IllegalArgumentException("Abbreviation already exists: " + abbreviation);
        if (!allIsoCurrencyCodes.contains(unit))
            throw new IllegalArgumentException("Coin unit is not a recognised ISO currency code: " + unit);

        Coin coin = new ConcreteCoin(name, abbreviation, value, unit);
        allCoins.add(coin);
        return coin;
    }

    public Collection<Coin> allCoins() {
        return unmodifiableListOfAllCoins;
    }
}