9

如何将 10 乘以一个Integer对象并取回该Integer对象?

我正在寻找最简洁的方法。

我可能会这样做:从Integer对象中获取 int,将它与另一个 int 相乘,然后用这个 int 值创建另一个 Integer 对象。

代码将类似于...

integerObj = new Integer(integerObj.intValue() * 10);

但是,我看到了作者这样做的代码:StringInteger对象中获取,最后连接“0”,然后Integer通过使用获取对象Integer.parseInt

代码是这样的:

String s = integerObj + "0";
integerObj = Integer.parseInt(s);

这样做有什么好处吗?

一般来说,在这种情况下,最有效/最简洁的方式是什么?

4

6 回答 6

27

使用 Java 5 的自动装箱,您可以简单地执行以下操作:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a);
于 2008-09-05T14:52:57.907 回答
7

字符串方法很有趣,但几乎可以肯定是一种不好的方法。

获取 Integer 的 int 值并创建一个新值将非常快,因为调用 parseInt 会相当昂贵。

总体而言,我同意您的原始方法(正如其他人指出的那样,如果您有 Java 5 中引入的自动装箱,则可以在没有太多混乱的情况下完成该方法)。

于 2008-09-05T14:52:19.237 回答
3

第二种方式的问题是Java中处理字符串的方式:

  • "0"在编译时转换为常量 String 对象。
  • 每次调用此代码时,s都会将其构造为新的 String 对象,javac并将该代码转换为String s = new StringBuilder().append(integerObj.toString()).append("0").toString()(旧版本为 StringBuffer)。即使您使用相同的integerObj,即

    String s1 = integerObj + "0"; String s2 = integerObj + "0";

    (s1 == s2)会 会 会false会会s1.equals(s2)true

  • Integer.parseIntnew Integer()无论如何内部调用,因为Integer它是不可变的。

顺便说一句,自动装箱/拆箱在内部与第一种方法相同。

于 2008-09-05T17:59:01.237 回答
1

远离第二种方法,如果您使用的是 java 1.5,最好的选择是自动装箱,您的第一个示例之前的任何内容都是最好的。

于 2008-09-05T14:56:08.540 回答
1

由于各种原因,使用 String 方法的解决方案并不是那么好。有些是美学原因,有些是实用的。

在实际方面,String 版本比更正常的形式创建了更多的对象(正如您在第一个示例中所表达的那样)。

在美学方面,我认为第二个版本掩盖了代码的意图,这几乎与让它产生你想要的结果一样重要。

于 2008-09-05T14:56:13.173 回答
0

上面工具包的答案是正确的,也是最好的方法,但它没有对正在发生的事情给出完整的解释。假设 Java 5 或更高版本:

Integer a = new Integer(2); // or even just Integer a = 2;
a *= 10;
System.out.println(a); // will output 20

您需要知道的是,这与执行以下操作完全相同:

Integer a = new Integer(2); // or even just Integer a = 2;
a = a.intValue() * 10;
System.out.println(a.intValue()); // will output 20

通过对对象“a”执行操作(在本例中为 *=),您不会更改“a”对象内的 int 值,而是实际上将新对象分配给“a”。这是因为“a”被自动拆箱以执行乘法,然后乘法的结果被自动装箱并分配给“a”。

整数是不可变的对象。(所有包装类都是不可变的。)

以这段代码为例:

static void test() {
    Integer i = new Integer(10);
    System.out.println("StartingMemory: " + System.identityHashCode(i));
    changeInteger(i);
    System.out.println("Step1: " + i);
    changeInteger(++i);
    System.out.println("Step2: " + i.intValue());
    System.out.println("MiddleMemory: " + System.identityHashCode(i));
}

static void changeInteger(Integer i) {
    System.out.println("ChangeStartMemory: " + System.identityHashCode(i));
    System.out.println("ChangeStartValue: " + i);
    i++;
    System.out.println("ChangeEnd: " + i);
    System.out.println("ChangeEndMemory: " + System.identityHashCode(i));
}

输出将是:

StartingMemory: 1373539035
ChangeStartMemory: 1373539035
ChangeStartValue: 10
ChangeEnd: 11
ChangeEndMemory: 190331520
Step1: 10
ChangeStartMemory: 190331520
ChangeStartValue: 11
ChangeEnd: 12
ChangeEndMemory: 1298706257
Step2: 11
MiddleMemory: 190331520

你可以看到'i'的内存地址正在改变(你的内存地址会不同)。

现在让我们用反射做一个小测试,将它添加到 test() 方法的末尾:

System.out.println("MiddleMemory: " + System.identityHashCode(i));
try {
    final Field f = i.getClass().getDeclaredField("value");
    f.setAccessible(true);
    f.setInt(i, 15);
    System.out.println("Step3: " + i.intValue());
    System.out.println("EndingMemory: " + System.identityHashCode(i));
} catch (final Exception e) {
    e.printStackTrace();
}

额外的输出将是:

MiddleMemory: 190331520
Step2: 15
MiddleMemory: 190331520

您可以看到“i”的内存地址没有改变,即使我们使用反射改变了它的值。
(不要在现实生活中以这种方式使用反射!!)

于 2014-06-18T08:54:57.930 回答