java中的static和final

时间:2012-09-22 19:19:36

标签: java static final

我正在从this页面阅读Java中的枚举示例。

在第一个示例中,我唯一不理解的部分是在此部分代码中使用static关键字:

private static final List<Card> protoDeck = new ArrayList<Card>();

// Initialize prototype deck
static {
    for (Suit suit : Suit.values())
        for (Rank rank : Rank.values())
            protoDeck.add(new Card(rank, suit));
}

public static ArrayList<Card> newDeck() {
    return new ArrayList<Card>(protoDeck); // Return copy of prototype deck
}

为什么protoDeck声明staticfinal?然后,使用静态循环初始化protoDeck。我知道静态变量,它们在对象实例之间保留它们的值。但这是一个单例类(私有构造函数),因此无法实例化。

那么这样做的好处是什么?如果proteDeck不是staticfinal会产生什么影响?

6 个答案:

答案 0 :(得分:2)

从技术上讲,这是不是单例类。 (单身人员有一个实例,这个实例 none !)

对于ArrayList<Card>,它是工厂方法,方法newDeck的工作方式与构造函数对“CardArrayList”类的工作方式相同。它不是Java构造函数,而是工厂方法,但除此之外它起到同样的作用:创建新的卡片组。

使用课程CardArrayList和子类型ArrayList显然是另类选择。试试这个练习:写一下类,这样就可以达到同样的目的。尝试使用常量(static final)来保留初始对象集。您会注意到这两者之间几乎没有什么区别,除了这种方法清楚地表明没有附加功能,但结果是“除了包含完整套牌的ArrayList<Card>之外”。子类化可能意味着有额外的功能,例如确保卡板不会被搞乱。

static final变量包含用作新对象模板的原型。

答案 1 :(得分:1)

您的代码的静态{....}部分将在Java虚拟机加载类的位置执行。

在您的代码段中,它用于初始化protoDeck ArrayList。

这不遵循Singleton模式,因为您的代码中没有证据表明该类只被实例化了一次。

答案 2 :(得分:1)

在类初始化(static括号中的代码)中,程序生成卡片的所有卡片并将其存储在protoDeck中。

调用newDeck时,将返回卡组的浅表副本。这意味着游戏中的所有牌对象都是同一个对象(只有一张“黑桃王牌”牌)。不过,它们在几个不同的套牌中进行管理。

恕我直言,对于这个例子来说这有点太复杂了,如果不是Cards而不是{{1}}那么其他类(一个初始化在RAM中代价高昂/昂贵,或者其他代表它们的地方)会更有意义系统资源 - 数据库连接或类似 - )。

答案 3 :(得分:0)

如果它不是静态的,代码将无法编译,因为newDeck方法是静态的,而newDeck是静态的,因为你没有为不同的卡获得不同的套牌。

让它不是最终的不会做任何不同的事情。这是最终的,因为你不能分配不同的数组。但你仍然可以添加它,所以它不是一成不变的。所以这是一个常见的线索,但不是行为的改变。

答案 4 :(得分:0)

Java中的final关键字支持各种编译时魔术。例如,当编译器知道永远不会重新分配变量时,它可以执行“memoization”优化。

单独这是final的一个很好的理由 - 默认情况下使用局部变量,参数和类成员 - 除非你真的必须能够重新分配它们,当然。

答案 5 :(得分:0)

如果protoDeck不是static,则每个Card会有一个static,这不会是一件好事。

显然,您只能使用static代码构建final变量。

protoDeck只是意味着永远不会替换{{1}}(尽管可以在内部进行更改)。