Ok (->) operatörü önceliği / önceliği en düşük mü yoksa atama önceliği / birleşik ataması en düşük mü?


18

JLS :

En düşük öncelik operatörü lambda ifadesinin okudır (->) , ardından atama işleticileri tarafından farkedilmiştir.

Hangi yönde takip edildi (artan öncelik, azalan öncelik)? - "izlenen", atamanın daha yüksek önceliğe veya daha düşük önceliğe sahip olduğu anlamına gelir (ok operatörüne göre)? Sanırım, arttıkça, "en düşük" (ok için) kesinlikle en düşük demektir.

Anladığım kadarıyla, ok (->) bunun en altında olmalı Princeton operatör öncelik tablosunun en altında olmalıdır (tüm atama operatörlerinin altındadır), bu nedenle ok (->) 0 (sıfır) öncelik Seviyesine (bu tabloya göre) sahip olmalıdır.

Anladığım kadarıyla doğru muyum?

ExamTray ok önceliğinin en azından atama ile aynı olduğunu söylüyor ... Artı ok ilişkisinin Sol-> Kime-> Sağ (atamanın aksine) olduğu açıklığa kavuşturuldu. Ok ilişkisi için herhangi bir JLS teklifi bulamadım.

Her zaman atama önceliğinin bir nedenden dolayı temelde en düşük olduğunu düşünürdüm.


5
The lowest precedence operator is the arrow of a lambda expression.
Kayaman

2
Evet, anlayışınız doğru.
Eran

4
Eğer ->düşük est , atama operatörleri düşük olamaz er öncelik.
Andy Turner

IntFunction fo = a->b->a-b; // in test Genel olarak -> önceliği / ilişkilendirilebilirliği anlamına gelir. Bu yüzden tüm öncelik / ilişkilendirilebilirlik tablosundaki öncelik / ilişkilendirme yerini açıklığa kavuşturmaya karar verdim çünkü bundan emin değildim.
Kod Tamamlandı

1
@glglgl örneğiniz IntUnaryOperator op; op = x -> x;ilginç. Belki de üretimin geçerli bir örneği (op = x) -> xolmadığı için dikkate alınmaz mı? op = xLambdaParameters
Andy Turner

Yanıtlar:


13

Alıntılanan JLS metninden önceki cümleyi not edin :

Operatörler arasındaki öncelik, dilbilgisi yapımları hiyerarşisiyle yönetilir.

Java dilinin dilbilgisi hangi yapıların mümkün ve dolaylı olarak operatör önceliğini belirler.

Bağladığınız princeton masası bile :

Java Dil Spesifikasyonu'nda açık bir operatör öncelik tablosu yoktur. Web'deki ve ders kitaplarındaki farklı tablolar bazı küçük yollarla aynı fikirde değildir.

Java dilinin dilbilgisi, atama operatörünün solundaki lambda ifadelerine izin vermez ve benzer şekilde, öğesinin solundaki atamalara izin vermez ->. Dolayısıyla, bu operatörler arasında herhangi bir belirsizlik yoktur ve JLS'de açıkça belirtilmesine rağmen, öncelik kuralı anlamsız hale gelir.

Bu, muğlaklık olmadan, örneğin böyle bir mücevher derlemeye izin verir:

static Consumer<String> C;
static String S;
public static void main(String[] args)
{
  Runnable r;
  r = () -> C = s -> S = s;
}

10

İlk olarak, pratik sorunu burada açıklayalım.

Şunun gibi bir tanımınız olduğunu varsayarsak:

IntUnaryOperator op;

Aşağıdaki sözdizimsel olarak kabul edilir ve beklendiği gibi çalışır:

op = x -> x;

Yani, değişkene intatanmış bir kimlik fonksiyonumuz var op. Ancak =daha yüksek bir önceliğe sahip olsaydık, Java'nın bunu şu şekilde yorumlamasını beklerdik:

(op = x) -> x;

Sözdizimsel olarak geçerli olmayan, bu nedenle derleme hatası olmalıdır. Dolayısıyla, ödev uygulamada oktan daha yüksek önceliğe sahip değildir.

Ancak aşağıdakiler de uygundur ( ttürün bir sınıf / örnek değişkeni olduğunu varsayalım int):

op = x -> t = x;

Bu derlenir ve eğer uygulanırsa işlev, işlenenin değerini atar tve ayrıca döndürür.

Bu, okun ödevden daha yüksek önceliğe sahip olmadığı anlamına gelir t = x. Aksi takdirde şu şekilde yorumlanırdı:

op = ( x -> t ) = x

ve açıkça, olan bu değil.

Yani operasyonların eşit önceliğe sahip olduğu görülüyor. Dahası, doğru çağrışımcı olmaları. Bu JLS bölüm 19'daki dilbilgisinden ima edilir :

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

Böylece lambda gövdesinin sağ tarafı bizi geri götürür Expression, yani içinde (daha yüksek öncelikli) bir lambda ya da içinde (daha yüksek öncelikli) bir atama yapabiliriz. "Yüksek öncelik" ile kastettiğim, üretim kurallarını ne kadar derinden incelerseniz, ifade ne kadar erken değerlendirilir.

Aynı şey atama operatörü için de geçerlidir:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

Bir kez daha, ödevin sağ tarafı bizi geri atar Expression, böylece bir lambda ifadesi veya bir ödev alabiliriz.

Dolayısıyla, dilbilgisi JLS metnine dayanmak yerine, bize durumun iyi tanımlanmış bir tanımını verir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.