2014-06-17 1 views
5

Sur Java 1.8, vous n'avez pas besoin de définir un champ comme final pour qu'il soit accessible depuis des classes anonymes.Accès aux champs de classes anonymes sur Java 1.8 compatibilité avec les anciennes versions

Par exemple, sur les anciennes versions:

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

Mais, maintenant, sur Java 1.8, bar n'a pas besoin d'être définitive:

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

Donc, si je compile mon projet, et la seule ressource implémentée sur Java 1.8 que j'utilise est celle-ci (je n'utilise pas de lambdas, de nouvelles classes, etc.), mon code sera-t-il exécutable sur des ordinateurs avec des versions plus anciennes de Java? Si non, pourquoi?

+3

Vous pourriez manquer cette [différence entre final et efficace finale] (http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final) –

+2

'javac' ne vous permet simplement pas de combiner' -source 1.8' avec '-target 1.7'. – Holger

+0

En quittant la tangente, mais je ne voudrais pas coder en 1.8 sans déclarer explicitement mes arguments ou variables finaux comme * final *. Contrairement à d'autres langages où les args et les vars sont effectivement immuables par défaut, Java, le langage, les a toujours rendus mutables, par défaut. Alors maintenant, Java 1.8 fait cette magie dans les coulisses qui brouille effectivement la ligne de ce qui est mutable et de ce qui ne l'est pas. Terrible idée quand il s'agit de la lisibilité du code. –

Répondre

6

Lors de la compilation avec -target 1.8, javac émettra des fichiers de classe avec un numéro de version de 52.0 qui n'est pas pris en charge par les JVM précédentes. Donc, même si c'est la seule différence, cela vous empêche d'exécuter les fichiers compilés avec -target 1.8.

Et javac ne prend pas en charge la spécification -source 1.8 et -target 1.7 en même temps. Il produira le message d'erreur source release 1.8 requires target release 1.8. Mais en effet, si l'utilisation de variables finales est la seule fonction Java 8 que vous utilisez, il n'y a pas de différence de code d'octet en plus du numéro de version. Si vous compilez un tel code ciblant 1.8 et corrigez les fichiers de classe en réduisant le numéro de version à 51.0, ils fonctionneront sur Java 7. C'est aussi simple que de réduire l'octet à l'index 7 de un.

La partie la plus délicate est de vous discipliner à ne pas utiliser d'autres Java 8 fonctionnalités lors de l'utilisation d'un compilateur Java 8 si vous voulez créer un code compatible Java 7 ...

1

Je pense que Java 8 a changé la version majeure du fichier de classe pour qu'elle soit différente de Java 7, donc une JVM plus ancienne ne sera probablement pas capable de charger les classes plus récentes.

Si vous compilez avec un -target 1.7, je ne sais pas si vous pouvez utiliser efficacement finale

0

Si vous compilez ce code sans -target 1.7 -source 1.7 il sera compilé pour une version plus récente de bytecode et ancienne JVM ne pouvait pas fonctionner comme Des classes.

Si vous compilez votre exemple avec -target 1.7 -source 1.7 options - complication échouera avec le message

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

donc, la réponse est NON, vous ne pouvez pas exécuter ce code sur JVM plus

Questions connexes