转载

Java谜题6:鸡与蛋-解决方案

如果没有给出一个(non-null)Chicken,则Eggthrow 的构造函数抛出 NullPointerException ,反之亦然。那么您如何获得对它们中任何一个的引用?

使这成为可能(甚至是偶然发生的)的一个常见缺陷是调用一个可以在构造函数的子类中重写的方法。但事实并非如此。您可以重写一种方法,使构造函数不调用,但是Java最终调用: finalize() 。该方法在对象被垃圾回收之前被调用,以使其有机会清理其资源。即使构造函数抛出异常,它也会被调用,因此通过重写它,我们可以获得对未完全创建的egg的引用。

<b>package</b> creator;
 
<b>import</b> chicken.Chicken;
<b>import</b> chicken.Egg;
 
<b>public</b> <b>class</b> Creator {
    <b>static</b> <b>class</b> FirstEgg <b>extends</b> Egg {
        FirstEgg() {
            <b>super</b>(<b>null</b>);
        }
 
        @Override
        <b>protected</b> <b>void</b> finalize() {
            <b>new</b> Chicken(<b>this</b>).ask();
        }
    }
 
    <b>public</b> <b>static</b> <b>void</b> main(String[] args) throws Exception {
        <b>try</b> {
            <b>new</b> FirstEgg();
        } <b>catch</b> (NullPointerException e) {
        }
         
        <font><i>// there are ways to force garbage collection harder,</i></font><font>
        </font><font><i>// but this works good enough for me </i></font><font>
        System.gc();
        System.runFinalization();
        Thread.sleep(1000);
    }
}
</font>

众所周知,终结机制有几个 问题,还有更好的选择。在Java的安全编码标准中,有多种方法可以抵御这种情况。另一种方法是在从Object类中调用构造函数之前引发异常。这意味着在调用super()之前执行此工作(或使用this()调用另一个构造函数)。从Java 6开始,这保证finalize()不会被调用。例如,在调用 this(Object)之前,我们先取消对mom.first的引用,以确保在没有妈妈的情况下无法创建鸡蛋:

<b>public</b> <b>class</b> Egg {
    <b>final</b> Object first;
     
    <b>public</b> Egg(Chicken mom) {
        <b>this</b>(mom.first);
    }
     
    <b>private</b> Egg(Object first) {
        <b>this</b>.first = first;
    }
}
原文  https://www.jdon.com/53163
正文到此结束
Loading...