代码之家  ›  专栏  ›  技术社区  ›  Roman

我可以在它的构造函数中引用一个对象吗?

  •  4
  • Roman  · 技术社区  · 15 年前

    public Manager(String userName) {
        game = new Game(userName);
        game.addManager(this);
    }
    

    问题是我指的是一个物体( this )在它的构造函数中(在它被实际创建之前)。

    7 回复  |  直到 15 年前
        1
  •  4
  •   Yishai    15 年前

    尽管它是合法的Java,而且在您描述的情况下(它是构造函数的最后一行),它是一个相当安全的事情(某些边缘情况除外),作为实践,它是一个不好的事情,并且喜欢使用 goto

     public static Manager createManager(String userName) {
            Manager manager = new Manager(userName);
            manager.game.addManager(manager);
            return manager;
     }
    

    我还应该指出,类之间的那种相互依赖(管理器知道游戏,游戏知道管理器)绝对是一种代码味道,我会像从构造函数传递这种气味一样,关心对它的需要。

        2
  •  3
  •   Community CDub    8 年前

    可以 那样做,但是你 .

    this 当构造函数仍在运行时,可能会产生各种奇怪的副作用,因为某些常见的保证在构造函数仍在运行时不成立(例如 final 在构造函数仍在运行时,变量似乎会更改其值。

    This IBM developerWorks article 施工期间。

    (最后一段是从 one of my earlier answers ).

        3
  •  2
  •   James    15 年前

    是的,很完美 但不推荐使用Java。见 here 有关更多详细信息,请参见 this 关键字。

        4
  •  1
  •   Jeff Storey    15 年前

    正如@James所说,你可以,但这不一定是你想做的。如果 game.addManager 尝试访问管理器的某些属性时,可能会尝试访问尚未初始化的管理器的属性。更好的方法是让一个外部对象调用一些in it方法(或一些生命周期方法)来添加管理器,而不是在构造函数中执行。

        6
  •  0
  •   Roman    15 年前

    这种技术违反了java并发概念之一——安全发布。你应该用 init()

    您可以在 引用已被转义。如果将对象在其构造函数中的实例传递给另一个对象,则可以在构造期间获取回调。它会导致不一致的行为,NPEs,死锁等等。

        7
  •  0
  •   Vincent    15 年前

    孩子,这不安全!虽然代码有效,但设计不好!您的代码允许“this”引用在正确构造对象之前转义。

    想象一下game.addManager()将调用“this”引用上的某个方法xxx()。 我们有一个子类Manager,ChildManager,它重写方法xxx(),这个方法依赖于ChildManager中的一个字段(当超级构造函数到达它的最后一行代码时,这个字段不会初始化)。 addManager()将在ChildManager中看到字段的未初始化值,这非常危险!

        public class Manager {
        Game game;
        public Manager (String userName){
            game = new Game(userName);
            game.addManager(this);
        }
        public void xxx(){
    
        }
    }
    
    public class ChildManager extends Manager {
        String name;
        public ChildManager (String username){
            super(username);
            name = username;
        }
    
        public void xxx (){
            System.out.println(name);
        }
    }
    
    public class Game {
        public Game (String userName){
    
        }
    
        public void addManager (Manager m){
            m.xxx();
        }
    }