web-dev-qa-db-fra.com

Pourquoi la méthode privée ne peut-elle pas être définitive aussi?

Est-il redondant d'ajouter private et final à une même méthode?

class SomeClass {

    //--snip--

    private final void doStuff()
    {
        // private work here
    }
}

Si c'est private, il n'y a aucun moyen que quelqu'un puisse le remplacer, non?

Pourquoi est-il possible d'ajouter un mot clé final s'il n'a aucun effet? (ou est-ce que je manque quelque chose?)

46
MightyPork

Fondamentalement, c'est autorisé car ils ne pensaient pas qu'il valait la peine de mettre un cas spécial interdisant le modificateur private. C'est comme comment vous pouvez également déclarer des méthodes sur une interface en tant que public, ou des classes imbriquées dans une interface en tant que static, même si ces mots clés sont impliqués dans les interfaces. Vous pouvez également déclarer des méthodes final sur une classe final, etc.

Java a pris la position de ne pas se plaindre lorsque vous ajoutez des modificateurs redondants. Ils le font régulièrement.

56
yshavit

Un cas Edge qui nécessite qu'une méthode privée soit définitive est lorsque l'annotation SafeVarargs est utilisée. Le code suivant ne se compile pas, car la méthode privée n'est pas définitive.

@SafeVarargs
private void method(List<String>... stringLists) {
    //TODO a safe varargs operation
}
5
jaco0646

Cela rend la langue plus flexible mais la langue ne garantit pas qu'elle aura un effet. La finalisation d'une méthode privée est un indice pour le compilateur ( JIT ).

Le Java Spécification du langage notes qui:

Une méthode peut être déclarée finale pour empêcher les sous-classes de la remplacer ou de la masquer.

Il s'agit d'une erreur de compilation pour tenter de remplacer ou de masquer une méthode finale.

Une méthode privée et toutes les méthodes déclarées immédiatement dans une classe finale ( §8.1.1.2 ) se comportent comme si elles étaient finales, car il est impossible de les remplacer.

Au moment de l'exécution, un générateur ou optimiseur de code machine peut "inline" le corps d'une méthode finale, en remplaçant une invocation de la méthode par le code dans son corps. Le processus d'inline doit conserver la sémantique de l'invocation de la méthode. En particulier, si la cible d'un appel de méthode d'instance est null, une exception NullPointerException doit être levée même si la méthode est en ligne. Un Java doit s'assurer que l'exception sera levée au bon point, afin que les arguments réels de la méthode soient considérés comme ayant été évalués dans le bon ordre avant l'appel de la méthode.

De Wikipedia :

Une idée fausse courante est que déclarer une classe ou une méthode comme finale améliore l'efficacité en permettant au compilateur d'insérer directement la méthode partout où elle est appelée (voir développement en ligne). Mais comme la méthode est chargée au moment de l'exécution, les compilateurs ne peuvent pas le faire. Seuls l'environnement d'exécution et le compilateur JIT savent exactement quelles classes ont été chargées, et donc seuls ils sont capables de prendre des décisions sur le moment de l'inline, que la méthode soit finale ou non

Les compilateurs de code machine qui génèrent directement du code machine spécifique à la plate-forme exécutable sont une exception. Lors de l'utilisation de la liaison statique, le compilateur peut supposer en toute sécurité que les méthodes et les variables calculables au moment de la compilation peuvent être intégrées.

4
McDowell