Różnica między finałem a finałem

Gram z lambda w Javie 8 i natknąłem się na Ostrzeżenie local variables referenced from a lambda expression must be final or effectively final. Wiem, że kiedy używam zmiennych wewnątrz anonimowej klasy, muszą one być ostateczne w zewnętrznej klasie , ale nadal-jaka jest różnica między finali effective final?

Author: alex, 2014-01-05

11 answers

... począwszy od Java SE 8, klasa lokalna może uzyskać dostęp do lokalnych zmiennych i parametrów bloku zamykającego, które są ostateczne lub faktycznie ostateczne. zmienna lub parametr, którego wartość Nigdy nie zostanie zmieniona po zainicjowaniu, jest ostatecznie ostateczna.

Na przykład, załóżmy, że zmienna numberLength nie jest zadeklarowana jako ostateczna, a w konstruktorze PhoneNumber dodajemy zaznaczoną instrukcję assignment:

public class OutterClass {  

  int numberLength; // <== not *final*

  class PhoneNumber {

    PhoneNumber(String phoneNumber) {
        numberLength = 7;   // <== assignment to numberLength
        String currentNumber = phoneNumber.replaceAll(
            regularExpression, "");
        if (currentNumber.length() == numberLength)
            formattedPhoneNumber = currentNumber;
        else
            formattedPhoneNumber = null;
     }

  ...

  }

...

}

Ze względu na to polecenie przypisania, zmienna numberLength nie jest już ostatecznie ostateczna. w rezultacie kompilator Javy generuje komunikat o błędzie podobny do "zmienne lokalne odwołujące się z wewnętrznej klasy muszą być ostateczne lub ostatecznie ostateczne" gdzie wewnętrzny numer Fonenumer klasy próbuje uzyskać dostęp do zmiennej numberLength:

Http://codeinventions.blogspot.in/2014/07/difference-between-final-and.html

Http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html

 184
Author: ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 16:13:00

Najprostszym wyjaĹ "nieniem" efektywnie finalnym " jest wyobraĺźenie sobie dodania modyfikatora final do deklaracji zmiennej. Jeśli przy tej zmianie program zachowuje się w ten sam sposób, zarówno w czasie kompilacji, jak i podczas wykonywania, wtedy ta zmienna jest ostatecznie ostateczna.

 110
Author: Maurice Naftalin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 15:33:48

Zgodnie z docs :

Zmienna lub parametr, którego wartość Nigdy nie zostanie zmieniona po zainicjowaniu, jest ostatecznie ostateczna.

Zasadniczo, jeśli kompilator stwierdzi, że zmienna nie pojawia się w przypisaniach poza jej inicjalizacją, wtedy zmienna jest uważana za efektywnie ostateczną.

Na przykład, rozważmy jakąś klasę:

public class Foo {

    public void baz(int bar) {
        // While the next line is commented, bar is effectively final
        // and while it is uncommented, the assignment means it is not
        // effectively final.

        // bar = 2;
    }
}
 30
Author: Mark Elliot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-11 22:39:53

Z artykułu 'Brian Goetz',

'Effectively final' jest zmienną, która nie dałaby kompilatorowi błędu if it were to be appended by 'final'

Lambda-state-final-Brian Goetz

 23
Author: Ajeet Ganga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-15 23:14:40

Ta zmienna poniżej jest final , więc nie możemy zmienić jej wartości po zainicjowaniu. Jeśli spróbujemy, dostaniemy błąd kompilacji...

final int variable = 123;

Ale jeśli stworzymy taką zmienną, możemy zmienić jej wartość...

int variable = 123;
variable = 456;

Ale w Java 8 wszystkie zmienne są domyślnie final . Jednak istnienie drugiej linii w kodzie sprawia, że nie jest ostateczną . Jeśli więc usuniemy 2-gą linię z powyższego kodu, nasza zmienna będzie teraz " efektywnie finał"...

int variable = 123;
Więc.. każda zmienna przypisana raz i tylko raz, jest "efektywnie ostateczna" .
 12
Author: Eurig Jones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-03 23:38:19

Zmienna jest final lub finally Kiedy jest inicjalizowana raz i nigdy nie jest zmutowana w klasie właściciela. I nie możemy zainicjować W pętlach lub klasach wewnętrznych.

Finał :

final int number;
number = 23;

:

int number;
number = 34;
 6
Author: samadadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-07 16:01:27

Gdy wyrażenie lambda używa przypisanej zmiennej lokalnej z otaczającej go przestrzeni, istnieje ważne ograniczenie. Wyrażenie lambda może używać tylko zmiennej lokalnej, której wartość nie zmienia się. Ograniczenie to jest określane jako " variable capture ", które jest opisane jako; lambda expression capture values, a nie zmienne .
Zmienne lokalne, których może używać wyrażenie lambda, są znane jako " effectively final ".
Zmienną ostateczną jest zmienna, której wartość nie zmienia się po pierwszym przypisaniu. Nie ma potrzeby jawnego deklarowania takiej zmiennej jako ostatecznej, chociaż nie byłoby to błędem.
Spójrzmy na przykład, mamy lokalną zmienną i, która jest zainicjalizowana wartością 7, a w wyrażeniu lambda staramy się zmienić tę wartość, przypisując nową wartość do i. spowoduje to błąd kompilatora - " lokalna zmienna, którą zdefiniowałem w otaczającym zakresie musi być ostateczna lub efektywnie ostateczna "

@FunctionalInterface
interface IFuncInt {
    int func(int num1, int num2);
    public String toString();
}

public class LambdaVarDemo {

    public static void main(String[] args){             
        int i = 7;
        IFuncInt funcInt = (num1, num2) -> {
            i = num1 + num2;
            return i;
        };
    }   
}
 6
Author: infoj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-29 15:21:15

efektywny końcowy temat jest opisany w JLS 4.12.4 , a ostatni akapit składa się z jasnego wyjaśnienia:

Jeśli zmienna jest finalna, dodanie ostatecznego modyfikatora do jej deklaracji nie spowoduje żadnych błędów w czasie kompilacji. I odwrotnie, lokalna zmienna lub parametr, który jest uznany za ostateczny w prawidłowym programie, staje się ostatecznie ostateczny, jeśli ostateczny modyfikator zostanie usunięty.

 2
Author: Dmitry N.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 04:24:52
public class LambdaScopeTest {
    public int x = 0;        
    class FirstLevel {
        public int x = 1;    
        void methodInFirstLevel(int x) {

            // The following statement causes the compiler to generate
            // the error "local variables referenced from a lambda expression
            // must be final or effectively final" in statement A:
            //
            // x = 99; 

        }
    }    
}

Jak powiedzieli inni, zmienna lub parametr, którego wartość Nigdy nie zostanie zmieniona po zainicjowaniu, jest ostatecznie ostateczna. W powyższym kodzie, jeśli zmienisz wartość x w klasie wewnętrznej FirstLevel wtedy kompilator wyświetli komunikat o błędzie:

Zmienne lokalne odwołujące się do wyrażenia lambda muszą być ostateczne lub ostatecznie ostateczne.

 1
Author: Tenacious,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 06:44:59

Jeśli można dodać modyfikator final do zmiennej lokalnej, to / Align = "left" /

Wyrażenia Lambda mogą uzyskać dostęp

  • Zmienne statyczne,

  • Zmienne instancji,

  • Finał parametry metody oraz

  • Finał zmienne lokalne.

Źródło: OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide, Jeanne Boyarsky, Scott Selikoff

Dodatkowo,

Zmienna effectively final jest zmienną, której wartość Nigdy zmienione, ale nie jest zadeklarowane za pomocą słowa kluczowego final.

Source: Starting Out with Java: From Control Structures through Objects( 6th Edition), Tony Gaddis

Ponadto, nie zapominaj o znaczeniu final, że jest on zainicjowany dokładnie raz, zanim zostanie użyty po raz pierwszy.

 1
Author: snr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 06:00:19

Jednakże, począwszy od Javy SE 8, klasa lokalna może uzyskać dostęp do lokalnych zmiennych i parametrów bloku>, które są ostateczne lub ostatecznie ostateczne.

To nie zaczęło się na Javie 8, używam tego od dawna. Kod używany (przed Javą 8) jako legalny:

String str = ""; //<-- not accesible from anonymous classes implementation
final String strFin = ""; //<-- accesible 
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
         String ann = str; // <---- error, must be final (IDE's gives the hint);
         String ann = strFin; // <---- legal;
         String str = "legal statement on java 7,"
                +"Java 8 doesn't allow this, it thinks that I'm trying to use the str declared before the anonymous impl."; 
         //we are forced to use another name than str
    }
);
 -6
Author: FiruzzZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-30 10:54:05