Java 如何通过引用正确传递整数类?
我希望有人能为我澄清这里发生了什么。我在integer类中搜索了一段时间,但是因为integer覆盖了Java 如何通过引用正确传递整数类?,java,integer,pass-by-reference,Java,Integer,Pass By Reference,我希望有人能为我澄清这里发生了什么。我在integer类中搜索了一段时间,但是因为integer覆盖了+操作符,所以我无法找出哪里出了问题。我的问题是这一行: Integer i = 0; i = i + 1; // ← I think that this is somehow creating a new object! 我的理由如下: 我知道java是按值传递的(),所以我认为在下面的示例中,integer对象应该每次递增 public class PassByReference {
+
操作符,所以我无法找出哪里出了问题。我的问题是这一行:
Integer i = 0;
i = i + 1; // ← I think that this is somehow creating a new object!
我的理由如下:
我知道java是按值传递的(),所以我认为在下面的示例中,integer对象应该每次递增
public class PassByReference {
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
public static void main(String[] args) {
Integer integer = new Integer(0);
for (int i =0; i<10; i++){
inc(integer);
System.out.println("main: "+integer);
}
}
}
公共类PassByReference{
公共静态整数公司(整数i){
i=i+1;//我想这一定是**偷偷地**创建一个新的整数。。。
系统输出打印项次(“Inc:+i”);
返回i;
}
公共静态void main(字符串[]args){
整数=新整数(0);
对于(int i=0;i有两个问题:
整数是按值传递的,而不是按引用传递的。更改方法内的引用不会反映到调用方法中传入的引用中
整数是不可变的。没有像Integer#set(i)
这样的方法。否则,您可以直接使用它
要使其工作,需要重新分配inc()
方法的返回值
integer = inc(integer);
要了解有关按值传递的更多信息,请参见另一个示例:
public static void main(String... args) {
String[] strings = new String[] { "foo", "bar" };
changeReference(strings);
System.out.println(Arrays.toString(strings)); // still [foo, bar]
changeValue(strings);
System.out.println(Arrays.toString(strings)); // [foo, foo]
}
public static void changeReference(String[] strings) {
strings = new String[] { "foo", "foo" };
}
public static void changeValue(String[] strings) {
strings[1] = "foo";
}
我想是自动包装把你甩了
这部分代码:
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
Integer i = 0;
i = i + 1;
实际上可以归结为如下代码:
public static Integer inc(Integer i) {
i = new Integer(i) + new Integer(1);
System.out.println("Inc: "+i);
return i;
}
这当然不会更改传入的引用
你可以用这样的东西来修复它
public static void main(String[] args) {
Integer integer = new Integer(0);
for (int i =0; i<10; i++){
integer = inc(integer);
System.out.println("main: "+integer);
}
}
publicstaticvoidmain(字符串[]args){
整数=新整数(0);
对于(int i=0;i您在这里看到的不是重载的+
运算器,而是自动装箱行为。Integer
类是不可变的,您的代码:
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
Integer i = 0;
i = i + 1;
编译器(在自动装箱之后)将其视为:
因此,您的结论是正确的,Integer
实例被更改了,但不是偷偷摸摸的-这与Java语言定义一致:-)如果您将inc()函数更改为
public static Integer inc(Integer i) {
Integer iParam = i;
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println(i == iParam);
return i;
}
然后您将看到它总是打印“false”。
这意味着加法将创建Integer的一个新实例,并将其存储在局部变量i(“local”,因为i实际上是传递的引用的副本)中,使调用方法的变量保持不变
Integer是一个不可变的类,这意味着您不能更改它的值,但必须获得一个新实例。在这种情况下,您不必像这样手动执行:
i = new Integer(i+1); //actually, you would use Integer.valueOf(i.intValue()+1);
相反,它是通过自动装箱完成的。整数是不可变的。您可以在自定义包装器类中包装int
class WrapInt{
int value;
}
WrapInt theInt = new WrapInt();
inc(theInt);
System.out.println("main: "+theInt.value);
你在这里是正确的:
Integer i = 0;
i = i + 1; // <- I think that this is somehow creating a new object!
整数i=0;
i=i+1;//通过引用传递有两种方法
从Apache Commons库中使用
创建自定义类,如下所示
下面是执行此操作的示例代码:
public class Test {
public static void main(String args[]) {
Integer a = new Integer(1);
Integer b = a;
Test.modify(a);
System.out.println(a);
System.out.println(b);
IntegerObj ao = new IntegerObj(1);
IntegerObj bo = ao;
Test.modify(ao);
System.out.println(ao.value);
System.out.println(bo.value);
}
static void modify(Integer x) {
x=7;
}
static void modify(IntegerObj x) {
x.value=7;
}
}
class IntegerObj {
int value;
IntegerObj(int val) {
this.value = val;
}
}
输出:
1
1
7
7
上面的回答很好,解释了OP中的实际问题
如果任何人需要传递需要全局更新的数字,请使用AtomicInteger(
),而不是创建建议的各种包装类或依赖第三方LIB
AtomicInteger(
)当然主要用于线程安全访问,但是如果性能没有问题,为什么不使用这个内置类呢?当然,额外的好处是明显的线程安全性
import java.util.concurrent.atomic.AtomicInteger
1)只有引用的副本作为值发送给形式参数。当形式参数变量被赋予其他值时,形式参数的引用将更改,但实际参数的引用在该整数对象中保持不变
公共类理解对象{
public static void main(String[] args) {
Integer actualParam = new Integer(10);
changeValue(actualParam);
System.out.println("Output " + actualParam); // o/p =10
IntObj obj = new IntObj();
obj.setVal(20);
changeValue(obj);
System.out.println(obj.a); // o/p =200
}
private static void changeValue(Integer formalParam) {
formalParam = 100;
// Only the copy of reference is set to the formal parameter
// this is something like => Integer formalParam =new Integer(100);
// Here we are changing the reference of formalParam itself not just the
// reference value
}
private static void changeValue(IntObj obj) {
obj.setVal(200);
/*
* obj = new IntObj(); obj.setVal(200);
*/
// Here we are not changing the reference of obj. we are just changing the
// reference obj's value
// we are not doing obj = new IntObj() ; obj.setValue(200); which has happend
// with the Integer
}
}
类IntObj{
整数a
public void setVal(int a) {
this.a = a;
}
}它不是真正的按值传递。它是引用的按值传递…因为对象唯一要传递的是内存地址。严格来说,对于引用是“按值传递引用”,对于原语是“按值传递引用”。那么,一个引用副本被发送到函数中。发送到函数的引用副本与发送到函数的引用有何不同?有什么显著的区别吗?BalusC已经搞定了,但这里有一个简单的解释。Java发送一个在函数堆栈上创建的引用副本。行字符串=新字符串[]{“foo”,“foo”};修改在changeReference(String[])本地堆栈上创建的引用的副本。调用函数main()会知道在其自身堆栈上创建的引用(而不是在changeReference()堆栈上创建的引用).huh,好吧,这很有趣。感谢自动装箱术语。不可变似乎也很关键。祝你周末愉快!你可以查看自动装箱。回到Java 1.4,你只能添加带整数的整数,或者带整数的整数。现在,你可以以任何方式做的事情都有点难以概念化,只看代码。相关问题:为什么是整数是否设置为不可变?@RahulJain不确定,我怀疑它与实际值类型(int
)一致,所以它们都有相同的语义。一致性是什么意思?int可以更改,但不能是整数,这是包装类的一个缺点。@RahulJainint
是一个基本类型。基本类型是不可变的。我怀疑你把不可变性和final
关键字混淆了-它们是不同的东西。你可以更改Integer
变量的引用(与int
变量的值相同)。它们非常一致。性能如何,它是否完好无损?显然,如果只需要AtomicInteger
通过引用传递,则线程安全不需要它。性能似乎与Integer相同(假设您只使用.set(),.get(),并且没有使用任何线程安全操作)。
public void setVal(int a) {
this.a = a;
}