Java Language
Wyrażenia
Szukaj…
Wprowadzenie
Uwagi
Aby uzyskać informacje na temat operatorów, które mogą być używane w wyrażeniach, zobacz Operatory .
Priorytet operatora
Gdy wyrażenie zawiera wiele operatorów, można je odczytać na różne sposoby. Na przykład wyrażenie matematyczne 1 + 2 x 3
można odczytać na dwa sposoby:
- Dodaj
1
i2
i pomnóż wynik przez3
. To daje odpowiedź9
. Gdybyśmy dodali nawiasy, wyglądałoby to na( 1 + 2 ) x 3
. - Dodaj
1
do wyniku pomnożenia2
i3
. To daje odpowiedź7
. Gdybyśmy dodali nawiasy, wyglądałoby to na1 + ( 2 x 3 )
.
W matematyce konwencja polega na odczytywaniu wyrażenia w drugą stronę. Ogólna zasada jest taka, że mnożenie i dzielenie odbywa się przed dodawaniem i odejmowaniem. Gdy używana jest bardziej zaawansowana notacja matematyczna, albo albo „oczywiste” (dla wyszkolonego matematyka!), Albo nawiasy są dodawane w celu jednoznaczności. W obu przypadkach skuteczność notacji w przekazywaniu znaczenia zależy od inteligencji i wspólnej wiedzy matematyków.
Java ma takie same jasne zasady dotyczące odczytywania wyrażeń, w oparciu o pierwszeństwo używanych operatorów.
Zasadniczo każdemu operatorowi przypisuje się wartość pierwszeństwa ; patrz tabela poniżej.
Na przykład:
1 + 2 * 3
Priorytet +
jest niższy niż priorytet *
, więc wynikiem wyrażenia jest 7, a nie 9.
Opis | Operatory / konstrukcje (podstawowe) | Precedens | Stowarzyszenie |
---|---|---|---|
Kwalifikator Zdanie wtrącone Tworzenie instancji Dostęp do pola Dostęp do tablicy Wywołanie metody Odniesienie do metody | wymienić . Nazwa ( expr ) new podstawowy . Nazwa podstawowy [ wyrażenie ] podstawowy ( expr, ... ) podstawowe :: nazwa | 15 | Z lewej na prawą |
Przyrost postu | expr ++ , expr -- | 14 | - |
Wstępny przyrost Unary Obsada 1 | ++ expr, -- expr, + Expr, - wyrażenie, ~ expr, ! expr, ( typ ) expr | 13 | - Od prawej do lewej Od prawej do lewej |
Mnożny | * /% | 12 | Z lewej na prawą |
Przyłączeniowy | + - | 11 | Z lewej na prawą |
Zmiana | << >> >>> | 10 | Z lewej na prawą |
Relacyjny | <> <=> = instanceof | 9 | Z lewej na prawą |
Równość | ==! = | 8 | Z lewej na prawą |
Bitowe AND | I | 7 | Z lewej na prawą |
Wyłącznie bitowe OR | ^ | 6 | Z lewej na prawą |
Bitowe włącznie OR | | | 5 | Z lewej na prawą |
Logiczne AND | I & | 4 | Z lewej na prawą |
Logiczne OR | || | 3) | Z lewej na prawą |
Warunkowe 1 | ? : | 2) | Od prawej do lewej |
Zadanie Lambda 1 | = * = / =% = + = - = << = >> = >>> = & = ^ = | = -> | 1 | Od prawej do lewej |
1 Pierwszeństwo wyrażeń lambda jest złożone, ponieważ może wystąpić także po rzutowaniu lub jako trzecia część warunkowego operatora trójskładnikowego.
Wyrażenia stałe
Stałe wyrażenie jest wyrażeniem, które zwraca typ pierwotny lub ciąg znaków, i którego wartość można oszacować w czasie kompilacji do literału. Wyrażenie musi oceniać bez zgłaszania wyjątku i musi się składać tylko z następujących elementów:
Literały pierwotne i łańcuchowe.
Rzutowanie typów na typy pierwotne lub
String
.Następujące jednoargumentowe operatory:
+
,-
,~
i!
.Następujące operatory binarne:
*
,/
,%
,+
,-
,<<
,>>
,>>>
,<
,<=
,>
,>=
,==
!=
,&
,^
,|
,&&
i||
.Trójskładnikowy operator warunkowy
?
:
.Stałe wyrażenia w nawiasach.
Proste nazwy odnoszące się do zmiennych stałych. (Zmienna stała jest zmienną zadeklarowaną jako
final
gdzie samo wyrażenie inicjujące jest wyrażeniem stałym).Nazwy kwalifikowane w postaci
<TypeName> . <Identifier>
które odnoszą się do zmiennych stałych.
Zauważ, że powyższa lista wyklucza ++
i --
, operatory przypisania, class
i instanceof
, wywołania metod i odwołania do zmiennych ogólnych lub pól.
Stałe wyrażenia typu String
skutkują „wewnętrznym” String
, a operacje zmiennoprzecinkowe w wyrażeniach stałych są oceniane za pomocą semantyki ścisłej dla FP.
Używa wyrażeń stałych
Wyrażeń stałych można używać (prawie) wszędzie tam, gdzie można zastosować wyrażenie normalne. Mają jednak szczególne znaczenie w następujących kontekstach.
Wyrażenia stałe są wymagane dla etykiet przypadków w instrukcjach przełączników. Na przykład:
switch (someValue) {
case 1 + 1: // OK
case Math.min(2, 3): // Error - not a constant expression
doSomething();
}
Jeśli wyrażenie po prawej stronie przypisania jest wyrażeniem stałym, wówczas przypisanie może wykonać prymitywną konwersję zwężającą. Jest to dozwolone pod warunkiem, że wartość stałego wyrażenia mieści się w zakresie typu po lewej stronie. (Patrz JLS 5.1.3 i 5.2 ) Na przykład:
byte b1 = 1 + 1; // OK - primitive narrowing conversion.
byte b2 = 127 + 1; // Error - out of range
byte b3 = b1 + 1; // Error - not a constant expession
byte b4 = (byte) (b1 + 1); // OK
Kiedy wyrażenie stałe jest używane jako warunek w do
, while
lub for
, wówczas wpływa na analizę czytelności. Na przykład:
while (false) {
doSomething(); // Error - statenent not reachable
}
boolean flag = false;
while (flag) {
doSomething(); // OK
}
(Uwaga: nie dotyczy if
instrukcji if
. Kompilator Java pozwala na niedostępność bloku instrukcji if
then
lub w else
if
. Jest to analog Java w kompilacji warunkowej w C i C ++.)
Wreszcie static final
pola static final
w klasie lub interfejsie ze stałymi inicjalizatorami wyrażeń są inicjowane z niecierpliwością. W ten sposób gwarantuje się, że stałe te będą przestrzegane w stanie inicjalizacji, nawet jeśli na wykresie zależności inicjalizacji klasy występuje cykl.
Aby uzyskać więcej informacji, zobacz JLS 15.28. Wyrażenia stałe .
Kolejność oceny wyrażeń
Wyrażenia Java są oceniane według następujących reguł:
- Operandy są oceniane od lewej do prawej.
- Operandy operatora są oceniane przed operatorem.
- Operatory są oceniane według priorytetu operatorów
- Listy argumentów są oceniane od lewej do prawej.
Prosty przykład
W poniższym przykładzie:
int i = method1() + method2();
kolejność oceny jest następująca:
- Lewy operand operatora
=
jest przetwarzany na adresi
. - Oceniany jest lewy operand operatora
+
(method1()
). -
method2()
jest prawy argument operatora+
(method2()
). - Operacja
+
jest oceniana. - Operacja
=
jest oceniana, przypisując wynik dodania doi
.
Zauważ, że jeśli efekty wywołań są obserwowalne, będziesz w stanie zauważyć, że wywołanie metody method1
występuje przed wywołaniem method2
.
Przykład z operatorem, który ma efekt uboczny
W poniższym przykładzie:
int i = 1;
intArray[i] = ++i + 1;
kolejność oceny jest następująca:
- Oceniany jest lewy operand operatora
=
. Daje to adresintArray[1]
. - Wstępny przyrost jest oceniany. Dodaje to
1
doi
, a ocenia na2
. - Operand prawej
+
jest oceniany. - Operacja
+
jest oceniana na:2 + 1
->3
. - Operacja
=
jest oceniana, przypisując3
dointArray[1]
.
Zauważ, że ponieważ lewostronny argument =
jest oceniany jako pierwszy, nie ma na niego wpływu efekt uboczny podwyrażenia ++i
.
Odniesienie:
Podstawy wyrażeń
Wyrażenia w Javie są podstawową konstrukcją do wykonywania obliczeń. Oto kilka przykładów:
1 // A simple literal is an expression
1 + 2 // A simple expression that adds two numbers
(i + j) / k // An expression with multiple operations
(flag) ? c : d // An expression using the "conditional" operator
(String) s // A type-cast is an expression
obj.test() // A method call is an expression
new Object() // Creation of an object is an expression
new int[] // Creation of an object is an expression
Ogólnie wyrażenie składa się z następujących form:
- Nazwy wyrażeń, które składają się z:
- Proste identyfikatory; np.
someIdentifier
- Kwalifikowane identyfikatory; np.
MyClass.someField
- Proste identyfikatory; np.
- Podstawowe, które składają się z:
- Literały; np.
1
,1.0
,'X'
,"hello"
,false
inull
- Klasowe wyrażenia dosłowne; np.
MyClass.class
-
this
i<TypeName> . this
- Wyrażenia w nawiasach; np.
( a + b )
- Wyrażenia związane z tworzeniem instancji klasy; np.
new MyClass(1, 2, 3)
- Wyrażenia tworzenia instancji Array; np.
new int[3]
- Wyrażenia dostępu do pola; np.
obj.someField
lubthis.someField
- Wyrażenia dostępu do tablicy; np.
vector[21]
- Wywoływanie metod; np.
obj.doIt(1, 2, 3)
- Odwołania do metod (Java 8 i nowsze); np.
MyClass::doIt
- Literały; np.
- Jednoznaczne wyrażenia operatora; np
!a
lubi++
- Wyrażenia operatora binarnego; np.
a + b
lubobj == null
- Wyrażenia operatora trójskładnikowego; np.
(obj == null) ? 1 : obj.getCount()
- Wyrażenia lambda (Java 8 i nowsze); np.
obj -> obj.getCount()
Szczegóły dotyczące różnych form wyrażeń można znaleźć w innych tematach.
- Temat Operatory obejmuje wyrażenia jednoargumentowe, binarne i trójskładnikowe.
- Temat Wyrażenia lambda obejmuje wyrażenia lambda i wyrażenia referencyjne metod.
- Temat Klasy i obiekty obejmuje wyrażenia tworzenia instancji klasy.
- Temat Tablice obejmuje wyrażenia dostępu do tablicy i wyrażenia tworzenia instancji tablicy.
- Temat Literały obejmuje różne rodzaje wyrażeń dosłownych.
Rodzaj wyrażenia
W większości przypadków wyrażenie ma typ statyczny, który można określić w czasie kompilacji poprzez badanie i jego podwyrażenia. Są to tak zwane wyrażenia autonomiczne .
Jednak (w Javie 8 i nowszych) następujące wyrażenia mogą być wyrażeniami wielowymiarowymi :
- Wyrażenia w nawiasach
- Wyrażenia tworzenia instancji klasy
- Wyrażenia wywołania metody
- Wyrażenia odniesienia do metody
- Wyrażenia warunkowe
- Wyrażenia lambda
Gdy wyrażenie jest wyrażeniem poli, na jego typ może wpływać typ docelowy wyrażenia; tj. do czego jest używany.
Wartość wyrażenia
Wartość wyrażenia jest przypisaniem zgodnym z jego typem. Wyjątkiem jest sytuacja, gdy wystąpiło zanieczyszczenie hałdy ; np. ponieważ ostrzeżenia o „niebezpiecznej konwersji” zostały (niewłaściwie) stłumione lub zignorowane.
Instrukcje wyrażeń
W przeciwieństwie do wielu innych języków, Java ogólnie nie pozwala na używanie wyrażeń jako instrukcji. Na przykład:
public void compute(int i, int j) {
i + j; // ERROR
}
Ponieważ wynik oceny wyrażenia typu „nie można użyć”, a ponieważ nie może on wpłynąć na wykonanie programu w żaden inny sposób, projektanci Java stwierdzili, że takie użycie jest błędne lub mylące.
Nie dotyczy to jednak wszystkich wyrażeń. Podzbiór wyrażeń jest (w rzeczywistości) legalny jako oświadczenie. Zestaw zawiera:
- Wyrażenie przypisania, w tym operacje i staje się przypisaniami.
- Wyrażenia zwiększające i zmniejszające przed i po.
- Wywołania metod (
void
lub non-void
). - Wyrażenia tworzenia instancji klasy.