为什么Java中的最终实例类变量?

abi*_*rai 14 java final

如果实例变量设置为final,则其值不能更改为

public class Final {

    private final int b;

    Final(int b) {
        this.b = b; 
    }

    int getFinal() {
        return  b = 8;  // COMPILE TIME ERROR 
    }
}
Run Code Online (Sandbox Code Playgroud)


在代码的某处我看到实例类变量 HashMap被 声明为final

 private  final Map<String, Object> cacheMap = new HashMap<String, Object>();
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这样宣布?通常在这种情况下它被声明.这是否意味着如果我放入哈希映射然后我无法更改其值?

编辑:
如果声明为final的cacheMap作为参数传递给另一个类,那么如果我更改其引用,则不会显示final的错误.为什么会这样?

 class CacheDTO {

    private Map conditionMap;

    public Map getConditionMap() {
        return conditionMap;
    }

    public void setConditionMap(Map conditionMap) {
        this.conditionMap = conditionMap;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后

private  final Map<String, Object> cacheMap = new HashMap<String, Object>();
CacheDTO cc = new CacheDTO();
cc.setConditionMap(cacheMap);
Map<String, Object> cacheMapDeclaredAsFinal = cc.getConditionMap();
Map<String, Object> newMap = new HashMap<String, Object>();
cacheMapDeclaredAsFinal = newMap;    // In this case no error is shown. Though cacheMapDeclaredAsFinal reference is obtained by calling cc.getConditionMap() and cacheMapDeclaredAsFinal refers to final.
Run Code Online (Sandbox Code Playgroud)

Sur*_*tta 33

你不能改变篮子.你仍然可以改变里面的水果.

来自语言规范#14.12.4

一旦分配了最终变量,它总是包含相同的值.如果最终变量包含对对象的引用,则可以通过对对象的操作来更改对象的状态,但该变量将始终引用同一对象.

声明a fieldreference final时,必须在构造函数退出时设置一次值.

您只能在构造函数中为该变量赋值.

 private  final Map<String,Object> CacheMap = new HashMap<String,Object>();
Run Code Online (Sandbox Code Playgroud)

在这里你可以做到

CacheMap.put(.....  
Run Code Online (Sandbox Code Playgroud)

在课堂上.

但你做不到

CacheMap =   something.  //compile error.
Run Code Online (Sandbox Code Playgroud)

你应该知道的区别valuereference.

编辑

这里

 Map<String, Object> cachemapdeclaredasfinal = cc.geConditionMap();

 Map<String, Object> newMap = new HashMap<String, Object>();

 cachemapdeclaredasfinal  = newMap; // In this case no error is shown
Run Code Online (Sandbox Code Playgroud)

原因,

由于 cachemapdeclaredasfinal 不是新地图,因此它是另一个参考 conditionMap

当你创建这样的新实例时

   Map<String, Object> cachemapdeclaredasfinal =
                                new HashMap<String, Object>(cc.geConditionMap());
Run Code Online (Sandbox Code Playgroud)

那个错误消失了.既然你用了新的.

编辑2:

 private Map conditionMap;

 public void setConditionMap(Map ConditionMap) {
        this.conditionMap = conditionMap;
    }
  private  final Map<String, Object> CacheMap = new HashMap<String, Object>();
  CacheDto cc = new CacheDto();
  cc.setConditionMap(CacheMap);
  Map<String, Object> cachemapdeclaredasfinal = cc.geConditionMap();
  Map<String, Object> newMap = new HashMap<String, Object>();
 cachemapdeclaredasfinal  = newMap;
Run Code Online (Sandbox Code Playgroud)

在这里,你困惑的是.

您正在分配一个final声明map为正常(非final)的声明map.当您检索到该正常时,只有您正在获取而不是final那样您可以assign进一步使用/ 它.

简而言之

normalMap= finalMap; //no error since normalMap is not final
finalMap =normalMap;// compiler error since normalMap is final
Run Code Online (Sandbox Code Playgroud)

  • @RandomGuy你现在只告诉我`最终变量是常数不能改变'.docs说`如果一个final变量持有一个对象的引用,那么对象的状态可能会被对象上的操作改变,但是变量总是引用同一个对象.所以引用状态可以改变.不是整个参考. (3认同)

Mar*_*nik 16

final与变量所指的对象的内容无关.您将无法更改变量的值并使其引用另一个对象.