我制作了一个Point类来管理xy坐标(我知道一些Java默认程序包已经具有一些以类似方式运行的Point对象,我将其用作惰性选择,这是一个示例,请不要介意^^ )。
在使用它之前,我使用的是int基本类型。
事情是,当将类或原始类型作为方法的参数传递时,两者的行为方式不同,如果我在方法中更改原始变量的值,则原始变量不会受到影响,这与我使用的是对象,因为它是作为参数传递的引用。
我的问题是,由于我使用Point进行数学运算(下面的示例),因此我必须手动创建新对象以保存结果,并且我从不使用它在两个变量之间建立“链接”,就像对象行为一样通常。
我的积分课程:
public class Point {
public int x;
public int y;
public Point(int nx, int ny) {
this.x = nx;
this.y = ny;
}
public Point() {
this(0, 0);
}
}
方法示例:
public Point getAdjacent(int x, int y, Direction dir) {
Point pt = new Point(x, y);//basically, i would like to do that automatically
switch (dir) {
case Up:
pt.y -= 1;
break;
case Down:
pt.y += 1;
break;
case Right:
pt.x -= 1;
break;
case Left:
pt.x += 1;
break;
default:
//do nothing
}
return pt;
}
总而言之,是否可以使Point表现得像原始类型?
编辑:我的意思是当它作为参数传递或执行point1 = point2
时,它将自动复制它答案 0 :(得分:1)
首先::请确保在切换代码中使用break语句。否则,当大小写匹配时,切换块将“掉线”并执行:
pt.y -= 1;
pt.y += 1;
pt.x -= 1;
pt.x += 1;
(参考:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html)
根据问题,您确实可以使用Point类。下面的代码将:
1.使用一个点作为输入。
2.从输入Point中将变量x和y提取到复制基元中。
3.更改复制的基元。
4.根据副本创建一个新的Point。
这样,“旧”点将保持不变。
public Point getAdjacent(final Point point, final Direction dir) {
int x = point.x;
int y = point.y;
switch (dir) {
case Up:
y -= 1;
break;
case Down:
y += 1;
break;
case Right:
x -= 1;
break;
case Left:
x += 1;
break;
default:
break;
}
return new Point(x, y);
}
答案 1 :(得分:0)
这个问题可能有点太广泛了,因为人们可能会对“行为”一词的含义进行广泛的争论。但是在某种程度上,我们可以解决这个问题:
最短的答案可能是:否,这不可能。
一个更为详尽的答案可能是:不,还还不可能让一个类(或更确切地说是一个对象)表现得像一个原始值。
长答案:
我们正在努力实现可能与您要实现的目标接近的行为。此处的相关关键字是值类型。
一些资源:
但是,当前版本的Java和JVM不支持此功能,并且可能需要一段时间才能整理出详细信息。
直到那时,仍有一些可行的解决方法可以实现预期的目标。
最简单的解决方案是您已经提出的解决方案:您总是返回一个新实例,而不是修改给定的对象。
您在问题中显示的示例可能不是最好的例子,因为您显示的方法getAdjacent
实际上可能是static
方法。它不使用以任何方式调用它的实例。
然后,您始终可以确定每次修改都收到一个新实例。否则,请想象以下代码片段:
Point a = new Point(1,2);
Point b = new Point(3,4);
a.add(b);
System.out.println(a); // What does this print?
取决于add
方法的实现,其行为可能不清楚。如果是这样实现的:
public void add(Point other) {
this.x += other.x;
this.y += other.y;
}
然后将修改点a
,输出将为(4,6)
。
但是如果是这样实现的
public Point add(Point other) {
return new Point(this.x+other.x, this.y+other.y);
}
然后a
不会受到影响,并且输出仍然是(1,2)
。
通常,制作Point
不可变之类的东西基本上可以实施这种编程风格。因此,您可以在类x
中创建变量y
和final
,以便始终确保对象在创建后不能被修改:
public class Point {
// Note that these are FINAL:
private final int x;
private final int y;
public Point(int nx, int ny) {
this.x = nx;
this.y = ny;
}
...
}
对于类似Point
类(我在this answer中提到过的类)这样看似微不足道的东西,还有一些其他设计方面的考虑,但是讨论这些问题不在此答案的范围之内。 >