12
votes

Existe-t-il une annotation d'opération non prise en charge en Java?

Y a-t-il des annotations en Java qui marquent une méthode comme non pris en charge? Par exemple. Disons que j'écris une nouvelle classe qui implémente l'interface java.util.list code>. Les méthodes Ajouter () de cette interface sont facultatifs et je n'en ai pas besoin dans ma mise en œuvre et je dois donc faire ce qui suit:

public void add(Object obj) {
   throw new UnsupportedOperationException("This impl doesn't support add");
}


6 commentaires

S'il n'y a pas, il devrait y avoir vraiment, tant que les classes JDK de base ont ce concept absurde d'une opération «facultative» dans une interface.


Je pense qu'il est ridicule que vous implémentez la liste pour une classe que vous n'avez pas besoin de ajouter () méthode. Vous faites quelque chose de mal ici, mais je n'ai pas assez d'informations pour dire quoi.


@Erick: Le Doc de Java.Util.List indique clairement que l'opération est facultative. Il est valable de mettre en œuvre une liste en lecture seule qui ne prend pas en charge Ajouter ().


@Erik Voir java.util.collections.unmodifiablelist () Pour un exemple de quand cela est utile et acceptable.


Alors, qu'est-ce que cet objet fait lorsque vous appelez ajouter () ?


@Erik (de la Javadoc) "... tente de modifier la liste renvoyée, qu'il soit direct ou via son itérateur, aboutit à un non pris en chargeOrexception ."


4 Réponses :


11
votes

Bien que sur la surface, cela semble utile, il ne vous aiderait pas beaucoup. Comment utilisez-vous habituellement une liste? Je fais généralement quelque chose comme ceci: xxx pré>

Il y a déjà une indirection là-bas, donc si j'appelle list.add ("hi") code>, comment le compilateur devrait-il savoir que Cette implémentation spécifique de la liste ne prend pas en charge cela? p>

Que diriez-vous: P>

void populate(List<String> list) {
    list.add("1");
    list.add("2");
}


3 commentaires

Points justes. Cependant, je m'attendrais à ce qu'il serait possible que le compilateur ramasse des références quasi directes telles que votre premier exemple. Le second, j'admets, est beaucoup plus difficile, mais je suis sûr que des outils d'analyse de code statique seraient en mesure de gérer votre deuxième scénario référencé indirectement. Oh bien, merci pour votre réponse!


Je conviens que c'est possible (certains compilateurs, tels que Haskell, je crois) effectuer ce type de vérification, prouvant essentiellement que chaque type est utilisé en toute sécurité partout. Mais c'est un problème vraiment difficile, avec une utilisation limitée dans ce cas. Soyez juste prudent où vous passez votre liste - sans ajouter. :-)


Oublions le compilateur, qu'en est-il de l'IDE. (Ce n'est pas très différent de @NULLABLABLE et @notnull annotations)



4
votes

Vous pouvez le faire en utilisant AspectJ si vous le connaissez bien. Vous devez d'abord créer une coupe de points, puis donner un conseil ou déclarer des points d'erreur d'erreur / avertissement correspondant à ce point coupé. Bien sûr, vous avez besoin de votre propre interface d'annotation @unsupporteDoperationDoperation. J'ai donné un simple fragment de code à ce sujet.

// This the point-cut matching calls to methods annotated with your 
// @UnsupportedOperation annotation.
pointcut unsupportedMethodCalls() : call(@UnsupportedOperation * *.*(..));

// Declare an error for such calls. This causes a compilation error 
// if the point-cut matches any unsupported calls.
declare error: unsupportedMethodCalls() : "This call is not supported."

// Or you can just throw an exception just before this call executed at runtime
// instead of a compile-time error.
before() : unsupportedMethodCalls() {
    throw new UnsupportedOperationException(thisJoinPoint.getSignature()
        .getName());
}


3 commentaires

Je suis inconnu avec Aspecj; serait-ce que cela capturerait des utilisations de pouvant être traçées en arrière pour éventuellement / se référant définitivement à xxxlist (où xxxlist a son ajout () méthode annotée avec @unsupportedoperation )?


Aspectj utilise principalement un tissage de la compilation. C'est-à-dire que votre code est en train d'être compilé, le tisserand de Aspiration inserve certaines lignes de code en fonction des aspects. Si vous êtes capable de compiler votre classe de liste avec un aspect que j'ai écrit, cela fonctionne.


Merci, cela a l'air vraiment intéressant et j'ai voulu regarder plus loin dans Aspectj. Cependant, je ne vois pas comment cela pourrait résoudre le problème du code à l'aide d'une interface de l'objet concret, tel que le deuxième exemple de Jonathan.



2
votes

(2018) alors qu'il peut ne pas être possible de le détecter au moment de la compilation, il pourrait y avoir une alternative. I.e. L'IDE (ou d'autres outils) pourrait utiliser l'annotation pour avertir l'utilisateur qu'une telle méthode est utilisée.

il y a un billet pour cela: JDK-6447051

D'un point de vue technique, il ne devrait pas être beaucoup plus difficile de mettre en œuvre que des inspections qui détectent une utilisation illégale d'un @notnull ou d'un accessor @NULLABLE .


1 commentaires

Dommage que le billet soit fermé :(



0
votes