java - 如何将java泛型从一个方法应用到同一个类中的一个字段

标签 java

我有一个函数可以提供用给定注释注释的类映射

void <A extends Annotation> ImmutableMap<Class<?>, A> find(Class<A> annotation, String packageBase) {
    final ClassLoader loader = Thread.currentThread().getContextClassLoader();

    return ClassPath.from(loader).getTopLevelClassesRecursive(packageBase).stream()
            .filter(x -> x.load().getAnnotation(annotation) != null)
            .collect(Collectors.collectingAndThen(Collectors
                    .toMap(ClassPath.ClassInfo::load, x -> x.load().getAnnotation(annotation)), ImmutableMap::copyOf));
}

我想做一个带有缓存的通用提供者,就像下面的例子

@Singleton
public class AnnotatedClassProvider {
    private final Map<Class<? extends Annotation>, ImmutableMap<Class<?>, Object>> cache;
    private final String basePackage;

    public AnnotatedClassProvider(String basePackage) {
        this.basePackage = basePackage;
        this.cache = Maps.newHashMap();
    }

    public <A extends Annotation> ImmutableMap<Class<?>, A> get(Class<A> annotation) {
        ImmutableMap<Class<?>, A> cached = cache.get(annotation);
        if (cached != null)
            return cached;

        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
        cached = ClassPath.from(loader).getTopLevelClassesRecursive(basePackage).stream()
                .filter(x -> x.load().getAnnotation(annotation) != null)
                .collect(Collectors.collectingAndThen(Collectors
                        .toMap(ClassPath.ClassInfo::load, x -> x.load().getAnnotation(annotation)), ImmutableMap::copyOf));
        this.cache.put(annotation, cached);
        return (cached);
    }
}

我的问题:我找不到替换 Object 的方法通过通用 A就像在 get函数,对于以下 map :

private final Map<Class<? extends Annotation>, ImmutableMap<Class<?>, Object>> cache;

编辑:
当我没有指定 map 泛型但我必须在 get 方法中强制转换时,它会编译。有没有办法避免这种情况?

private final Map<Class<? extends Annotation>, ImmutableMap> cache;

我觉得应该是这样的

private final <A extends Annotation> Map<Class<A>, ImmutableMap<Class<?>, A>> cache;

最佳答案

没有强制转换似乎是不可能的,所以下面几行解决了我的问题:

private final Map<Class<? extends Annotation>, ImmutableMap> cache;

public <A extends Annotation> ImmutableMap<Class<?>, A> get(Class<A> annotation) {
    @SuppressWarnings("unchecked")
    ImmutableMap<Class<?>, A> cached = cache.get(annotation);
    ...
}

对于有趣的人,这就是我的提供者现在的样子

界面

public interface AnnotatedClassProvider {
    <A extends Annotation> ImmutableMap<Class<?>, A> get(Class<A> annotation) throws IOException;
}

抽象类

public abstract class AbstractAnnotatedClassProvider implements AnnotatedClassProvider {
    private final Map<Class<? extends Annotation>, ImmutableMap> cache;

    public AbstractAnnotatedClassProvider() {
        this.cache = Maps.newHashMap();
    }

    protected final <A extends Annotation> ImmutableMap<Class<?>, A> find(Class<A> annotation, @Nullable String basePackage) throws IOException {
        @SuppressWarnings("unchecked")
        ImmutableMap<Class<?>, A> cached = cache.get(annotation);

        if (cached != null)
            return cached;

        ClassPath classPath = ClassPath.from(Thread.currentThread().getContextClassLoader());

        ImmutableSet<ClassPath.ClassInfo> set = basePackage == null
                ? classPath.getAllClasses()
                : classPath.getTopLevelClasses(basePackage);

        cached = set.stream()
                .filter(x -> x.load().getAnnotation(annotation) != null)
                .collect(Collectors.collectingAndThen(Collectors
                        .toMap(ClassPath.ClassInfo::load, x -> x.load().getAnnotation(annotation)), ImmutableMap::copyOf));
        this.cache.put(annotation, cached);
        return (cached);
    }
}

实现

public final class Providers {
    public static AnnotatedClassProvider newBased(String basePackage) {
        return new AbstractAnnotatedClassProvider() {
            @Override
            public <A extends Annotation> ImmutableMap<Class<?>, A> get(Class<A> annotation) throws IOException {
                return super.find(annotation, basePackage);
            }
        };
    }

    public static AnnotatedClassProvider newSimple() {
        return new AbstractAnnotatedClassProvider() {
            @Override
            public <A extends Annotation> ImmutableMap<Class<?>, A> get(Class<A> annotation) throws IOException {
                return super.find(annotation, null);
            }
        };
    }
}

示例

@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface Controller {
    String value();
}

package com.test

@Controller("mainController")
public class Main {

    public static void main(String[] args) {
        AnnotatedClassProvider provider = Providers.newBased("com.test");
        Map<Class<?>, Controller> classes = provider.get(Controller.class);

        classes.forEach((x, y ) -> System.out.println(String.format("Class: %s annotated with %s with value %s",
                x.getName(), y.getClass().getName(), y.value())));
    }
}

输出:类:Main.java,用值为 mainController 的 Controller.class 注释

感谢所有评论。

关于java - 如何将java泛型从一个方法应用到同一个类中的一个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45232052/

相关文章:

java - 如何使用 sbt 将 java 库与 scala 一起使用?

java - libGDX、Box2D、碰撞和禁止空中跳跃

java - 从控制台读取不同类型的数字时减少代码重复

java - 从以编程方式打开 android 键盘获取文本

java - 两个非常长的整数相加

java - 如何将数字字符串转换为不同的 ArrayList

java - Android HttpClient 异步任务

java - 如果java是按值传递的,为什么我的对象在执行方法后会发生变化?

java - libgdx 如何检测冲突?

java - 如何进行简单的log4j配置?