定义 final 一个不可变参数,将参数绑定到另一个局部变量并改变局部变量是否合法?
Is it legitimate to define final an immutable parameter, bind the parameter to another local variable and mutate the local variable?
请注意:同样的问题适用于其他不可变类型,例如 String 和 Boolean。
我有一个这样的方法(这是一个更复杂方法的简单例子):
示例 1
public BigDecimal addTwo(BigDecimal bigDecimal) {
bigDecimal = bigDecimal.add(new BigDecimal(2));
return bigDecimal;
}
我知道,我可以 return bigDecimal.add(new BigDecimal(2))
。但这只是一个例子。
此代码的问题是我无法将 final
添加到方法参数中,Eclipse 困扰着我。所以我会写:
示例 2
public BigDecimal addTwo(final BigDecimal bigDecimal) {
BigDecimal bigDecimalLocal = bigDecimal;
bigDecimalLocal = bigDecimalLocal.add(new BigDecimal(2));
return bigDecimalLocal;
}
我知道,我可以直接做BigDecimal bigDecimalLocal = bigDecimal.add(new BigDecimal(2))
。但我再说一遍,这只是一个例子。
问题是:当我做的时候:
BigDecimal bigDecimalLocal = bigDecimal;
我不是创建一个新的BigDecimal
。我将同一个对象分配给不同的变量。我 克隆 BigDecimal
的简单方法是:
示例 3
BigDecimal bigDecimalLocal = new BigDecimal(bigDecimal.toString());
问题是:既然BigDecimal
是不可变的,这真的有必要吗?我不能像示例 #2 那样简单地做吗?我认为 final
关键字不能以这种方式失效。
看来你不明白引用的概念
当你有这个:
BigDecimal incoming = new BigDecimal(2);
addTwo(incoming);
...
public BigDecimal addTwo(BigDecimal bigDecimal) {
bigDecimal = bigDecimal.add(new BigDecimal(2));
}
事情是:incoming
在该方法结束后仍然是 2!
那个 add()
调用创建了一个 new BigDecimal 对象,然后变量 bigDecimal 指向那个新对象。
但是引用incoming
仍然指向旧对象!
长话短说:方法参数的关键字 final 根本 没有您想象的那样。它的唯一目的是防止你re-assigning到那个parameter/value。所以你真的很想了解 objects and references. And then about pass by reference.
之间的区别
示例 2 很好,但您根本不需要局部变量,我认为它们会降低方法的可读性。我会简单地做
public BigDecimal addTwo(final BigDecimal bigDecimal) {
return bigDecimal.add(BigDecimal.valueOf(2));
}
What if I want to add another BigDecimal"? I have to return bigDecimal.add(BigDecimal.valueOf(2).add(BigDecimal.valueOf(3))
? I think it's not so readable.
如果您要多次添加两个(或多个常量),那么提取常量作为常量可能是有意义的。喜欢,
private static final BigDecimal TWO = BigDecimal.valueOf(2);
private static final BigDecimal THREE = BigDecimal.valueOf(3);
public static BigDecimal addTwoAndThree(final BigDecimal bigDecimal) {
return TWO.add(THREE).add(bigDecimal);
}
好吧,我承认我对 final
关键字一无所知。我必须说我不明白它的用处:
如果在方法内部重新赋值一个参数,final
与否,对象不变,当然
如果您改为修改非不可变对象,final
或不修改,对象也会在方法之外更改。
似乎带有 final
的参数唯一能做的就是它不能仅在方法内重新分配。
我必须说我经常做这样的事情:
public List<MyBean> findByNation(String nation) {
if (nation != null) {
nation = nation.toUpperCase();
} else {
nation = "";
}
[...]
}
或
public List<Date> findConfirmedDates(Date start, Date end) {
if (end == null) {
end = new Date();
}
}
或
public String findFilteredSql(String queryFilter, SearchBean searchBean) {
if (searchBean.getSupplierId() != null) {
queryFilter += " JOIN SUPPLIER_COMMODITY sc ON sc.SUPPLIERID = v.SUPPLIERID ";
}
[...]
}
或
public static String format(BigDecimal val, Locale locale, int scale) {
if (val == null) {
return "-";
}
val = valLocal.subtract(BigDecimal.ONE);
val = val.multiply(NumberUtility.BigDecimal100);
[...]
}
是的,在大学里我了解到,如果我创建一个新变量,而不是覆盖旧变量,程序的速度会提高(我记不太清楚了,在我看来 CPU 和寄存器以某种方式参与......)。无论如何,这是 micro-optimizations,对进行数字计算的 C 或 Fortran 库很有用。
恕我直言,我编写上述方法的方式更具可读性,对不起 final
。
所以我没有发现 final
在这些情况下的实用性。而且,我根本不觉得它有用。我想我会采用问题中的示例 #1,我会简单地禁用 Eclipse 的警告,并且不添加这个可以说有用的关键字。
请注意:同样的问题适用于其他不可变类型,例如 String 和 Boolean。
我有一个这样的方法(这是一个更复杂方法的简单例子):
示例 1
public BigDecimal addTwo(BigDecimal bigDecimal) {
bigDecimal = bigDecimal.add(new BigDecimal(2));
return bigDecimal;
}
我知道,我可以 return bigDecimal.add(new BigDecimal(2))
。但这只是一个例子。
此代码的问题是我无法将 final
添加到方法参数中,Eclipse 困扰着我。所以我会写:
示例 2
public BigDecimal addTwo(final BigDecimal bigDecimal) {
BigDecimal bigDecimalLocal = bigDecimal;
bigDecimalLocal = bigDecimalLocal.add(new BigDecimal(2));
return bigDecimalLocal;
}
我知道,我可以直接做BigDecimal bigDecimalLocal = bigDecimal.add(new BigDecimal(2))
。但我再说一遍,这只是一个例子。
问题是:当我做的时候:
BigDecimal bigDecimalLocal = bigDecimal;
我不是创建一个新的BigDecimal
。我将同一个对象分配给不同的变量。我 BigDecimal
的简单方法是:
示例 3
BigDecimal bigDecimalLocal = new BigDecimal(bigDecimal.toString());
问题是:既然BigDecimal
是不可变的,这真的有必要吗?我不能像示例 #2 那样简单地做吗?我认为 final
关键字不能以这种方式失效。
看来你不明白引用的概念
当你有这个:
BigDecimal incoming = new BigDecimal(2);
addTwo(incoming);
...
public BigDecimal addTwo(BigDecimal bigDecimal) {
bigDecimal = bigDecimal.add(new BigDecimal(2));
}
事情是:incoming
在该方法结束后仍然是 2!
那个 add()
调用创建了一个 new BigDecimal 对象,然后变量 bigDecimal 指向那个新对象。
但是引用incoming
仍然指向旧对象!
长话短说:方法参数的关键字 final 根本 没有您想象的那样。它的唯一目的是防止你re-assigning到那个parameter/value。所以你真的很想了解 objects and references. And then about pass by reference.
之间的区别示例 2 很好,但您根本不需要局部变量,我认为它们会降低方法的可读性。我会简单地做
public BigDecimal addTwo(final BigDecimal bigDecimal) {
return bigDecimal.add(BigDecimal.valueOf(2));
}
What if I want to add another BigDecimal"? I have to return
bigDecimal.add(BigDecimal.valueOf(2).add(BigDecimal.valueOf(3))
? I think it's not so readable.
如果您要多次添加两个(或多个常量),那么提取常量作为常量可能是有意义的。喜欢,
private static final BigDecimal TWO = BigDecimal.valueOf(2);
private static final BigDecimal THREE = BigDecimal.valueOf(3);
public static BigDecimal addTwoAndThree(final BigDecimal bigDecimal) {
return TWO.add(THREE).add(bigDecimal);
}
好吧,我承认我对 final
关键字一无所知。我必须说我不明白它的用处:
如果在方法内部重新赋值一个参数,
final
与否,对象不变,当然如果您改为修改非不可变对象,
final
或不修改,对象也会在方法之外更改。似乎带有
final
的参数唯一能做的就是它不能仅在方法内重新分配。
我必须说我经常做这样的事情:
public List<MyBean> findByNation(String nation) {
if (nation != null) {
nation = nation.toUpperCase();
} else {
nation = "";
}
[...]
}
或
public List<Date> findConfirmedDates(Date start, Date end) {
if (end == null) {
end = new Date();
}
}
或
public String findFilteredSql(String queryFilter, SearchBean searchBean) {
if (searchBean.getSupplierId() != null) {
queryFilter += " JOIN SUPPLIER_COMMODITY sc ON sc.SUPPLIERID = v.SUPPLIERID ";
}
[...]
}
或
public static String format(BigDecimal val, Locale locale, int scale) {
if (val == null) {
return "-";
}
val = valLocal.subtract(BigDecimal.ONE);
val = val.multiply(NumberUtility.BigDecimal100);
[...]
}
是的,在大学里我了解到,如果我创建一个新变量,而不是覆盖旧变量,程序的速度会提高(我记不太清楚了,在我看来 CPU 和寄存器以某种方式参与......)。无论如何,这是 micro-optimizations,对进行数字计算的 C 或 Fortran 库很有用。
恕我直言,我编写上述方法的方式更具可读性,对不起 final
。
所以我没有发现 final
在这些情况下的实用性。而且,我根本不觉得它有用。我想我会采用问题中的示例 #1,我会简单地禁用 Eclipse 的警告,并且不添加这个可以说有用的关键字。