final 和其他 Java 關鍵字 - 1

“嗨,阿米戈!”

“嗨,比拉博!”

“今天,我將向您介紹 Java 中的幾個關鍵字。但我將從最有趣的關鍵字開始:關鍵字 final。

“在聲明變量、方法或類時可以使用關鍵字final 。”

“為什麼我們需要final?”

“這很簡單。如果我們將一個變量標記為最終變量,那麼它就變得不可更改了:”

final int i = 5;
i++; //Compilation error: the value of i cannot be changed.

“我懂了。”

“如果我們將方法標記為 final,則禁止在派生類中覆蓋該方法:”

class Cat
{
 public final String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat
{
 public String getName() //Compilation error: overriding the getName()
 {
  return "tiger";
 }
}

“我明白了。但是為什麼你需要禁止覆蓋一個方法呢?”

“嗯,舉個例子,假設一個程序員在一個方法中寫了很多重要的代碼,並且想保證所有繼承他的類的類都具有指定的行為。”

“最後,第三種用法。”

“如果我們用關鍵字 final 標記一個類,那麼它就不能被繼承。”

public final class Cat
{
 public String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat //Compilation error: the Cat class cannot be
{
 public String getName()
 {
  return "tiger";
 }
}

“為什麼我們要阻止一個類被繼承?”

“你應該明白,我們阻止繼承並不是為了煩人,而是為了安全和代碼完整性。如果不禁止類繼承,那麼暗示它是允許的。而且類的編寫的代碼設計器將適用於此類的對像以及任何派生類的對象。”

“但是,如果開發人員意識到即使對他的類進行微小的更改也會導致一切按預期停止工作,那麼最好禁止繼承。”

“例如,String 類被聲明為 final,所有原始類型也是如此:Integer、Boolean、Double、Character……”

“啊,明白了。String 類是作為不可變類創建的,如果它們突然可變,那麼很多東西都會停止工作。”

“好吧,差不多。這麼說吧:一切都會像以前一樣工作,但有時會出現很難發現和理解的錯誤。所以,在某些情況下,繼承類或方法並不是真正的罪過,但禁止它意味著以後要捕獲的錯誤更少。”

“你還能在哪裡使用final?”

“您可以在函數參數之前和方法中的變量之前使用 final。這是一個示例:”

public void setName(final String name)
{
 final String displayName = "Mr."+ name;
  …
 this.name = displayName;
}

“那有什麼意義呢?”

“嗯,有兩個。首先,如果我們想告訴其他開發人員這個值是一個特定的常量,而不僅僅是一個變量,我們就將一個變量聲明為 final。”

例如,我們要根據價格計算銷售稅:

public int getPriceNDS()
{
 final int NDS = 20;
 return this.price * NDS / 200;
}

“其次,我們在編寫本地或匿名內部類時需要這種類型的變量。我很快就會告訴你這些類型的類。但不是今天。”

“好吧,到目前為止還沒有什麼太複雜的事情。”

“請注意,只有變量變得不可更改,而不是它可能引用的對象。對象仍然可以更改。”

“其實我正想問問這個,而且沒有辦法讓對像不可變?”

“不,除非你寫一個不可變的類。”

“請注意,由於無法更改最終變量的值,因此您必須立即為其分配初始值。”

這段代碼將編譯 此代碼無法編譯
class Home
{
 private final int width = 200;
 private final int height = 100;

 public Home()
 {
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
 }
}

“但是,也就是說,Java 允許您將類的最終變量的初始化延遲到構造函數。”

這段代碼將編譯 此代碼無法編譯
class Home
{
 private final int width = 200;
 private final int height;

 public Home()
 {
  height = 100;
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
 }
}

“此外,不同的構造函數可以用不同的值初始化最終變量。這很方便:”

這段代碼將編譯
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
  width = 200;
 }

 public Home(int width)
 {
  this.height = 300;
  this.width = width;
 }

 public Home(int width, int height)
 {
  this.height = height;
  this.width = width;
 }
}

“這是一個非常有趣的話題,絕對一切都說得通。謝謝你,Bilaabo!”