Java 对两个向量求和的参考可变性
References Mutability in Java summing two vectors
我是 Java 的新手,我正在学习 class,但是在其中一个练习中,我在比较我的答案与老师的答案时产生了疑问。
假设我有一个 class 将多项式的系数保存为属性,我现在想添加两个多项式。
在老师的解决方案(方法add_1)中,他复制了两个数组的系数求和,但是据我所知,到目前为止,双精度数是不可变的,所以我认为我不需要使用副本,但只能直接使用地址(方法 add_2)。我已经测试了我在数组中的值没有发生变化,但是我想确认我的理解。
public class Polynomial {
// coefficient at index k belongs to term x^k
// consistency: array is always present and contains at least one number (which
// may be zero)
private double[] coefficients;
// --------------------- constructors
// ----------------------------------------------
// constructor: zero polynomial
public Polynomial() {
coefficients = new double[1];
coefficients[0] = 0;
}
public static Polynomial add_1(Polynomial f, Polynomial g) { // Option 1
double[] f_array = f.getCoefficients();//Do I need this copy?
double[] g_array = f.getCoefficients();//Do I need this copy?
int n = Math.max(f_array.length, g_array.length); // new array needs to be this long
double[] target = new double[n];
// fastest way to do it without if-statements:
for (int k = 0; k < n; k = k + 1) {
target[k] = 0;//Zero vector array
}
for (int k = 0; k < f_array.length; k = k + 1) {
target[k] = target[k] + f_array[k];
}
for (int k = 0; k < g_array.length; k = k + 1) {
target[k] = target[k] + g_array[k];
}
// Turn array into an object
Polynomial p = new Polynomial();
p.setCoefficients(target);
return p;
}
public static Polynomial add_2(Polynomial f, Polynomial g) { // Option 2
int n = Math.max(f_array.length, g_array.length); // new array needs to be this long
double[] target = new double[n];
// fastest way to do it without if-statements:
for (int k = 0; k < n; k = k + 1) {
target[k] = 0;//Zero vector array
}
for (int k = 0; k < f.coefficients.length; k = k + 1) {
target[k] = target[k] + f.coefficients[k];
}
for (int k = 0; k < g.coefficients.length; k = k + 1) {
target[k] = target[k] + g.coefficients[k];
}
// Turn array into an object
Polynomial p = new Polynomial();
p.setCoefficients(target);
return p;
}
// --------------------- setter / getter methods
// -----------------------------------
// setter for coefficients, creates a copy(!) of coefficients and stores it
public void setCoefficients(double[] coefficients) {
this.coefficients = new double[coefficients.length];
for (int k = 0; k < coefficients.length; k = k + 1) {
this.coefficients[k] = coefficients[k];
}
}
// getter for coefficients, returns a copy(!) of the polynomials coefficients
public double[] getCoefficients() {
double[] copy = new double[coefficients.length];
for (int k = 0; k < coefficients.length; k = k + 1) {
copy[k] = coefficients[k];
}
return copy;
}
}
- 我的方法 add_2 是否受到保护以防止突变,或者我是否有任何理由应该使用副本?
非常感谢
double[] f_array = f.getCoefficients();//Do I need this copy?
这掩盖了对 java 的误解。
f.getCoefficients()
不是 return 双数组。那是不可能的; java 只能 return 基元和引用。它return是对双数组的引用。
这里没有复制数组。 java 隐式制作的唯一副本是引用和基元;任何其他复制都是您必须明确使用的内容,例如copy()
或 clone()
或 Arrays.copyOf
调用。您在这里所做的只是复制了一份 参考文献,这无关紧要。 f.getCoefficients()
已经 return 引用的副本。
让我试着用一个例子来解释:
class Example {
double[] array = new double[10];
public static void main(String[] args) {
Example ex = new Example();
double[] arr = ex.array;
arr[0] = 1;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
ex.array[0] = 2;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
arr = new double[20];
arr[0] = 20;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
}
}
> 1
> 1
> 2
> 2
> 20
> 2
最初只有一个数组,ex.array
和arr
都是指向这个数组的引用。 arr[0] =
正在取消引用引用并对您在那里找到的内容进行操作,因此,虽然 arr
和 ex.array
是副本,但它是同一引用的副本,就像我做一张藏宝图副本交给你,如果你跟着你的地图,挖下去,偷走宝藏,然后我跟着我的副本,我发现宝藏不见了 - 所以它在这里:arr[0] = 1
影响唯一数组,因此打印 ex.array[0[]
也显示 1
.
后来用arr = new double[20]
我们先新建一个对象(new double[20]
),然后把这个新建对象的引用赋值给arr
,对ex.array
。因此,现在,就好像你有一张与我的 ex.array
藏宝图完全不同的藏宝图。因此,当你按照你的地图向下挖掘并在框中放一个 20
时,如果我按照我的地图,我 不会 看到它,因此为什么最后 2行打印 20
和 1
,而不是 20
和 20
.
我是 Java 的新手,我正在学习 class,但是在其中一个练习中,我在比较我的答案与老师的答案时产生了疑问。
假设我有一个 class 将多项式的系数保存为属性,我现在想添加两个多项式。
在老师的解决方案(方法add_1)中,他复制了两个数组的系数求和,但是据我所知,到目前为止,双精度数是不可变的,所以我认为我不需要使用副本,但只能直接使用地址(方法 add_2)。我已经测试了我在数组中的值没有发生变化,但是我想确认我的理解。
public class Polynomial {
// coefficient at index k belongs to term x^k
// consistency: array is always present and contains at least one number (which
// may be zero)
private double[] coefficients;
// --------------------- constructors
// ----------------------------------------------
// constructor: zero polynomial
public Polynomial() {
coefficients = new double[1];
coefficients[0] = 0;
}
public static Polynomial add_1(Polynomial f, Polynomial g) { // Option 1
double[] f_array = f.getCoefficients();//Do I need this copy?
double[] g_array = f.getCoefficients();//Do I need this copy?
int n = Math.max(f_array.length, g_array.length); // new array needs to be this long
double[] target = new double[n];
// fastest way to do it without if-statements:
for (int k = 0; k < n; k = k + 1) {
target[k] = 0;//Zero vector array
}
for (int k = 0; k < f_array.length; k = k + 1) {
target[k] = target[k] + f_array[k];
}
for (int k = 0; k < g_array.length; k = k + 1) {
target[k] = target[k] + g_array[k];
}
// Turn array into an object
Polynomial p = new Polynomial();
p.setCoefficients(target);
return p;
}
public static Polynomial add_2(Polynomial f, Polynomial g) { // Option 2
int n = Math.max(f_array.length, g_array.length); // new array needs to be this long
double[] target = new double[n];
// fastest way to do it without if-statements:
for (int k = 0; k < n; k = k + 1) {
target[k] = 0;//Zero vector array
}
for (int k = 0; k < f.coefficients.length; k = k + 1) {
target[k] = target[k] + f.coefficients[k];
}
for (int k = 0; k < g.coefficients.length; k = k + 1) {
target[k] = target[k] + g.coefficients[k];
}
// Turn array into an object
Polynomial p = new Polynomial();
p.setCoefficients(target);
return p;
}
// --------------------- setter / getter methods
// -----------------------------------
// setter for coefficients, creates a copy(!) of coefficients and stores it
public void setCoefficients(double[] coefficients) {
this.coefficients = new double[coefficients.length];
for (int k = 0; k < coefficients.length; k = k + 1) {
this.coefficients[k] = coefficients[k];
}
}
// getter for coefficients, returns a copy(!) of the polynomials coefficients
public double[] getCoefficients() {
double[] copy = new double[coefficients.length];
for (int k = 0; k < coefficients.length; k = k + 1) {
copy[k] = coefficients[k];
}
return copy;
}
}
- 我的方法 add_2 是否受到保护以防止突变,或者我是否有任何理由应该使用副本?
非常感谢
double[] f_array = f.getCoefficients();//Do I need this copy?
这掩盖了对 java 的误解。
f.getCoefficients()
不是 return 双数组。那是不可能的; java 只能 return 基元和引用。它return是对双数组的引用。
这里没有复制数组。 java 隐式制作的唯一副本是引用和基元;任何其他复制都是您必须明确使用的内容,例如copy()
或 clone()
或 Arrays.copyOf
调用。您在这里所做的只是复制了一份 参考文献,这无关紧要。 f.getCoefficients()
已经 return 引用的副本。
让我试着用一个例子来解释:
class Example {
double[] array = new double[10];
public static void main(String[] args) {
Example ex = new Example();
double[] arr = ex.array;
arr[0] = 1;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
ex.array[0] = 2;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
arr = new double[20];
arr[0] = 20;
System.out.println(arr[0]);
System.out.println(ex.array[0]);
}
}
> 1
> 1
> 2
> 2
> 20
> 2
最初只有一个数组,ex.array
和arr
都是指向这个数组的引用。 arr[0] =
正在取消引用引用并对您在那里找到的内容进行操作,因此,虽然 arr
和 ex.array
是副本,但它是同一引用的副本,就像我做一张藏宝图副本交给你,如果你跟着你的地图,挖下去,偷走宝藏,然后我跟着我的副本,我发现宝藏不见了 - 所以它在这里:arr[0] = 1
影响唯一数组,因此打印 ex.array[0[]
也显示 1
.
后来用arr = new double[20]
我们先新建一个对象(new double[20]
),然后把这个新建对象的引用赋值给arr
,对ex.array
。因此,现在,就好像你有一张与我的 ex.array
藏宝图完全不同的藏宝图。因此,当你按照你的地图向下挖掘并在框中放一个 20
时,如果我按照我的地图,我 不会 看到它,因此为什么最后 2行打印 20
和 1
,而不是 20
和 20
.