【问题标题】:Nested Subclass Instantiation Declaration Java嵌套子类实例化声明 Java
【发布时间】:2018-02-04 00:16:50
【问题描述】:

来自 JavaScript 背景,我发现以下代码有点过于健壮,包含多个语句;并且想知道如何简化代码,并在一条语句中完成所有操作。

Student 是超类,Friend 和 Schedule 是聚合成超类 ArrayList 公共成员的子类(这些不是嵌套类)。这是我当前的代码:

public static void main(String[] args) {

  // Subclass1 instantiation and declaration
  Friend friend_of_andy_1 = new Friend(1002, "Bob");
  ArrayList<Friend> andys_friends = new ArrayList<>();
  andys_friends.add(friend_of_andy_1);    // superclass member

  // Subclass1 instantiation and declaration
  Schedule schedule_of_andy_1 = new Schedule(1, "Yoga practice");
  ArrayList<Schedule> andys_schedule = new ArrayList<>();
  andys_schedule.add(schedule_of_andy_1); // superclass member

  // Superclass instantiation declaration with subclass objects in constructor argument
  Student student_andy = new Student(1001, "Andy", andys_friends, andys_schedule);

}

我想知道是否可以这样做,在单个语句中声明/实例化超类和子类;这可能吗?

public static void main(String[] args) {

  Student student_andy = new Student(
    1001,
    "Andy",
    // instantiation of subclass
    ArrayList<Friend>[
      Friend(
        {
          1002,
          "Bob"
        }
      )
    ],
    ArrayList<Schedule>[
      Schedule(
        {
          1,
          "Yoga practice"
        }
      )
    ]
  )

};

【问题讨论】:

  • 你知道Arrays.asList(foo, bar, baz)吗?
  • @DawoodibnKareem 是的……你能不能把 foo 写成实例化/声明……像这样:Arrays.asList(new_foo(arg1, arg2), bar, baz) ??
  • 您为什么不尝试一下,然后在此处发表评论,说明您的进展如何?

标签: java inheritance subclass aggregation


【解决方案1】:

首先,你只在一个地方使用friend_of_andy_1,所以你可以消除它:

List<Friend> andys_friends = new ArrayList<>();
andys_friends.add(new Friend(1002, "Bob"));

其次,如果您对具有固定大小的列表感到满意,即您不能向其中添加更多元素,则可以使用Arrays.asList(),而不是创建ArrayList

List<Friend> andys_friends = Arrays.asList(new Friend(1002, "Bob"));

然后你可以对Schedule做同样的事情,并在Student的创建中内联:

Student student_andy = new Student(1001, "Andy",
                                   Arrays.asList(new Friend(1002, "Bob")),
                                   Arrays.asList(new Schedule(1, "Yoga practice")));

如果列表必须可调整大小,则使用ArrayList​(Collection&lt;? extends E&gt; c) 构造函数:

Student student_andy = new Student(
        1001,
        "Andy",
        new ArrayList<>(Arrays.asList(
                new Friend(1002, "Bob")
        )),
        new ArrayList<>(Arrays.asList(
                new Schedule(1, "Yoga practice")
        ))
);

当然还有你想要的格式,如果你更喜欢占用太多代码行的分解样式:

Student student_andy = new Student(
    1001,
    "Andy",
    new ArrayList<>(
        Arrays.asList(
            new Friend(
                1002,
                "Bob"
            )
        )
    ),
    new ArrayList<>(
        Arrays.asList(
            new Schedule(
                1,
                "Yoga practice"
            )
        )
    )
);

【讨论】:

  • 是的,它需要调整大小,您能解释一下在构建新学生之后如何调整列表的大小吗? -- 使用 ArrayList​(Collection extends E> c)
  • @Jim22150 student_andy.addFriend(new Friend(1007, "John")); 其中addFriend(Friend friend) 实现为this.friends.add(friend); --- 你真的只是问如何向List 添加一些东西吗?
  • @Jim22150 列表不需要显式调整大小。如果它们可以调整大小,那么您可以使用add 方法根据需要向它们添加内容。 Arrays.asList 创建的列表不可调整大小,这就是为什么此解决方案的后半部分从 Arrays.asList 创建的列表中构建额外列表的原因。
【解决方案2】:

好的,那么,本质上,您缺少 JSON [footnote-1] 太多了吗?可以理解。

以下是在 Java 中创建实例的松散方法集合,以便它尽可能看起来像 JSON。

1) 数组: 使用内联数组字面量

它们在 Java 中略显冗长,但几乎与 JSON 中的 [ ... ] 一样好,例如:

new int[]{1, 2, 3}

是整数数组的文字。

2) 对象:定义适当的构造函数

如果你的Friend 有一个构造函数public Friend(int id, String name),那么初始化Friends 真的很容易和愉快:

new Friend(1234, "Bob")

3) 更多对象,更快使用工厂方法

如果你定义工厂方法,你可以摆脱new。例如。如果你有

class Friend {
    ...
    static Friend friend(int id, String name) { return new Friend(id, name); }
}

那么你甚至可以摆脱new。这在您定义某种嵌入式 DSL 并且确实需要此构造函数数千次的极少数情况下很有用。

4) 列表: 使用asList

您可以在 Java 中使用 静态导入 导入静态方法:

import static java.util.Arrays.asList;

现在您可以使用方便的asList,以便

asList(friend(2, "John"), friend(3, "Bob"))

给你一个朋友列表。

5) 映射:使用带有初始化块的匿名子类。

这个看似疯狂的东西在 java 中有效:

HashMap<String, Integer> hm = new HashMap<>{{
  put("foo", 10);
  put("bar", 20);
}};

这是因为内部的一对花括号包含了一个 initializer 块,您可以在其中调用 this 上的方法。

好的,现在你可以轻松创建了:

  • 原始资料:字符串、ints、doubles
  • 用户定义的对象(使用构造函数和工厂方法)
  • 数组
  • 列表
  • 地图

这应该足以在 Java 中创建特殊的 json-esque 数据结构。


现在,假设所有构造函数都已就位,您的代码将变为:

import static java.util.Arrays.asList;

...

Student student_andy = new Student(
  1001,
  "Andy",
  asList(new Friend(1002, "Bob")),
  asList(new Schedule(1, "Yoga practice"))
)

我们在这里没有使用地图,所以带有初始化块的提示只是一个奖励。

[footnote-1] 更准确地说:您似乎缺少 JavaScript 片段,该片段允许轻松初始化那些规范映射到 JSON 对象的对象。 JSON 当然不是 JavaScript。感谢@Andreas 指出这一点。

【讨论】:

  • 谢谢,这看起来是一套很棒的工具可供试用。是的,确实缺少 JSON;但是,将读取实际的 JSON 数据。所以我可以看到在循环外部数据时我绝对可以在哪里使用你的建议。
  • 请注意,已经有非常强大的标准库可以为 Java 解析 JSON,因此这些技巧在处理 JSON 本身时可能不太有用。但是,我发现它有时对设置小型测试用例很有用,我需要一些小的具体数据结构。
  • 你能推荐一个用于 NetBeans 的 JSON 库吗?
  • @Andreas 不要给男人一条鱼。给他一根鱼竿!啊,什么,忘记钓鱼竿,给他一个该死的拖网渔船! ;) 不,认真的。我刚刚看到根本问题是 OP 缺少 JSON。我不希望他太想念 JSON。所以我一次给了所有必要的部分。我希望这能解决根本问题,而不仅仅是这三个对象实例的问题。
  • @Jim22150 Netbeans 只是一个 IDE。它不关心您使用哪个项目依赖项。有各种库可以处理 JSON,例如javax.jsonorg.json see here 还有更复杂的工具,如 jacksongson。这取决于你想用它做什么:你想访问原始解析的 json 数据,还是想把它映射到 PlainOldJavaO自动生成对象?只需点击链接,四处看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
相关资源
最近更新 更多