【问题标题】:static arraylist with instances of Class with initial values具有带初始值的类实例的静态数组列表
【发布时间】:2017-09-19 17:28:11
【问题描述】:

我正在创建一个带有静态数组列表的 Coin 类,该类存储创建的类的每个实例,但是我需要使用初始实例启动该列表,而且我还没有弄清楚如何在不添加两次的情况下做到这一点(因为一个冗余代码),有什么建议吗?

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

【问题讨论】:

  • 存储每个实例的静态数组列表不知道你想做什么
  • 请记住,这种模式本质上是线程不安全的(也就是说,你基本上永远不能用它编写线程安全的代码),所以这是一个坏习惯。更好的方法是私有构造函数和调用该构造函数然后将实例添加到coins 的静态工厂方法。
  • 最好有一个 CoinFactory 类来创建(并返回)Coin 实例并将它们添加到自身。您当前的解决方案不是线程安全的,这只是一个缺点。
  • @DodgyCodeException 你能解释一下吗,我认为这可能是解决方案
  • @NicolasQuiroz 我试图解释;在下面查看我的新答案。

标签: java arraylist java-8 static-initialization


【解决方案1】:

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

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

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

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

【讨论】:

  • 那么有什么更好的主意呢?
  • 有一个实际的类来存储你制作的所有硬币。不要让它与构造函数绑定,明确列出它们。
  • 嘿,当你说 不要让它与构造函数绑定,明确列出它们时,我不明白这一点。你的意思是每当我实例化它时,构造函数不会自动存储它,但我必须手动执行它?
  • 是的。让你的构造函数自动存储东西是危险和令人担忧的。
【解决方案2】:

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

【讨论】:

  • 这就是 OP 正在做的事情,但他们想要的是“自动”添加一个 Coin(“Pesos chilenos”),而不需要此类的用户手动实例化它。
【解决方案3】:

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

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

还有 Coin 工厂类:

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

【讨论】:

    猜你喜欢
    • 2015-06-26
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多