当前位置: 首页 > 面试题库 >

实施注释的用例

羊舌源
2023-03-14
问题内容

什么是实现注释的有效用例?

在设计主要基于注释的配置系统时,我有时需要创建实现代码生成或程序配置的注释的类。

另一种选择是将批注中包含的数据镜像到DTO中,这似乎是一项开销。

这是一个例子:

public enum IDType {
    LOCAL,
    URI,
    RESOURCE;
}

@Documented
@Target( { METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Id {
    /**
     * @return
     */
    IDType value() default IDType.LOCAL;
}

与实施

public class IdImpl implements Id{

    private final IDType idType;

    public IdImpl(IDType idType){
        this.idType = idType;
    }

    @Override
    public IDType value() {
        return idType;
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return Id.class;
    }

}

我为此收到编译器警告,但是对于许多用例来说,它似乎是一个有效的工具。

上面示例的警告是

注释类型Id不应用作IdImpl的超级接口

编辑:

我刚刚从Guice找到了这个例子:

bind(CreditCardProcessor.class)
    .annotatedWith(Names.named("Checkout"))
    .to(CheckoutCreditCardProcessor.class);

从Names中查看此Javadoc。

有谁知道为什么存在此限制或有其他用例的信息?


问题答案:

我从没有在实践中使用过它,但是得到的是,您可以使用类代替注释。

让我们创建一个人工的例子。假设我们有一个文档生成器。它@Docu从给定的类中读取注释并打印description属性。像这样:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;

public class DokuGenerator {

    public static void main(String[] args) throws Exception {
        new DokuGenerator(StaticClass.class, StaticClass2.class);
    }

    public DokuGenerator(Class<?>... classesToDokument) throws Exception {
        List<Docu> documentAnnotations = getDocumentAnnotations(classesToDokument);
        printDocumentation(documentAnnotations);
    }

    private List<Docu> getDocumentAnnotations(Class<?>... classesToDokument)
            throws Exception {
        List<Docu> result = new ArrayList<Docu>();
        for (Class<?> c : classesToDokument)
            if (c.isAnnotationPresent(Docu.class))
                result.add(c.getAnnotation(Docu.class));
        return result;
    }

    private void printDocumentation(List<Docu> toDocument) {
        for (Docu m : toDocument)
            System.out.println(m.description());
    }

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Docu {
    String description();
}

@Docu(description = "This is a static class!")
class StaticClass {
}

@Docu(description = "This is another static class!")
class StaticClass2 {
}

印刷品:

This is a static class!  
This is another static class!

我们现在想要完成的是,一个类不仅可以被静态注释,而且可以将运行时信息添加到文档中。@Docu大多数时候我们很高兴使用注释,但是在某些特殊情况下,我们需要特殊的文档。我们可能想为某些方法添加性能文档。我们可以通过让一个类实现注释来做到这一点。生成器首先检查注释,如果不存在,则检查类是否实现了注释。如果是这样,它将类添加到注释列表中。

像这样(生成器中只有两行代码):

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DokuGenerator {

    public static void main(String[] args) throws Exception {
        new DokuGenerator(StaticClass.class, StaticClass2.class,
                DynamicClass.class);
    }

    public DokuGenerator(Class<?>... classesToDokument) throws Exception {
        List<Docu> documentAnnotations = getDocumentAnnotations(classesToDokument);
        printDocumentation(documentAnnotations);
    }

    private List<Docu> getDocumentAnnotations(Class<?>... classesToDokument)
            throws Exception {
        List<Docu> result = new ArrayList<Docu>();
        for (Class<?> c : classesToDokument)
            if (c.isAnnotationPresent(Docu.class))
                result.add(c.getAnnotation(Docu.class));
            else if (Arrays.asList(c.getInterfaces()).contains(Docu.class))
                result.add((Docu) c.newInstance());
        return result;
    }

    private void printDocumentation(List<Docu> toDocument) {
        for (Docu m : toDocument)
            System.out.println(m.description());
    }

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Docu {
    String description();
}

@Docu(description = "This is a static class!")
class StaticClass {
}

@Docu(description = "This is another static class!")
class StaticClass2 {
}

class DynamicClass implements Docu {

    public DynamicClass() {
        try {
            Thread.sleep((long) (Math.random() * 100));
        } catch (InterruptedException e) {
            // ignore exception to make debugging a little harder
        }
    }

    @Override
    public String description() {
        long millis = System.currentTimeMillis();
        new DynamicClass();
        millis = System.currentTimeMillis() - millis;
        return "This is a dynamic class. I run on "
                + System.getProperty("os.name")
                + ". The construction of an instance of this class run for "
                + millis + " milliseconds.";
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return Docu.class;
    }

}

输出为:

This is a static class!  
This is another static class!  
This is a dynamic class. I run on Windows XP. The construction of an instance of this class run for 47 milliseconds.

您没有太多更改代码生成器,因为您可以使用该类代替注释。

其他示例谁可能是使用注释或XML作为配置的框架。您可能有一个处理注释的处理器。如果使用XML作为配置,则可以生成实现注释的类的实例,并且您的处理器可以对它们进行处理,而无需进行任何更改!(当然,还有其他方法可以达到相同的效果,但这是一种实现方法)



 类似资料:
  • 问题内容: 我的以下字段带有,指定了默认值: 如果该属性存在,该代码将字段的值正确初始化为系统属性“ tolerance.percentage”。如果不存在,则默认为25。 不过,我想进一步加强此int字段的最小值和最大值,因为它表示一个整数百分比小于100,而且墨菲定律意味着某人(可能是我)可以从外部对属性进行配置,而我应用程序将在运行时开始做奇怪的事情,这对于我来说太晚了。如果在应用程序启动时

  • 我有一把刀: 问题是,当我试图使用DAO进行加载调用时,使用DynamoDBMapper以field d1作为哈希键来获取项目,它会抛出一个DynamoDBExc0019,说:为公共DAO. getField2()找到了空键,但实际上表的值对应于field d2。问题,这是因为Lombok注释而不是手动突变代码,还是一般来说我们一起使用Lombok和DynamoDBAnnotions?

  • Storm 使用 CGroup 来限制 worker 的资源使用, 以保证公平和 QOS. 请注意:CGroups 目前仅支持 Linux 平台(内核版本 2.6.24 及更高版本) 设置 要使用 CGroups, 请确保正确安装 cgroups 并配置 cgroup.有关设置和配置的更多信息, 请访问: https://access.redhat.com/documentation/en-US/

  • 问题内容: 是否有注释声明某个方法即使是公共的也不会包含在JavaDocs中? 就像是: 附言:我了解这里有关API的要点,但是这些方法只是“不受支持”。它们可以工作(并且必须是公共的,以便从其他软件包访问),但是我们不希望在它们的功能与受支持的使用场景无关时,对其进行记录并回答有关如何使用它们的问题。好的设计可能意味着将它们移到另一个类,但是它们在逻辑上引用了该类中的数据。 问题答案: 如果您使

  • 我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?

  • 问题内容: 我尝试实现冒泡排序,但是不确定它是否正确。如果您可以看一下它,并且它是气泡式的,并且可以通过更好的方式完成,请不要害羞。这是代码: 问题答案: 这是冒泡排序的正常实现,似乎还可以。可以进行几种优化,但是总体思路是相同的。这里有一些想法: 如果在内循环中未执行任何交换时,外循环有一个迭代,则中断,无用继续 在外循环的每次迭代中,交换内循环的方向-从左至右执行一次,然后从右至左执行一次(这