Ich bin auf einen Fehler gestoßen, den ich nicht verstanden habe, als ich meinen eigenen Anmerkungsprozess erstellt habe. Beachten Sie, welche Art von Fehler Sie kennen.
Java
openjdk 10.0.2
Gradle
Gradle 4.10
Eclipse
4.8.0 (Photon)
※Pleiades
Ordnerstruktur
|-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-Projekt von foo
, bar
--bar
implementiert die Annotationsverarbeitung und foo
verwendet sie
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");
}
}
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();
}
clazz
-Element akzeptiert Class
-Instanzen bis zu MyInterface
ConcreteClass.java
package foo;
public class ConcreteClass extends AutoGeneratedClass {}
--Erstellen Sie "ConcreteClass", indem Sie "AutoGeneratedClass" erben, die automatisch durch die Annotationsverarbeitung generiert wird
Foo.java
package foo;
@MyAnnotation(clazz=ConcreteClass.class)
public class Foo {}
--Klasse, die tatsächlich "MyAnnotation" verwendet
clazz
-Element hat eine Class
-Instanz von ConcreteClass
.Das Kompilieren sieht folgendermaßen aus:
> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Error:Symbol kann nicht gefunden werden
public class ConcreteClass extends AutoGeneratedClass {
^
Symbol:Klasse AutoGeneratedClass
...\foo\src\main\java\foo\Foo.java:3:Error:Inkompatibler Typ: Class<ConcreteClass>Klasse<? extends MyInterface>Kann nicht konvertiert werden:
@MyAnnotation(clazz=ConcreteClass.class)
^
2 Fehler
ConcreteClass
konnte nicht kompiliert werden, da AutoGeneratedClass
, die automatisch generiert werden soll, nicht gefunden werden kannMyAnnotation.java
package foo;
...
public @interface MyAnnotation {
- Class<? extends MyInterface> clazz();
+ Class<?> clazz();
}
--Entfernen Sie die Obergrenze von "MyInterface", die im "clazz" -Element von "MyAnnotation" angegeben ist
Ergebnis kompilieren
> gradle :foo:compileJava
...
BUILD SUCCESSFUL in 3s
--Dann wird die Zusammenstellung bestanden. --Geheimnis
MyAnnotation.java
package foo;
...
public @interface MyAnnotation {
- Class<? extends MyInterface> clazz();
+ Class<? extends AutoGeneratedClass> clazz();
}
Ergebnis kompilieren
> gradle :foo:compileJava
...
BUILD SUCCESSFUL in 3s
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation(clazz=AutoGeneratedClass.class)
public class Foo {}
--MyAnnotation
hat die Obergrenze vonClass <? Extends MyInterface>
Ergebnis kompilieren
...
BUILD SUCCESSFUL in 4s
--Dies kompiliert auch --Interface-> Automatisch generierte Klasse-> Es scheint, dass ein Fehler auftritt, wenn es sich um eine Beziehung einer selbst erstellten Klasse handelt
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
public class Foo {
+ private Class<?> clazz = ConcreteClass.class;
}
ConcreteClass.class
Ergebnis kompilieren
> gradle :foo:compileJava
BUILD SUCCESSFUL in 3s
OtherAnnotation.java
package foo;
...
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OtherAnnotation {
Class<? extends MyInterface> clazz();
}
--Erstelle OtherAnnotation.java
mit der gleichen Definition wie MyAnnotation
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
+ @OtherAnnotation(clazz=ConcreteClass.class)
public class Foo {}
OtherAnnotation
zu Foo
hinzugefügtErgebnis kompilieren
> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Error:Symbol kann nicht gefunden werden
public class ConcreteClass extends AutoGeneratedClass {
^
Symbol:Klasse AutoGeneratedClass
...\foo\src\main\java\foo\Foo.java:4:Error:Inkompatibler Typ: Class<ConcreteClass>Klasse<? extends MyInterface>Kann nicht konvertiert werden:
@OtherAnnotation(clazz=ConcreteClass.class)
^
2 Fehler
OtherClass.java
package foo;
@OtherAnnotation(clazz=ConcreteClass.class)
public class OtherClass {}
Foo.java
package foo;
- @MyAnnotation(clazz=ConcreteClass.class)
+ @MyAnnotation
public class Foo {}
--OtherAnnotation
ist das gleiche wie das vorherige
Ergebnis kompilieren
> Task :foo:compileJava FAILED
...\foo\src\main\java\foo\ConcreteClass.java:3:Error:Symbol kann nicht gefunden werden
public class ConcreteClass extends AutoGeneratedClass {
^
Symbol:Klasse AutoGeneratedClass
...\foo\src\main\java\foo\OtherClass.java:3:Error:Inkompatibler Typ: Class<ConcreteClass>Klasse<? extends MyInterface>Kann nicht konvertiert werden:
@OtherAnnotation(clazz=ConcreteClass.class)
^
2 Fehler
Nach der Organisation der Ergebnisse verschiedener Versuche scheint ein Fehler aufzutreten, wenn die folgenden Bedingungen erfüllt sind:
Class
-Instanz wird im Annotation-Element angegeben.Class
-Instanz ist eine" selbst erstellte Klasse "in der hierarchischen Beziehung von" selbst erstellte Schnittstelle-> Klasse, die automatisch durch Annotationsverarbeitung generiert wird-> selbst erstellte Klasse ".Ich bin mir nicht sicher.