J'ai rencontré une erreur que je n'ai pas comprise lorsque j'ai créé mon propre processus d'annotation. Notez le type d'erreur que vous connaissez.
Java
openjdk 10.0.2
Gradle
Gradle 4.10
Eclipse
4.8.0 (Photon)
※Pleiades
Structure des dossiers
|-settings.gradle
|-build.gradle
|-foo/
| `-src/main/java/
| `-foo/
| |-Foo.java
| |-ConcreteClass.java
| |-MyAnnotation.java
| `-MyInterface.java
|
`-bar/
`src/main/
|-java/
| `-bar/
| `-MyProcessor.java
`-resources/
`-META-INF/services/
`-javax.annotation.processing.Processor
--Multi-projet de foo
, bar
--bar
implémente le traitement des annotations et foo
l'utilise
MyProcessor.java
package bar;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;
public class MyProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!annotations.isEmpty()) {
try {
JavaFileObject javaFileObject = this.processingEnv.getFiler().createSourceFile("foo.AutoGeneratedClass");
try (BufferedWriter writer = new BufferedWriter(javaFileObject.openWriter())) {
writer.write(
"package foo;\n" +
"import foo.MyInterface;\n" +
"public class AutoGeneratedClass implements MyInterface {}"
);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
return true;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Set.of("foo.MyAnnotation");
}
}
MyAnnotation
--Une classe appelée ʻAutoGeneratedClass qui implémente l'interface
MyInterface` est automatiquement générée.MyInterface.java
package foo;
public interface MyInterface {}
MyAnnotation.java
package foo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
Class<? extends MyInterface> clazz();
}
--Annotation à traiter
clazz
accepte les instances Class
jusqu'à MyInterface
ConcreteClass.java
package foo;
public class ConcreteClass extends AutoGeneratedClass {}
--Créer ConcreteClass
en héritant de ʻAutoGeneratedClass` généré automatiquement par le traitement des annotations
Foo.java
package foo;
@MyAnnotation(clazz=ConcreteClass.class)
public class Foo {}
--Classe qui utilise réellement MyAnnotation
--L'élément clazz
a une instance Class
de ConcreteClass
.
La compilation ressemble à ceci:
> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Erreur:Impossible de trouver le symbole
public class ConcreteClass extends AutoGeneratedClass {
^
symbole:Classe AutoGeneratedClass
...\foo\src\main\java\foo\Foo.java:3:Erreur:Type incompatible: Class<ConcreteClass>Classe<? extends MyInterface>Ne peut pas être converti en:
@MyAnnotation(clazz=ConcreteClass.class)
^
2 erreurs
ConcreteClass
car ʻAutoGeneratedClass`, qui devrait être généré automatiquement, est introuvable.javac
sans utiliser Gradle, mais l'erreur s'est toujours produite.MyAnnotation.java
package foo;
...
public @interface MyAnnotation {
- Class<? extends MyInterface> clazz();
+ Class<?> clazz();
}
--Supprimer la limite supérieure de MyInterface
spécifiée dans l'élément clazz
de MyAnnotation
Compiler le résultat
> gradle :foo:compileJava
...
BUILD SUCCESSFUL in 3s
MyAnnotation.java
package foo;
...
public @interface MyAnnotation {
- Class<? extends MyInterface> clazz();
+ Class<? extends AutoGeneratedClass> clazz();
}
--Change la limite supérieure de clazz
de MyInterface
à la classe auto-générée ʻAutoGeneratedClass`
Compiler le résultat
> gradle :foo:compileJava
...
BUILD SUCCESSFUL in 3s
--La compilation passera --Mystère
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation(clazz=AutoGeneratedClass.class)
public class Foo {}
--MyAnnotation
a la limite supérieure deClasse <? Etend MyInterface>
Compiler le résultat
...
BUILD SUCCESSFUL in 4s
--Cela compile également --Interface-> Classe auto-générée-> Il semble qu'une erreur se produise lorsqu'elle devient une relation de classe auto-créée
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
public class Foo {
+ private Class<?> clazz = ConcreteClass.class;
}
clazz
de MyAnnotation
--Utilisez ConcreteClass
sur le terrainConcreteClass.class
Compiler le résultat
> gradle :foo:compileJava
BUILD SUCCESSFUL in 3s
--Compiler les passes --Il semble qu'il n'y ait aucun problème à dépendre de la sous-classe de la classe générée automatiquement.
OtherAnnotation.java
package foo;
...
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OtherAnnotation {
Class<? extends MyInterface> clazz();
}
--Créez ʻOtherAnnotation.java avec la même définition que
MyAnnotation`
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
+ @OtherAnnotation(clazz=ConcreteClass.class)
public class Foo {}
--Ajout de ʻOtherAnnotation à
Foo`
clazz
vers MyAnnotation
a été suppriméCompiler le résultat
> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Erreur:Impossible de trouver le symbole
public class ConcreteClass extends AutoGeneratedClass {
^
symbole:Classe AutoGeneratedClass
...\foo\src\main\java\foo\Foo.java:4:Erreur:Type incompatible: Class<ConcreteClass>Classe<? extends MyInterface>Ne peut pas être converti en:
@OtherAnnotation(clazz=ConcreteClass.class)
^
2 erreurs
MyAnnotation
--Il semble que peu importe si l'annotation est la cible du traitement des annotations.OtherClass.java
package foo;
@OtherAnnotation(clazz=ConcreteClass.class)
public class OtherClass {}
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
public class Foo {}
--ʻOtherAnnotation` est le même que le précédent
@OtherAnnotation (clazz = ConcreteClass.class)
dans ʻOtherClass`, ce qui n'a rien à voir avec le traitement des annotations.Compiler le résultat
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Erreur:Impossible de trouver le symbole
public class ConcreteClass extends AutoGeneratedClass {
^
symbole:Classe AutoGeneratedClass
...\foo\src\main\java\foo\OtherClass.java:3:Erreur:Type incompatible: Class<ConcreteClass>Classe<? extends MyInterface>Ne peut pas être converti en:
@OtherAnnotation(clazz=ConcreteClass.class)
^
2 erreurs
--Même si la classe n'est pas la cible du traitement d'annotation directe, il semble qu'une erreur se produira si ConcreteClass.class
est référencé par l'élément d'annotation.
Si vous organisez les résultats de divers essais, il semble qu'une erreur se produira lorsque les conditions suivantes sont remplies?
--L'instance Class
est spécifiée dans l'élément d'annotation.
--L'instance Class
est une" classe auto-créée "dans la relation hiérarchique de" interface auto-créée-> classe générée automatiquement par le traitement d'annotations-> classe auto-créée ".
Classe
du côté de l'annotation est Classe <? Étend l'interface personnalisée>
.
--Exécuter avec le traitement des annotations OpenJDKJe ne suis pas sûr.