Pytanie Zainicjuj statyczne pole końcowe w konstruktorze


public class A 
{    
    private static final int x;

    public A() 
    {
        x = 5;
    }
}
  • final oznacza, że ​​zmienna może zostać przypisana tylko raz (w konstruktorze).
  • static oznacza, że ​​jest instancją klasy.

Nie rozumiem, dlaczego jest to zabronione. Gdzie te słowa kluczowe przeszkadzają sobie nawzajem?


76
2018-02-23 16:28


pochodzenie




Odpowiedzi:


Konstruktor będzie wywoływany za każdym razem, gdy zostanie utworzona instancja klasy. Zatem powyższy kod oznacza, że ​​wartość x zostanie ponownie zainicjalizowana za każdym razem, gdy tworzona jest instancja. Ale ponieważ zmienna jest zadeklarowana jako ostateczna (i statyczna), możesz to tylko zrobić

class A {    
    private static final int x;

    static {
        x = 5;
    }
}

Ale jeśli usuniesz statyczne, możesz to zrobić:

class A {    
    private final int x;

    public A() {
        x = 5;
    }
}

Albo to:

class A {    
    private final int x;

    {
        x = 5;
    }
}

162
2018-02-23 16:32



+1 dla jasnej i prostej odpowiedzi - sactiw
Najwyraźniej nikt nie zadał sobie trudu, aby wyjaśnić, że zmienne statyczne są zmiennymi istniejącymi we wszystkich instancjach klasy. W związku z tym można je utworzyć tylko raz, gdy klasa jest ładowana - nie wtedy, gdy konstruuje się potencjalnie wiele wystąpień klasy. - iheanyi
Polecam też tylko przypisanie w deklaracji, a nie w bloku statycznym. Jest po prostu czystszy i prawdopodobnie jest tym, co OP chciał zrobić: private static final int x = 5; - qwertzguy


statyczne zmienne końcowe są inicjowane po załadowaniu klasy. Konstruktora można nazwać znacznie później lub wcale. Ponadto, konstruktor będzie wywoływany wiele razy (z każdym nowym obiektem), więc pole nie może być już ostateczne.

Jeśli potrzebujesz niestandardowej logiki, aby zainicjować swoje statyczne pole końcowe, umieść to w statycznym bloku


15
2018-02-23 16:31



Ok, ale właśnie wyjaśniłeś, co się dzieje. Pytam, dlaczego? Mam na myśli, bez finału działa, bez statycznego działa. więc połączenie obu tworzy jakąś nową logikę? - Yaron Levi
@ YaronLevi, właśnie to powiedział ... pole statyczne jest członkiem samej klasy. W swoim konstruktorze przypisujesz wartość do zmiennej. Słowo "finał" oznacza, że ​​możesz przypisać wartość do zmiennej JEDEN czas, w twoim kodzie przypisujesz wartość do zmiennej za każdym razem, gdy tworzona jest klasa - ponieważ zmienna jest statyczna (członek klasy). Jeśli pozbędziesz się statycznego, możesz przydzielić mu wartość w konstruktorze, ponieważ za każdym razem jest nową zmienną. Jeśli pozbędziesz się finału, to jest to tylko zmienna statyczna, do której możesz przypisać nową wartość w dowolnym momencie. - user12345613
@ user12345613 przedstawił całkiem dobre wyjaśnienie. Sama, praca ostateczna lub statyczna; ale raz połączone, siły "statyczne końcowe" jest tylko jedno takie pole dla tej klasy we wszystkich instancjach i można je zainicjować tylko raz bez względu na liczbę instancji. - user908645


Zastanów się, co stanie się za drugim razem, gdy utworzysz obiekt. Próbuje ustawić to PONOWNIE, co jest wyraźnie zabronione przez bycie statycznym finałem. Może być ustawiony tylko raz dla całej klasy, a nie dla instancji.

Powinieneś ustawić wartość, gdy ją zadeklarujesz

private static final x=5;

Jeśli potrzebujesz dodatkowej logiki lub bardziej skomplikowanej instancji, możesz to zrobić w statycznym bloku inicjalizacyjnym.


6
2018-02-23 16:32





static oznacza, że ​​zmienna jest unikalna w aplikacji. final oznacza, że ​​powinna być ustawiona tylko raz.

Jeśli ustawisz go w swoim konstruktorze, pozwalasz ustawić zmienną więcej niż jeden raz.

Dlatego należy go zainicjować bezpośrednio lub zaproponować metodę statyczną, aby go zainicjować.


5
2018-02-23 16:33





Finał nie oznacza, że ​​należy go zainicjować w konstruktorze. Zasadniczo to się robi:

 private static final int x = 5;

statyczny zamiast tego oznacza, że ​​zmienna zostanie udostępniona za pośrednictwem wielu instancji klasy. Na przykład :

public class Car {
   static String name;
   public Car(String name) {
      this.name = name;
   }
}

...

Car a = new Car("Volkswagen");
System.out.println(a.name); // Produces Volkswagen

Car b = new Car("Mercedes");
System.out.println(b.name); // Produces Mercedes
System.out.println(a.name); // Produces Mercedes

3
2018-02-23 16:38





Pomyśl o tym. Możesz to zrobić za pomocą swojego kodu:

A a = new A();
A b = new A(); // Wrong... x is already initialised

Prawidłowe sposoby inicjalizacji x to:

public class A 
{    
    private static final int x = 5;
}

lub

public class A 
{    
    private static final int x;

    static
    {
        x = 5;
    }
}

2
2018-02-23 16:33





    public class StaticFinalExample {
  /*
   * Static final fields should be initialized either in
   * static blocks or at the time of declaration only
   * Reason : They variables are like the utility fields which should be accessible
   * before object creation only once.
   */
  static final int x;

  /*
   * Final variables shuould be initialized either at the time of declaration or
   * in initialization block or constructor only as they are not accessible in static block
   */
  final int y;

  /*
   * Static variables can be initialized either at the time of declaration or
   * in initialization or constructor or static block. Since the default value is given to the
   * static variables by compiler, so it depends on when you need the value
   * depending on that you can initialize the variable appropriately
   * An example of this is shown below in the main method
   */
  static int z;

  static {
    x = 20; // Correct
  }
  {
    y = 40; // Correct
  }
  StaticFinalExample() {
    z = 50; // Correct
  }
  public static void main (String args[]) {
    System.out.println("Before Initialization in Constructor" + z);   // It will print 0
    System.out.println("After Initializtion in Constructor" + new StaticFinalExample().z); // It will print 50
  }
}

0
2018-04-05 10:59