final i inne słowa kluczowe Java - 1

"Cześć, Amigo!"

"Cześć, Bilaabo!"

„Dzisiaj opowiem o kilku słowach kluczowych w Javie. Ale zacznę od najciekawszego: słowa kluczowego final ” .

„Możesz użyć słowa kluczowego final podczas deklarowania zmiennej, metody lub klasy”.

„A po co nam finał?”

„To całkiem proste. Jeśli oznaczymy zmienną jako ostateczną, staje się ona niezmienna:”

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

"Widzę."

„Jeśli oznaczymy metodę jako ostateczną, to zastępowanie metody w klasach pochodnych jest zabronione:”

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

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

„Rozumiem. Ale dlaczego miałbyś zabronić zastępowania metody?”

„Cóż, jako przykład, załóżmy, że programista napisał wiele ważnego kodu w metodzie i chce zagwarantować, że wszystkie klasy, które dziedziczą jego klasę, będą miały określone zachowanie”.

„I wreszcie trzecie użycie”.

„Jeśli oznaczymy klasę słowem kluczowym final, nie można jej odziedziczyć”.

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";
 }
}

„A dlaczego mielibyśmy zapobiegać dziedziczeniu klasy?”

„Powinieneś zrozumieć, że nie zapobiegamy, by dziedziczenie było irytujące, ale raczej ze względu na bezpieczeństwo i integralność kodu. Jeśli dziedziczenie klas nie jest zabronione, oznacza to, że jest dozwolone. I że kod napisany przez klasę designer będzie działał poprawnie dla obiektów tej klasy, jak również dla obiektów dowolnych klas pochodnych."

„Ale jeśli programista zdaje sobie sprawę, że nawet niewielkie zmiany w jego klasie spowodują, że wszystko przestanie działać zgodnie z oczekiwaniami, lepiej zakazać dziedziczenia”.

„Na przykład klasa String jest zadeklarowana jako ostateczna, podobnie jak wszystkie typy pierwotne: Integer, Boolean, Double, Character…”

„Ach, rozumiem. Klasa String została stworzona jako klasa niezmienna i gdyby nagle stała się zmienna, wiele rzeczy przestałoby działać”.

„Cóż, prawie. Ujmijmy to w ten sposób: wszystko działałoby prawie jak wcześniej, ale czasami pojawiałyby się błędy, które byłyby bardzo trudne do znalezienia i zrozumienia. Tak więc w niektórych przypadkach dziedziczenie klas lub metod tak naprawdę nie jest grzechem, ale zakazanie oznacza mniej błędów do wyłapania później”.

„Gdzie jeszcze możesz użyć final?”

„Możesz użyć final przed parametrami funkcji i przed zmiennymi w metodzie. Oto przykład:”

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

— A jaki to ma sens?

„Cóż, są dwa. Po pierwsze, deklarujemy zmienną jako ostateczną, jeśli chcemy powiedzieć innym programistom, że ta wartość jest określoną stałą, a nie tylko zmienną”.

Na przykład chcemy obliczyć podatek od sprzedaży na podstawie ceny:

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

„Po drugie, potrzebujemy tego typu zmiennych podczas pisania lokalnych lub anonimowych klas wewnętrznych. Wkrótce opowiem o tego typu klasach. Ale nie dzisiaj”.

„Dobrze, jak dotąd nie było nic zbyt skomplikowanego”.

„Pamiętaj, że tylko zmienna staje się niezmienna, a nie obiekt, do którego może się odnosić. Obiekt nadal można zmienić”.

„Właściwie właśnie miałem o to zapytać. I nie ma sposobu, aby obiekt stał się niezmienny?”

„Nie, chyba że napiszesz niezmienną klasę”.

„Należy pamiętać, że ponieważ wartości zmiennej końcowej nie można zmienić, należy natychmiast przypisać jej wartość początkową”.

Ten kod się skompiluje Ten kod się nie skompiluje
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()
 {
 }
}

„Ale to powiedziawszy, Java pozwala opóźnić inicjalizację zmiennych końcowych klasy do konstruktora”.

Ten kod się skompiluje Ten kod się nie skompiluje
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;
 }
}

„Dodatkowo różne konstruktory mogą inicjować zmienne końcowe różnymi wartościami. Jest to całkiem wygodne:”

Ten kod się skompiluje
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;
 }
}

„To był naprawdę interesujący temat i absolutnie wszystko ma sens. Dziękuję, Bilaabo!”