如何在Scala中使用Java注解?

huangapple go评论73阅读模式
英文:

How can I use a Java Annotation in Scala?

问题

以下是您提供的内容的翻译部分:

Java注解

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Trace {
    public String key() default "";
    public byte step() default 0;
    public String url() default "";
}

@SupportedAnnotationTypes("com.custom.annotations.Trace")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@AutoService(Processor.class)
public class TraceProcessor extends AbstractProcessor {

    // ...(其他部分未翻译)
}

Scala

import com.custom.annotations.Trace

@Trace(key = "ECI-12")
class Simulation1 extends Simulation {}

使用Java注解在Java源代码中时,Trace注解会被TraceProcessor处理,并生成一个文件。但是在Scala中进行相同操作时却不起作用。

英文:

I have a custom Java annotation which generates a file when test sources are compiled. But when I import this annotation into a Scala class and I use it in the same way that in Java, Scala is not processing it.

Java Annotation

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Trace {
    public String key() default "";
    public byte step() default 0;
    public String url() default "";
}

@SupportedAnnotationTypes("com.custom.annotations.Trace")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@AutoService(Processor.class)
public class TraceProcessor extends AbstractProcessor {

    public static final String DEFAULT_FILE_PATH = "target/";
    public static final String DEFAULT_FILE_NAME = "trazability.txt";

    private Messager messager;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        Set<? extends Element> annotatedElements = getTraceAnnotatedElements(roundEnv);
        if(annotatedElements.size() == 0) {
            return true; // If there is not annotation, fast exist.
        }

        System.out.println("Processing @Trace annotations...");
        try {
            generateTraceFile(annotatedElements);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);

        // get messager for printing errors
        messager = processingEnvironment.getMessager();
    }

    private Set<? extends Element> getTraceAnnotatedElements(RoundEnvironment roundEnv) {
        return roundEnv.getElementsAnnotatedWith(Trace.class);
    }

    private void generateTraceFile(Set<? extends Element> annotatedElements) throws FileNotFoundException {
        PrintWriter out = new PrintWriter(DEFAULT_FILE_PATH + DEFAULT_FILE_NAME);

        System.out.println("Annotated elements with @Trace: " + annotatedElements.size());
        for (Element element : annotatedElements) {
            if (element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.METHOD) {
                String key = element.getAnnotation(Trace.class).key();
                int step = element.getAnnotation(Trace.class).step();

                if(element.getKind() == ElementKind.METHOD) {
                    String className = ((TypeElement) element.getEnclosingElement()).getQualifiedName().toString();
                    String methodName = element.getSimpleName().toString();
                    System.out.println("Add " + element.getKind().name() + " with key: " + key + " step: " + step + " class: " + className + " method: " + methodName);
                    out.print(key + ";" + step + ";" + className + "." + methodName);
                } else {
                    String packageName = ((Symbol) element).getQualifiedName().toString();
                    String className = packageName + "." + element.getSimpleName().toString();
                    System.out.println("Add " + element.getKind().name() + " with key: " + key + " step: " + step + " class: " + className);
                    out.print(key + ";" + step + ";" +  className);
                }
                out.println();
            }
        }
        out.println();
        out.close();
        System.out.println("File trazability generated into target folder");
    }

    private void printError(Element element, String message) {
        messager.printMessage(Diagnostic.Kind.ERROR, message, element);
    }

}

Scala

import com.custom.annotations.Trace

@Trace(key = "ECI-12")
class Simulation1 extends Simulation {}

When I use the java annotation into a Java source then the Trace annotation is processed by TraceProcessor and a file is generated. But when I do the same with Scala it doesn't work.

答案1

得分: 2

在Scala代码中使用Java注解可能会导致不可预测的结果,其中大部分很可能根本无法工作。请不要在您的Scala代码中使用它们,因为这样做会引起Java和Scala开发者的反感。将您喜爱的Java世界中的库与Scala融合,可能不会带来Scala能够提供的最佳效果,反而会引发一系列在不同资源上很少考虑的问题。Scala有其自己的生态系统,最好尽量避免使用Java库,即使您在Java方面非常熟练,也应该优先考虑使用Scala库来解决问题。

Java注解通常用于简化Java冗长的语法和糟糕的类型系统所强制执行的样板代码。Scala拥有自己的元编程框架(黑盒宏、白盒宏、宏注解和隐式宏),以及许多其他抽象概念,例如强大的HKT类型系统和无所不在的隐式搜索机制。因此,对于大多数情况,您绝对不需要使用宏注解。

此外,针对您的问题可能存在Scala解决方案。如果您决定描述问题而不是贴出大量代码,其他人可以为您找到解决方案。

英文:

Usage of java annotations in scala code can lead to unpredictable results, most of them just simply won't work. Please don't use them in your Scala code, because by doing so you draw hate from both Java and Scala guys. Fusing your favorite libraries from java world with scala not yields you the best you can get from scala but raises a bunch of problems that are rarely considered on different resources. Scala has its own ecosystem, and it is better to avoid using java libraries as long you can solve problem with scala library even if you super proficient with java.

Java annotations commonly used to shave off boilerplate that is enforced by java verbose syntax and poor type system. Scala has own metaprogramming framework (blackbox macro, whitebox macro, macro annotations and implicit macro) and many other abstraction stuff such as potent type system with HKT and omnipotent implicit search mechanism. So, you definitely don't need macro annotations for most of the cases.

Moreover for your problem could exist a scala solution. Someone can find it for you if you decide to describe the problem rather than bring a wall of code instead.

答案2

得分: 0

Java的注解只能在Java编译器中工作,因为处理器需要与Java AST一起工作。你必须为Scala编写自己的宏注解,该注解使用与Java的注解处理器不兼容的编译器。请参阅此处:https://docs.scala-lang.org/overviews/macros/annotations.html

英文:

The Java annotation will only work with Java compilers since the processor needs to work with the Java AST. You must write your own macro annotation for Scala, which uses a compiler incompatible with Java's annotation processors. See here: https://docs.scala-lang.org/overviews/macros/annotations.html

huangapple
  • 本文由 发表于 2020年4月8日 00:21:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/61084674.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定