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?
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
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.
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;
}
}
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'
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" .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;
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;
};
}
}
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.
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.
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.
Dodatkowo,
Zmienna
effectively final
jest zmienną, której wartość Nigdy zmienione, ale nie jest zadeklarowane za pomocą słowa kluczowegofinal
.
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.
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
}
);
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