주석 처리 중 불분명한 오류 ※ 미해결

15502 단어 주석 처리Java
스스로 주석 처리를 했는데 잘 모르는 착오를 만났다.
아는 범위 내에 무슨 잘못을 적어라.

컨디션


Javaopenjdk 10.0.2GradleGradle 4.10Eclipse4.8.0 (Photon)Pleiades

이루어지다


폴더 구성
|-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
  • foo, bar의 다중 항목
  • bar 주석 처리를 실현했고 foo 주석 처리를 이용했다
  • 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 초대 처리를 목표로 하는 주석 처리 실현
  • MyInterface 인터페이스를 실현하는 클래스 자동 생성AutoGeneratedClass
  • 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 소자 수용MyInterface을 상한Class으로 하는 실례
  • ConcreteClass.java
    package foo;
    
    public class ConcreteClass extends AutoGeneratedClass {}
    
  • 계승 주석 처리 자동 생성AutoGeneratedClass으로 생성
  • Foo.java
    package foo;
    
    @MyAnnotation(clazz=ConcreteClass.class)
    public class Foo {}
    

  • 실제 사용ConcreteClass의 클래스
  • MyAnnotation 요소에 설정clazz 실례ConcreteClass
  • 분류도



    발생한 사건


    이걸 컴파일하면 아래가 이렇게 돼요.
    > gradle :foo:compileJava
    > Task :foo:compileJava FAILED
    ...\foo\src\main\java\foo\ConcreteClass.java:3: エラー: シンボルを見つけられません
    public class ConcreteClass extends AutoGeneratedClass {
                                       ^
      シンボル: クラス AutoGeneratedClass
    ...\foo\src\main\java\foo\Foo.java:3: エラー: 不適合な型: Class<ConcreteClass>をClass<? extends MyInterface>に変換できません:
    @MyAnnotation(clazz=ConcreteClass.class)
                                     ^
    エラー2個
    
  • 자동으로 생성해야 하는 ClassAutoGeneratedClass의 컴파일 실패
  • 를 찾지 못했습니다.

    다방면으로 시도하다


    Eclipse였으면 안 일어났을 거예요.

  • 이 프로젝트를 Eclipse에 직접 도입하고 주석 처리를 실행하면 오류가 발생하지 않는 이유는 무엇입니까?
  • Gradle을 사용하지 않고 원시적ConcreteClass 명령으로만 컴파일하려고 했지만 오류가 발생했다
  • 지정된 매개변수의 상한선을 중지하면 더 이상 발생하지 않습니다.


    MyAnnotation.java
    package foo;
    
    ...
    
    public @interface MyAnnotation {
    -   Class<? extends MyInterface> clazz();
    +   Class<?> clazz();
    }
    
  • javacMyAnnotation요소 중 지정된clazz의 상한선
  • 을 빼다
    컴파일 결과
    > gradle :foo:compileJava
    ...
    BUILD SUCCESSFUL in 3s
    
  • 시 컴파일 통과
  • 수수께끼
  • 상한선을 자동으로 생성된 클래스로 설정할 때 오류가 발생하지 않습니다


    MyAnnotation.java
    package foo;
    
    ...
    public @interface MyAnnotation {
    -   Class<? extends MyInterface> clazz();
    +   Class<? extends AutoGeneratedClass> clazz();
    }
    
  • MyInterface의 상한선을 clazz에서 자동생성류MyInterface
  • 로 변경
    컴파일 결과
    > gradle :foo:compileJava
    ...
    BUILD SUCCESSFUL in 3s
    
  • 컴파일 통과
  • 수수께끼
  • clazz를 자동으로 생성된 클래스로 지정해도 오류가 발생하지 않습니다


    Foo.java
    package foo;
    
    - @MyAnnotation(clazz=ConcreteClass.class)
    + @MyAnnotation(clazz=AutoGeneratedClass.class)
    public class Foo {}
    
  • AutoGeneratedClass의 한 측이 MyAnnotation의 상한 지정으로 설정
  • 컴파일 결과
    ...
    BUILD SUCCESSFUL in 4s
    
  • 컴파일도 통과
  • 인터페이스 -> 자동 생성 클래스-> 자체 제작 클래스로 변할 때 오류가 발생하기 쉽다
  • ConcertClass 자체에 의존하는 것은 문제가 없습니다.


    Foo.java
    package foo;
    
    - @MyAnnotation(clazz=ConcreteClass.class)
    + @MyAnnotation
    public class Foo {
    +   private Class<?> clazz = ConcreteClass.class;
    }
    

  • 요소 삭제Class<? extends MyInterface>MyAnnotation
  • 필드에서 사용clazz
  • ConcreteClass도 참고
  • 컴파일 결과
    > gradle :foo:compileJava
    BUILD SUCCESSFUL in 3s
    
  • 컴파일 통과
  • 자동으로 생성된 클래스에 의존하는 하위 클래스 자체는 문제가 없는 것 같다
  • 비처리 객체와 근사하게 참조할 수 없습니다.


    OtherAnnotation.java
    package foo;
    
    ...
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface OtherAnnotation {
        Class<? extends MyInterface> clazz();
    }
    
  • ConcreteClass.class와 같은 정의MyAnnotation
  • 만들기
    Foo.java
    package foo;
    
    - @MyAnnotation(clazz=ConcreteClass.class)
    + @MyAnnotation
    + @OtherAnnotation(clazz=ConcreteClass.class)
    public class Foo {}
    
  • OtherAnnotation.javaFoo
  • 추가
  • OtherAnnotation 한 측의 MyAnnotation 요소가 삭제되었습니다
  • 컴파일 결과
    > gradle :foo:compileJava
    > Task :foo:compileJava FAILED
    ...\foo\src\main\java\foo\ConcreteClass.java:3: エラー: シンボルを見つけられません
    public class ConcreteClass extends AutoGeneratedClass {
                                       ^
      シンボル: クラス AutoGeneratedClass
    ...\foo\src\main\java\foo\Foo.java:4: エラー: 不適合な型: Class<ConcreteClass>をClass<? extends MyInterface>に変換できません:
    @OtherAnnotation(clazz=ConcreteClass.class)
                                        ^
    エラー2個
    
  • clazz때와 동일한 오류 발생
  • 주석 처리 대상의 개편 여부와 무관
  • 주석 처리와 무관한 곳에 써도 안 된다


    OtherClass.java
    package foo;
    
    @OtherAnnotation(clazz=ConcreteClass.class)
    public class OtherClass {}
    
    Foo.java
    package foo;
    
    - @MyAnnotation(clazz=ConcreteClass.class)
    + @MyAnnotation
    public class Foo {}
    
  • MyAnnotation 이전과 동일
  • 주석 처리와 무관한OtherAnnotation에서 사용OtherClass
  • 컴파일 결과
    > Task :foo:compileJava FAILED
    ...\foo\src\main\java\foo\ConcreteClass.java:3: エラー: シンボルを見つけられません
    public class ConcreteClass extends AutoGeneratedClass {
                                       ^
      シンボル: クラス AutoGeneratedClass
    ...\foo\src\main\java\foo\OtherClass.java:3: エラー: 不適合な型: Class<ConcreteClass>をClass<? extends MyInterface>に変換できません:
    @OtherAnnotation(clazz=ConcreteClass.class)
                                        ^
    エラー2個
    
  • 직접 주석 처리 클래스가 아닌 경우에도 리더 컴포넌트에서 참조@OtherAnnotation(clazz=ConcreteClass.class)할 경우 오류가 발생할 수 있음
  • 증상을 정리하다


    여러 가지 시도의 결과를 정리하면 다음 조건을 만족할 때 틀릴 것 같다?
  • 모조 요소를 통해 실례를 지정ConcreteClass.class
  • 실례는 등급별 관계에서'자제 클래스'
  • , 즉'자제 인터페이스->주석 처리를 통해 자동으로 생성된 클래스->자제 클래스'
  • 모방측Class의 실례를 수신한 소자에 대한 정의Class
  • OpenJDK의 주석 처리를 통해 수행
  • 결론


    잘 모르겠어요.

    좋은 웹페이지 즐겨찾기