2014-06-17 45 views
5

W języku Java 1.8 nie trzeba definiować pola jako final, aby można było uzyskać dostęp z anonimowych klas.Dostęp do pól klas anonimowych na zgodność z wersją Java 1.8 ze starszymi wersjami

Na przykład, w starszych wersjach:

public void foo(final int bar) { 
    new Runnable() { 
    public void run() { 
     System.out.println(bar); 
    } 
    }; 
} 

Ale teraz, na Java 1.8, bar nie musi być ostateczna:

public void foo(int bar) { 
    new Runnable() { 
    public void run() { 
     System.out.println(bar); 
    } 
    }; 
} 

Więc jeśli mogę skompilować mój projekt, a jedynym zasobem zaimplementowanym w Javie 1.8, którego używam, jest to (nie używam żadnych lambd, nowych klas, itp.), czy mój kod będzie wykonywany na komputerach ze starszymi wersjami Javy? Jeśli nie, dlaczego?

+3

może Przegapiłeś to [różnica między ostateczna i skutecznie ostateczna] (http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively- final) –

+2

'javac' po prostu nie pozwala ci połączyć' -source 1.8' z '-target 1.7'. – Holger

+0

Schodzę ze stycznej, ale nie chciałbym kodować w 1.8 bez jawnie deklarowania moich ostatnich argumentów lub zmiennych jako * końcowy *. W przeciwieństwie do innych języków, w których wartości domyślne i vars są domyślnie niezmienne, domyślnie Java, język, zawsze je domyślnie zmienia. Teraz Java 1.8 robi to za kulisami, które skutecznie zacierają linię tego, co zmienne, a co nie. Okropny pomysł, jeśli chodzi o czytelność kodu. –

Odpowiedz

6

Podczas kompilacji z -target 1.8, javac będzie emitować pliki klas z numerem wersji 52.0, który nie jest obsługiwany przez poprzednie maszyny JVM. Więc nawet jeśli to jedyna różnica, uniemożliwia wykonywanie plików skompilowanych przy użyciu -target 1.8.

I javac nie obsługuje jednoczesnego określania -source 1.8 i -target 1.7. Zostanie wygenerowany komunikat o błędzie source release 1.8 requires target release 1.8.

Rzeczywiście, jeśli używasz efektywnie zmiennych końcowych, jest to jedyna funkcja Java 8, z której korzystasz, nie ma różnicy kodów bajtów poza numerem wersji. Jeśli skompilujesz taki kod kierujący do 1.8 i załatwisz pliki klasy, redukując numer wersji do 51.0, będą one działały na Java 7. Jest to tak proste, jak zredukowanie bajtu w indeksie 7 o jeden.

Najtrudniejsze jest zdyscyplinować się do nie korzystania z innych Java 8 możliwości podczas korzystania z Java 8 kompilator jeśli chcesz utworzyć Java 7 kod zgodny ...

1

Myślę, że Java 8 zmieniła wersję główną pliku klasowego na inną niż Java 7, więc starsza maszyna JVM prawdopodobnie nie będzie mogła załadować nowszych klas.

Jeśli skompilować z -target 1,7, nie wiem, czy można użyć skutecznie ostateczny

0

Jeśli skompilować ten kod bez -target 1.7 -source 1.7 zostanie skompilowany do nowszej wersji kodu bajtowego i starych JVM nie może uruchomić takie klasy.

Jeśli skompilować przykład z -target 1.7 -source 1.7 opcji - powikłanie zawiedzie z komunikatem

error: local variable bar is accessed from within inner class; needs to be declared final 
           System.out.println(bar); 
               ^

tak, to odpowiedź brzmi NIE, nie można uruchomić taki kod na starsze JVM na