如何将10乘以Java中的“Integer”对象?

问题描述:

如何将10乘以Integer对象并找回Integer对象?如何将10乘以Java中的“Integer”对象?

我正在寻找这样做的最好方法。

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

代码将是这样......

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

但是,我看到这里笔者是做什么的这样一个代码:从Integer对象获取String,并置“0”,在结束然后得到Integer对象返回使用Integer.parseInt

的代码是这样的:

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

的是无论以哪种方式做任何优点?

在这种情况下,一般情况下最有效/最新的方法是什么?

+0

我还建议你检查一下使用Integer是否真的需要。 Joshua指出在有效Java中使用原语要快很多倍。所以,如果可以的话,坚持** int **。 – 2008-09-05 15:54:56

+0

使用Integer实际上是一个设计约束。这个想法是我得到一个Integer对象,我必须更新它。所以,不能取消:) – Jagmal 2008-09-05 17:40:24

+0

更新现有的Integer对象不会发生没有反射巫术。 (像其他原始包装类型一样,Integer是不可变的。)你可以合理地做的最好的 - 以及任何理智的例子将会做的 - 用另一个对象代替它。对于大多数情况来说这足够好,但是意味着`void modifyInteger(Integer i)`不会做任何有价值的事情。 – cHao 2014-04-15 02:48:58

使用Java 5的autoboxing,你可以简单地做:

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

字符串的方法是有趣的,但几乎肯定是一个不好的方法来做到这一点。

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

总的来说,我跟你原来的方法(正如其他人所指出的,可没有这么多的混乱,如果你已经自动装箱为Java 5中引入完成)同意。

请从第二种方法了,最好的办法是,如果你使用的是Java 1.5的自动装箱,什么前面你的第一个例子是最好的。

使用String方法的解决方案由于各种原因不太好。有些是美学原因,其他人是实用的。

实际上,更多的对象是通过String版本创建的,而不是更常规的形式(如您在第一个示例中所表达的)。

上的美学笔记,我认为第二个版本掩盖了代码的意图,这是几乎得到它产生你想要的结果一样重要。

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

  • "0"在编译时被转换成一个恒定字符串对象。
  • 每次调用此代码时,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.parseInt无论如何,内部电话new Integer(),因为Integer是不可变的。

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

上面的工具包的答案是正确的,也是最好的方法,但它并没有给出正在发生的事情的完整解释。 假设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 

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