【问题标题】:Keep reference to new object passed into super constructor保持对传递给超级构造函数的新对象的引用
【发布时间】:2012-10-04 22:49:42
【问题描述】:

有没有一种好方法来维护对在构造函数中创建的对象的引用,该对象需要传递给某些扩展类的超级构造函数(除了使其可以从超类访问或将其作为构造函数传递给参数)?

让我用一个例子来澄清一下。参加这个课程(我无法修改并且无法访问 foo):

class TestA {
    TestA(Object foo) {}
}

现在,我想对这个类进行如下扩展:

class TestB extends TestA {
    Object myCopyOfFoo;

    TestB() {
        super(new Object());
    }
}

有没有好办法将创建的new Object()存储在myCopyOfFoo中?

这三个想法都不行:

TestB() {
    myCopyOfFoo = new Object();
    super(myCopyOfFoo);
}

(错误:构造函数调用必须是构造函数中的第一条语句)

TestB() {
    super(myCopyOfFoo = new Object());
}

(错误:在显式调用构造函数时无法引用实例字段 myCopyOfFoo)

TestB() {
    super(makeFoo());
}

Object makeFoo() {
    myCopyOfFoo = new Object();
    return myCopyOfFoo;
}

(错误:显式调用构造函数时无法引用实例方法)

我想我可以执行以下操作,但它既不是线程安全的也不是优雅的:

static Object tempFoo;

TestB() {
    super(tempFoo = new Object());
    myCopyOfFoo = tempFoo;
}

有人对我有更好的想法吗?为什么我的前两个想法不合法?

【问题讨论】:

    标签: java constructor field super


    【解决方案1】:

    怎么样:

    class TestB extends TestA {
        Object myCopyOfFoo;
    
        // I assume you actually wanted this to take a parameter called foo?
        // I've left it as per the question...
        TestB() {
            this(new Object());
        }
    
        private TestB(Object copy) {
            super(copy);
            myCopyOfFoo = copy;
        }
    }
    

    由于第二个构造函数是私有的,它只能在同一个类(或封闭类)中被调用,所以你只需要确保调用第二个构造函数的任何东西都像第一个构造函数一样进行了适当的复制。

    编辑:如果您的真实情况是您正在获取现有参数的副本,那么这将起作用...

    class ClassB extends ClassA {
        private final Foo copyOfInput;
    
        ClassB(Foo input) {
            super(input = input.clone());
            copyOfInput = input;
        }
    }
    

    虽然很丑:(

    【讨论】:

    • 这看起来是一个很好的解决方案,实际上非常适合我的代码,因为无论如何我已经在很多情况下使用了第二个私有构造函数。我很想已经勾选了这个答案,但它似乎仍然有很多代码。我对此表示怀疑,但让我们看看是否有更短的建议。但是已经谢谢你了!
    • @Markus:如果您的 real 案例实际上已经接受了一个参数并创建了一个副本,我有一个潜在的建议。如果您提供的代码确实具有代表性(即它从无到有创建一个新对象),那么我的其他建议将无济于事。不过我会编辑它。
    【解决方案2】:

    另一种选择:

    public class TestB extends TestA {
    
        Object myCopyOfFoo;
    
        private TestB(Object foo) {
            super(foo);
            myCopyOfFoo = foo;
        }
    
        public static TestB createInstance() {
            Object foo = new Object();
            return new TestB(foo);
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      下面的呢:

      class TestB extends TestA {
          Object myCopyOfFoo = new Object();
      
          TestB() {
              super(myCopyOfFoo);
          }
      }
      

      对象只会在创建新对象TestB时被初始化,所以本质上这会做你想做的事?

      【讨论】:

      • 不,得到错误“在调用超类型构造函数之前无法引用 myCopyOfFoo”
      • 另一个问题是编译器会将 myCopyOfFoo 的初始化内联到 TestB() 构造函数中。因此,即使它没有抛出错误,它也会使用 null 而不是 new Object 调用 super()。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-15
      • 1970-01-01
      • 2014-06-04
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多