如何将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);
的是无论以哪种方式做任何优点?
在这种情况下,一般情况下最有效/最新的方法是什么?
使用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
你可以看到, “我”的内存地址没有改变,即使我们使用反射改变了它的值。
(请不要在实际生活中使用这种反射方式!)
我还建议你检查一下使用Integer是否真的需要。 Joshua指出在有效Java中使用原语要快很多倍。所以,如果可以的话,坚持** int **。 – 2008-09-05 15:54:56
使用Integer实际上是一个设计约束。这个想法是我得到一个Integer对象,我必须更新它。所以,不能取消:) – Jagmal 2008-09-05 17:40:24