【发布时间】:2017-06-14 01:49:55
【问题描述】:
假设你有一个包含三个对象的类 您希望使用一种方法以相同方式更改的整数字段。
让我们保持简单,并说该方法所做的只是将传递给它的参数加 1。
也就是说,期望的行为是,当方法完成时,相关字段已经增加了 1。
在 Java 中,这些字段使用原始类型“int”是不可能实现的。
我知道 Java 如何“总是”按值传递,而不是按引用传递,
- 并且 - 我在互联网上听到耳语说这是 Integer 类以及其他对象“包装器”类存在的原因之一
对于通常的原始类型,例如 int 和 double。
理论上,将对象作为参数发送给方法应该提供一种[有效地,如果不是技术上]通过引用传递的方法,因为传递的值应该是对对象的引用的值。 非常棘手。但是——这就是我烦恼的地方——我尝试通过传递一个整数参数而不是一个 int,但仍没有实现所需的行为。 1 未添加到相关字段。
然而,当我创建我自己的对象时,它只包含一个字段,一个 int 值,并将该对象的一个实例作为参数传递 对于一个简单地将 1 添加到传递的参数的适当方法,实际上已经实现了所需的行为。 1 已添加到相关字段。
所以围绕这个查询的问题是——真的有必要制作我自己的自制类来携带一个简单的整数值 每次我想实现这种期望的行为? Java提供的现有工具Integer真的不能完成这个简单的任务吗?
我没有用一种很好的、简洁的方法来处理我在开头提到的所有三个假设的整数字段,而是觉得有必要(在一个单独的、类似的项目中,最终引发了这种思路)制作一个单独的方法来对应到三个字段中的每一个,每个字段中的代码基本相同。这似乎效率很低。
从表面上看,编写三个类似的方法而不是一个似乎没什么大不了的,但要澄清为什么这让我感到沮丧 - 想象一下,而不是像我所说的那样具有三个整数字段的对象,有人说,我不知道,四千。最好只写一件东西来执行相同的行为,而不是复制和粘贴(以及更改任何必要的小部分)四千次。
所以我想最终的问题是, 为什么 Integer 不能以合理的方式运行?如果它甚至不能帮助执行这么简单的事情,那么将原语包装在 Object 中的意义何在?我是否遗漏了一些关于如何让 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;
}
}
}
【问题讨论】:
-
嗨,Ryan,您似乎正在以一种奇怪的方式使用您的 Java 类
RefTest2。通常,该类将具有更新的字段。因此,setter 方法变量是通过引用传递还是通过值传递并不重要,因为我们只将它们用作传递信息的只读字段。 -
如果你想写一个有副作用的方法(这已经很糟糕了),那么使用数组。很明显的解决方法。
-
由于
Integer是不可变的,它在将其传递给方法并对其进行更改方面基本上与int的行为方式相同。您无法更改Integer中的值,您只能创建新实例,然后覆盖传递的值并保留先前的引用。 -
您写入字段,但您从未真正读取它们。这是故意的吗?我不清楚你期望发生什么。
-
也许很多人不希望您对 Integer 的“期望”行为?还是对许多人来说是不受欢迎的?
标签: java integer int pass-by-reference pass-by-value