【问题标题】:Create Instance of a Class that is Used in the Constructor of its Outer Class创建在其外部类的构造函数中使用的类的实例
【发布时间】:2015-07-06 15:52:06
【问题描述】:

我正在尝试创建一个在其外部类的构造函数中使用的类的实例。参考下面的代码,我需要一个UserData 对象,但我还需要一个TimeOnlineInfo 对象来创建它,而且我看不到在没有首先拥有UserData 实例的情况下获取TimeOnlineInfo 对象的方法,因为TimeOnlineInfo 不是静态的。我不能让它成为静态的,因为它需要从它的外部类访问一个方法。无论如何我可以让它工作或获得最相似的效果吗?我确实意识到我可以将类设为静态而不直接在 addTime 方法中保存数据,但我已经完成了这个问题的一半,我很想知道是否有办法做到这一点。

这是我的代码的一个非常简化的版本:

class UserData {
    TimeOnlineInfo timeOnline;

    public UserData(Object data1, Object data2, Object data3, Object data4, Object data5, TimeOnlineInfo timeOnlineInfo){
        this.timeOnlineInfo = timeOnlineInfo;
    }

    public class TimeOnlineInfo {
        private int time;

        public TimeOnlineInfo(int time){
           this.time = time;
        }

        public void addTime(int time){
            this.time += time;
            UserData.this.saveData();
        }
    }
}


UserData userData = new UserData(new UserData.TimeOnlineInfo());//Doesn't work because PlayInfo is not a static class
UserData userData = new UserData(userData.new TimeOnlineInfo());//This is just a stupid because i'm using the uncreated object in its own constructor

【问题讨论】:

  • 我不认为这是一个特别好的安排,如果 TimeOnlineInfoUserData 是严格的一对一关系(看起来是这样),为什么要单独,首先公开可见的TimeOnlineInfo 类?当然,这可能是有原因的,但根据您发布的内容,最简单的解决方案是完全摆脱 TimeOnlineInfo

标签: java constructor inner-classes nested-class outer-classes


【解决方案1】:

您对一些事情有一些普遍的困惑。让我们从头开始。

首先,这不是构造函数。

public void UserData(TimeOnlineInfo timeOnlineInfo){
    this.timeOnlineInfo = timeOnlineInfo;
}

您的意思是放弃 void 声明。

public UserData(TimeOnlineInfo timeOnlineInfo){
    this.timeOnlineInfo = timeOnlineInfo;
}

其次,用内部类的实例来实例化外部类在结构上没有意义,因为获得内部类的实例的唯一方法是使用外部类开始吧。

例如,您必须将new UserData().new TimeOnlineInfo(int) 用于TimeOnlineInfo 的实例,但这只是:

  • 如果您选择为UserData 创建一个无参数构造函数
  • 如果你真的不关心 UserData 的实例,你就会回来

如果你真的想要保留这个设计,那么考虑将一个 int 传递给你的构造函数,这样它就可以提供给TimeOnlineInfo 的实例。

class UserData {
    TimeOnlineInfo timeOnlineInfo;

    public void saveData() {
        // stub
    }

    public UserData(int value) {
        this.timeOnlineInfo = new TimeOnlineInfo(value);
    }


    public class TimeOnlineInfo {
        private int time;

        public TimeOnlineInfo(int time){
            this.time = time;
        }

        public void addTime(int time){
            this.time += time;
            UserData.this.saveData();
        }
    }
}

【讨论】:

  • 我仍然会将 TimeOnlineInfo 设为私有 :)
  • 只是一个错字,我在浏览器中写了整个东西。我想这可能是最好的解决方案,即使它有点损害可读性。我想那是我的错,但提出了这么一个奇怪的问题
  • @kmecpp 这不是你的错,这类问题很难在不过度简化的情况下简化为帖子。
【解决方案2】:

首先,您的 UserData 构造函数不是一个。

您已将其声明为 void 方法,因此不会编译 UserData 构造函数,并使用 TimeOnlineInfo 实例进行参数化。

但这可能只是一个错字。

然后,如果您可以在现有构造函数之上为UserData 实现无参数构造函数,则可以使用以下成语:

UserData ud = new UserData(new UserData().new TimeOnlineInfo(42));

但是,这似乎表明您的设计中存在更普遍的问题,因为您基本上必须初始化 UserData 两次才能获得可用的实例。

这里的想法是,你要么在构造函数中注入TimeOnlineInfo,在这种情况下,TimeOnlineInfo 可能会被更广泛的范围使用,而不仅仅是UserData,或者你只在UserData 中使用TimeOnlineInfo,在这种情况下,为UserData 使用一个空的构造函数并在其中初始化您的内部TimeOnlineInfo

【讨论】:

  • 是的,很抱歉,这是一个错字。由于您的原因,无参数构造函数似乎并不是一个好主意,但除了创建嵌套类的唯一目的之外,我也不想创建一个空的、无用的对象。
  • @kmecpp 是的,它看起来像一个丑陋的解决方法。这就是为什么我坚持最后一段关于设计部分的原因。
  • @kmecpp - 这不仅仅是没用;它会链接到错误的外部对象。
【解决方案3】:

你可以把你的构造函数改成这样:

public void UserData(int time){
    this.timeOnlineInfo = new TimeOnlineInfo(time);
}

您还可以将TimeOnlineInfos 构造函数设为私有,以阻止其他人实例化流氓TimeOnlineInfo 实例。

但是根据您发布的 sn-p,我可能会完全摆脱 TimeOnlineInfo


我被警告过,我认为的构造函数不是构造函数。所以首先,永远不要创建与类同名的常规方法

其余的仍然存在,这种安排的问题是任何人都可以创建一个TimeOnlineInfo 对象,即使它没有被创建它的UserData 引用,它也会触发UserData.this.saveData()

所以要么:

  1. 使TimeOnlineInfo 实例化成为UserData 的工作。
  2. 摆脱TimeOnlineInfo。 (如果你的班级已经很大,这是不可行的,但如果你的班级那么大,你可能还需要做其他事情。)
  3. 使您的内部类静态并显式管理连接:

    public void setTimeOnlineInfo(TimeOnlineInfo timeOnlineInfo){
    if (timeOnlineInfo.userData != null) {
        throw new IllegalArgumentException( "TOI already belongs to other UserData" );
    }
     if (this.timeOnlineInfo != null) {
         this.timeOnlineInfo.userData = null;
     }
     timeOnlineInfo.userData = this;
     this.timeOnlineInfo = timeOnlineInfo;
    

    }

    公共静态类 TimeOnlineInfo { 私人int时间; 私有用户数据用户数据;

     public TimeOnlineInfo(int time){
        this.time = time;
     }
    
     public void addTime(int time){
         this.time += time;
         userData.saveData();
     }
    

    }

远非理想,但它也可以解决其他几个问题。

【讨论】:

  • 那是不是构造函数。
  • @Makoto 你是对的...pff,那是另一件事要解决。
  • 这也不是最好的主意,因为 UserData 已经加载了保存所有不同数据所需的所有参数。此外 TimeOnlineInfo 是一种比我看起来更复杂的类型,它不仅仅是一个参数。
  • 静态嵌套类更好。
  • @biziclop - 我只是同意你的观点让你的内部类静态并明确管理连接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 2017-11-24
相关资源
最近更新 更多