请注意:同一问题适用于其他不可变类型,例如String和Boolean。
我有一个像这样的方法(这是一个更复杂方法的简单示例):
public BigDecimal addTwo(BigDecimal bigDecimal) {
bigDecimal = bigDecimal.add(new BigDecimal(2));
return bigDecimal;
}
我知道,我可以简单地返回bigDecimal.add(new BigDecimal(2))
。但这只是一个例子。
此代码的问题是我无法将final
添加到方法参数中,并且Eclipse困扰了我。所以我会写:
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
。我将同一对象分配给不同的变量。我found on SO克隆BigDecimal
的简单方法是:
BigDecimal bigDecimalLocal = new BigDecimal(bigDecimal.toString());
问题是:由于BigDecimal
是不可变的,这真的必要吗?我不能像示例2那样简单吗?我认为final
关键字不能以这种方式无效。
答案 0 :(得分:1)
示例2很好,但是您根本不需要局部变量,我认为它们会降低方法的可读性。我只会做
public BigDecimal addTwo(final BigDecimal bigDecimal) {
return bigDecimal.add(BigDecimal.valueOf(2));
}
如果我想添加另一个BigDecimal,该怎么办?我必须返回
bigDecimal.add(BigDecimal.valueOf(2).add(BigDecimal.valueOf(3))
?我认为它不太可读。
如果要多次添加两次(或多个常量),则提取常量作为常量可能是有意义的。喜欢,
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);
}
答案 1 :(得分:0)
您似乎不了解引用的概念。
拥有此功能时:
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根本没有实现您认为的那样。其唯一目的是防止您重新分配该参数/值。因此,您真的想了解objects and references之间的区别。然后是pass by reference。
答案 2 :(得分:0)
好吧,我承认我对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和寄存器都在其中某种方式...)。无论如何,这都是微优化,对于执行数值计算的C或Fortran库很有用。
恕我直言,我编写上述方法的方式更具可读性,对final
感到抱歉。
因此,在这些情况下,我找不到final
的实用程序。而且,我根本没有发现它的用处。我想我将在问题中采用Example#1,并且我只会禁用Eclipse的警告,并且不会以有用的方式添加此关键字。