【问题标题】:Error in OCJP exam simulation: how many objects are really created? [duplicate]OCJP 考试模拟中的错误:真正创建了多少对象? [复制]
【发布时间】:2013-08-18 09:59:16
【问题描述】:

在模拟 OCJP 认证时,我发现了这个问题:

1. StringBuffer s1 = new StringBuffer("abc");
2. StringBuffer s2 = s1;
3. StringBuffer s3 = new StringBuffer("abc");

How many objects are created ?

他们说正确答案是 4,因为他们说:

s1 is one object, s2 is another object, 
s3 is another object and "abc" is another String Object .

但对我来说这是错误的,应该是 3,因为 s1s2 是同一个对象。你怎么看?

【问题讨论】:

  • 如果真的如其所言,那么您应该停止使用该网站。
  • 是的,应该是 3。至少据我所知
  • 不会像在 C++ 中那样在赋值上调用复制构造函数。在 Java 中,我认为您应该执行类似 MyClass s2 = new MyClass(s1);
  • 请将链接发布到违规网站,以便我们避免它。
  • 学究气,不可能知道。 StringBuffer 构造函数可以在后台创建任意数量的对象。

标签: java


【解决方案1】:

你是对的,答案不是 4 个对象。

但是,“创建了多少对象”这个问题是模棱两可的。问题是执行代码时未创建三个对象之一。具体来说,对应于"abc" 文字的String 对象是实际上 在代码加载时创建的。执行该代码时,会创建两个 StringBuffer 对象,并使用预先存在的 String 对象。

实际上它比这更复杂,因为在类加载时,可能会创建另一个临时 String 对象,然后在它被实习后丢弃;

  • 如果 "abc" 文字已经加载到不同的类中,则将使用该类。

  • 如果字符串池实现需要将String放入池中,则未指定是否制作新的副本。

除非问题被更准确地陈述,否则没有单一的正确答案。最好的说法是:

  • 运行代码时会创建两个StringBuffer 对象。
  • 加载代码时会创建一个或两个String 对象。

然后是您是否应该计算构成StringBufferString 对象一部分的私有char[] 对象的问题。这可能会使对象数量增加到 8 个。

【讨论】:

  • 同意。这个问题不正确。也毫无意义。如果 OCJP 确实包含有关创建多少对象的任何问题,则应将其删除。我从来没有在面试中问过或被问过这样的问题,而且我会对任何这样做的面试官产生相当糟糕的看法。鉴于垃圾收集的存在,并且考虑到问题依赖于大多数程序员不会阅读的 JLS 方面,它基本上是完全无关紧要的。 +1
  • @EJP SCJP 包含此类问题,但绝不会出现这种极端情况(可能在内部实例化其他事物的类、字符串常量池等)。
【解决方案2】:

是的,肯定是 3 Object.both s1 和 s2 都指向同一个位置。所以 s1, s2 和 "abc" 是这里的对象。可能最好不要遵循该参考。

【讨论】:

  • 你第一次是对的。不要为此害羞。
  • 他实际上是错的,至少在电位上是这样。还创建了一个 Class 的实例,以及一个 Class 的实例。内部 StringBuffer 无疑也创建了一些东西的实例,以及它们的 Class. 的实例
  • @jwenting 这两个类实例都是在加载包含此代码的类时创建的,而不是在执行 OP 中的代码时创建的。
  • @EJP 是的,但他从未提及问题的范围 :)
【解决方案3】:

更正

应该有3个对象:

1. StringBuffer s1 = new StringBuffer("abc");

将在内存 s1 & "abc" 中创建两个对象。这是因为,字符串被保留,文字被添加到内存池中。

2. StringBuffer s2 = s1;

这里不会创建任何对象,因为 s2 将指向作为 s1 一部分创建的“abc”

3. StringBuffer s3 = new StringBuffer("abc");

只会为 s3 创建一个对象。

【讨论】:

  • 嗯,字符串实习不是意味着内存中只有一个"abc"吗?
  • 但它是字符串文字,而不是new String
  • not '用 new 运算符创建一个字符串对象'。他正在使用现有的 String 作为参数创建一个 StringBuffer。正确答案是 3。-1
  • 抱歉各位散布了错误信息。我试图纠正我的答案。随时提供更多的 cmets。
  • @OliCharlesworth 是对的,“abc”在编译时都是文字字符串,在运行时它们将是同一个对象。
【解决方案4】:

怎么样:

1. StringBuffer s1 = new StringBuffer("abc");

1 builder object + 1 char[] object +(1 个字符串字面量,如果已创建)

2. StringBuffer s2 = s1;

没有新对象。

3. StringBuffer s3 = new StringBuffer("abc");

1 builder 对象 + 1 char[] 对象

一个StringBuilder封装里面的backing char[],它一个对象。

正如@StephenC 所说,这个问题是模棱两可的。

【讨论】:

    【解决方案5】:

    3 或 4,具体取决于实现。一些编译器只会为常量“abc”创建一个 String 对象,并根据需要多次引用它,而其他编译器会为每个常量创建一个对象。 AFAIK,这并不是所有语言规范版本都强制要求的,将来可能会再次改变。

    或更多,取决于 StringBuffer 的实现(它可以主动创建一个 char[] 并复制初始化 String,而不是延迟执行直到 StringBuffer 的内容真正改变)。同样,这不应该由语言强制要求。而且,顺便说一句,就问题而言,数组是否算作Objects?如果 StringBuffer 实现将信息存储在 JNI 结构中会怎样?那算什么东西?我只是想再次强调我对非语言强制实施细节的观点。

    测试不应提出此类问题,除非它与特定实现和/或 JLS 版本有关。

    绝对清楚的是,他们给出的答案为 4 的原因是完全错误的。对s2 的赋值不会导致创建任何新对象。

    【讨论】:

    • 不正确。 JLS 和 JVM 规范要求 Java 编译器来池化字符串文字。
    • @EJP JLS 已经随着时间而改变,即使在这个特定方面也是如此。当我说“语言”时,我不是指 JLS 的最后一个版本,也不是下一个版本。不过,我会尽量让我的回答更清楚。非常感谢。
    • 我不知道有任何此类更改。请提供引用。据我所知,这种形式的问题的基本答案,但只涉及字符串和文字,自 1997 年以来根本没有改变。
    • 我很清楚这一点,因为很久以前(Java 的早期阶段),我开发了一个 Java 课程。本课程的第一版涵盖了 Java 1.0.1。为了演示如何创建Strings,我使用了一个小示例程序。好吧,我不得不更改我的示例程序(以及周围的解释)1 或 2 次,通常是同时讲授课程。我当然记得! :-)
    猜你喜欢
    • 1970-01-01
    • 2012-04-20
    • 2020-06-06
    • 2012-05-13
    • 2014-11-26
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多