7
votes

Java Compiler Oddity: champ déclaré dans la même classe, mais "pas visible"

Le compilateur Eclipse refuse de compiler le code suivant, indiquant que le champ S n'est pas visible. (L'aspect de l'IBM J Compiler refuse également, indiquant que "S n'a pu être résolu") Pourquoi? XXX

La spécification de langue Java Spécification STATS:

Sinon, nous disons qu'il y a de la valeur par défaut accès, qui n'est autorisé que lorsque L'accès se produit de l'intérieur de la paquet dans lequel le type est déclaré.

La manière dont je comprends, le champ est déclaré et accessible dans la même unité de compilation, donc dans le même paquet, et doit donc être accessible.

encore plus étrangement, ajoutant un Diminué de ? EXTENEZ TEST TO TEST Effectue le champ Visible, c'est-à-dire que le code suivant compile: xxx

ai-je trébuché sur un bug de compilateur, ou mal compris la spécification Java?

EDIT: Je suis sur un autre ordinateur maintenant. Ici, Javac accepte le code, mais Eclipse n'est toujours pas. Versions sur cette machine:

Plateforme Eclipse

Version: 3.4.2 ID de construction: M20090211-1700

JDK 1.6.0

Edit 2 En effet, Javac accepte le code. J'avais été testé en exécutant la construction de fourmis, qui utilise ...


1 commentaires

problème kewl. Où est Josh Bloch?


5 Réponses :


2
votes

Je ne peux pas reproduire ce que vous dites. Celles-ci sont toutes deux correctes pour moi sans avertissement, erreur ou quoi que ce soit avec Javac directement.

WinXP, Javac 1.6.0_16


Non, j'ai essayé avec Eclipse (V3.4.1, ID de construction: M20080911- 1700) et pour le premier, il dit: xxx

au moins pour le niveau de conformité du compilateur 1.6 et 1.5. La chose amusante étant, si vous regardez les options de correction rapide, il répertorie un Modifier la résolution de 's' . Lequel bien sûr ne résout pas le problème. Donc, le compilateur Eclipse et le "générateur" de correctif rapide semblent avoir une vue différente sur cela aussi; -)


pour le niveau de conformité du compilateur 1.4 (comme on l'attendait) dans Eclipse pour le premier une personne que j'ai xxx

et pour la seconde, je reçois xxx


si je spécifie - Source 1.4 et cible -1.4 dans la ligne de commande directement javac dit pour la première xxx

et pour le second, je reçois xxx


1 commentaires

Je suis maintenant sur un autre ordinateur, où Javac accepte le code, mais Eclipse n'est toujours pas. Que dit votre éclipse? Je vais répéter mon test sur la machine d'origine demain pour m'assurer que j'ai testé correctement.



4
votes

Eh bien, voyons. Je dirais que le compilateur ne peut pas bien garantir que foo () sera appelé par une entité dans l'emballage, et ne peut donc pas garantir que s est visible. Par exemple, ajoutez xxx

puis dans certaines sous-classes banane dans un autre paquet xxx

et oups! getclass () rendements banane , qui ne peut pas voir s .

modifier: dans un sens, autre.backage.banana Ne n'a pas un champ s . Si la banane était dans le même paquet, il pourrait toujours avoir sa propre propriété S et devrait se référer à Test S s via super .


2 commentaires

Je crois comprendre que la banane ne peut pas voir S signifie que le code dans la banane de l'unité de compilation ne peut pas accéder à l'art. Mais mon code est dans le test de l'unité de compilation ...


Oui, votre code est dans le test de l'unité de compilation, mais une sous-classe putative pourrait ne pas être, et cette classe sera le résultat de GetClass (), et que la classe ne peut pas voir le champ protégé contre le paquet. L'erreur du compilateur est correcte, je pense.



6
votes

Essayez ceci: xxx

[modifier à clarifier]:

getclass (). Cast (O) retourne un objet de type ' capture n ° 1 - de? Étend le test 'et pas test . La question est donc liée aux génériques et à la manière dont le compilateur traite. Je ne connais pas les détails de la spécification sur les génériques, mais que certains compilateurs (par commentaires ici) acceptent votre code, il s'agit donc d'un trou de boucle dans la spécification ou que certains de ces compilateurs ne sont pas entièrement en fonction de la spécification. < / p>

[Dernières pensées]: Je crois que le compilateur Eclipse est en réalité (soigneusement) correct ici. L'objet o peut en fait être une extension du test (et défini dans un autre paquet) et le compilateur n'a aucun moyen de savoir si c'est bien le cas ou non. Donc, il le traite comme le pire cas d'une instance d'une extension définie dans un autre paquet. Il aurait été super correct si l'ajout d'un qualificatif final à la classe Test aurait permis d'accéder au champ s , mais ce n'est pas.


4 commentaires

Remarque Ce qui précède a été compilé sur Mac OS X / Eclipse 3.4.


Euh ... je l'ai déjà fait? Ou que renonce à la variable locale de mon extrait de 2e code accomplir? Je sais que ça marche. Ma question est la raison pour laquelle le premier extrait ne le fait pas.


Ce n'est pas parce que vous supposez que la capture générique est également définie dans le même paquet par le compilateur. Si ce n'est pas le cas, la visibilité de niveau de paquet ne s'applique plus.


(Et désolé, j'ai écrémé votre message et j'ai raté la fin.)



1
votes

En fait dans presque tous les cas, sauf si nécessaire par des génériques, c'est mieux (et plus sûr) d'utiliser l'opérateur de Cast de Java. J'ai discuté ici . Java Cast Operateur a examiné par-dessus Verbose, mais c'est le bon outil ici.

Remplacement de Mode code> La méthode avec l'opérateur compile tout simplement à Eclipse. P>

public class Test {

    String s;

    void foo(Object o) {
        String os = ((Test) o).s;
    }
}


0 commentaires

0
votes

très bizarre. Pour une raison inconnue (pour moi), le compilateur Eclipse nécessite une fonte explicite: xxx

tandis que le code compile parfaitement sans le coulé avec JDK de Sun (je cours la version 1.6.0_16 sur GNU / Linux).


0 commentaires