int vs Integer vs用户创建的类在Java中实现有效的引用传递行为

int vs Integer vs用户创建的类在Java中实现有效的引用传递行为,java,integer,int,pass-by-reference,pass-by-value,Java,Integer,Int,Pass By Reference,Pass By Value,假设有一类对象有三个 要更改的整型字段,所有字段都以相同的方式使用一个方法进行更改 让我们简单地说,该方法所做的就是向传递给它的参数添加1 也就是说,期望的行为是,在方法完成时,相关字段增加了1 在Java中,使用这些字段的基本类型“int”无法实现这一点。 我知道Java如何“始终”按值传递,而不是按引用传递, -而且-我在互联网上听到了一些耳语,这是Integer类和其他对象“包装器”类存在的原因之一 对于通常的基本类型,如int和double 从理论上讲,将对象作为参数发送给方法应该提供一

假设有一类对象有三个 要更改的整型字段,所有字段都以相同的方式使用一个方法进行更改

让我们简单地说,该方法所做的就是向传递给它的参数添加1

也就是说,期望的行为是,在方法完成时,相关字段增加了1

在Java中,使用这些字段的基本类型“int”无法实现这一点。
我知道Java如何“始终”按值传递,而不是按引用传递, -而且-我在互联网上听到了一些耳语,这是Integer类和其他对象“包装器”类存在的原因之一 对于通常的基本类型,如int和double

从理论上讲,将对象作为参数发送给方法应该提供一种[有效地,如果不是技术上的]按引用传递的方法,因为传递的值被认为是对对象的引用的值。 非常棘手。但是——这就是我的烦恼所在——我已经尝试通过传递一个整数参数而不是一个 int,并且预期的行为仍然没有实现。1未添加到相关字段

然而,当我创建自己的对象时,它只包含一个字段,一个int值,并将这个对象的一个实例作为参数传递 对于一个只需向传递的参数添加1的适当方法,所需的行为实际上已经完成。1已添加到相关字段

所以围绕这个查询的问题是-是否真的有必要设计我自己的自制类来携带一个简单的整数值 每次我想要达到这个期望的行为?Java提供的现有工具Integer真的不能执行这个简单的任务吗

我没有一个好的、简洁的方法来处理我在开始时提到的所有三个假设的整数字段,我觉得有必要(在一个单独的、类似的项目中,最终引发了这种思路)创建一个单独的方法,对应于这三个字段中的每一个,每个字段中的代码基本相同。这似乎效率很低

从表面上看,写三个类似的方法而不是一个方法似乎没什么大不了的,但为了澄清为什么这让我感到沮丧——想象一下,不是像我说的那样,一个有三个整型字段的对象,而是说,我不知道,四千个。如果只写一件事情来执行相同的行为,而不是复制和粘贴(以及更改任何必要的小块内容)四千次,那会好得多

所以我想最终的问题是, 为什么整数不能以合理的方式起作用?如果一个基本体不能帮助执行如此简单的操作,那么在一个对象中包装一个基本体有什么意义呢?我是否遗漏了一些简单的关于如何让Integer以期望的方式运行的内容?(希望如此)答案似乎很接近,但令人愤怒地遥不可及,因为“RInteger”产生了所需的行为,而“Integer”却没有

下面是我在试图找出如何构造这个棘手问题时使用的全部源代码

package r9mp;

import javax.swing.SwingUtilities;

public class RefTest2 {
//[main m]
public static void main(String[] args){
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            new RefTest2();
        }
    });
}
//[fields]
int i;
Integer I;
RInteger RI;

//[constr]
public RefTest2(){
    intTest();
    IntegerTest();
    RIntegerTest();

    display();
}

//[methods]
private void intTest(){
    i = 100;
    intMethod(i);
}
private void IntegerTest(){
    I = 100;  //boxing? auto?
    IntegerMethod(I);
    I = 100; //just in case.
    IntegerMethod2(I);
}
private void RIntegerTest(){
    RI = new RInteger(100);
    RIntegerMethod(RI);
}

private void intMethod(int ipar){
    ipar = ipar + 1;//no change. expected.
}
private void IntegerMethod(Integer IPar){
    IPar = IPar + 1;//no change. frustrating.
    pln("From inside IntegerMethod: IPar = " + IPar );
    pln("From inside IntegerMethod: I = " + I );
}
private void IntegerMethod2(Integer IPar){
    IPar = new Integer(IPar+1);//still no change.  there are no set methods for Integer, or I'd try them.
}
private void RIntegerMethod(RInteger riPar){
    riPar.value = riPar.value + 1;
}

private void display(){
    pln(
            "Display...    \n" +
            "i: "  + i  + "\n" +
            "I: "  + I  + "\n" +
            "RI: " + RI + "\n" +
            "--------"
            );
}

private void pln(){
    pln("");
}
private void pln(String s){
    System.out.println(s);
}

//[internal class]
private class RInteger{
    int value;
    public RInteger(int v){
        value = v;
    }
    public String toString(){
        return ""+value;

    }
}

}

这里是输出…

首先,您需要阅读有关不变性的内容,以了解为什么拥有不变性是一件非常好的事情。甚至存在利用它的完整语言(功能性的,大部分)

一旦你读到了这方面的内容,那么请阅读Eric Lippert关于不变性的系列文章。从这里开始:头脑=崩溃

但是为了给你一个简单的提示,为什么像
Integer
这样的原始包装器是不可变的,让我说这些类经常被用作散列映射中的键,并且一个键必须是不可变的,这样它的
hashCode
就永远不会改变,否则散列映射将失败,并且很难跟踪行为。hashmaps中的可变键是令人讨厌的bug

您可以使用自己设计的充当引用的类来实现所需的功能,或者只需传递数组并在
array[0]
处修改元素即可

我个人的喜好如下:

  • 我会尽可能多地使用返回值
  • 当返回值不适用时(与
    invokeLater
    的情况一样),我的下一个首选项是可以访问封闭类字段的内部/嵌套/匿名类
  • 如果这也不是一个选项,那么我的下一个选项就是为手头的应用程序精心设计的特殊类。(
    MyMutableNumberRapper
  • 当我只想要一些快速而肮脏的东西时,像
    Ref
    (甚至是单元素数组)这样的通用类将是我的最终选择

原语及其包装器的一种方法如何

private int incInteger(int value)
{
    return value + 1;       
}
并呼吁:

int intVal = 100;
intVal = incInteger(intVal);

Integer integerVal = 200;
integerVal = incInteger(integerVal);

嗨,Ryan,您似乎以一种奇怪的方式使用Java类
RefTest2
。通常,该类将具有更新的字段。所以setter方法变量是按引用传递还是按值传递并不重要,因为我们只将它们用作传递信息的只读字段。如果您想编写一个具有副作用的方法(这已经很糟糕),那么就使用数组。非常明显的解决方法。由于
Integer
是不可变的,因此它的行为方式基本上与
int
相同,即将其传递给方法并对其进行更改。您不能更改
整数
中的值,只能创建新实例,然后覆盖传递的值并保留以前的引用。您写入字段,但从未实际读取字段。这是故意的吗?我不清楚你期望发生什么。也许你对Integer的“期望”行为不是很多人想要的?或者对许多人来说是不受欢迎的