Java Generics限制接口

tor*_*omp 10 java generics interface

我不确定这是否可能,但我想要完成的是:

public static <A,B extends SomeClass & A> B makeB(A thing) {...}
Run Code Online (Sandbox Code Playgroud)

本质上,使用反射/生成驱动的进程,我想提供类型B的东西,其中B是类SomeClass并实现接口A,而A是用户通过泛型提供的.

我不是在询问生成B的机制 - 我已经掌控了这一点.我正在寻找的是一种将泛型类型参数限制<A>为接口而不是类的方法,以便我可以使用语法B extends SomeClass & A来实现清洁类型安全.

这可能吗?有人知道这个问题的替代方法吗?


编辑:我想我没有非常清楚地表达自己,因为它似乎在评论中引起了混淆:

B旨在成为通配符的占位符,以便客户端可以获得单个对象,该对象既是a SomeClassA不必基于信任进行转换.客户端将不能访问到实现的实际类的名称SomeClassA,因为它会在编译时产生的,因此对于类型安全性这个问题.

Pau*_*ora 5

强加这样的编译时限制是不可能的.通用类型参数是参考类型的替身; 它们不区分类类型和接口类型.类型参数声明中的附加边界必须是接口类型这一事实仅仅是偶然的 - 您利用此作为将类型作为接口的方法的策略是巧妙的,但它被类型参数不能使用的限制所击败在多个边界.

您唯一的选择是使用Class.isInterface()类似Louis Wasserman 指出的运行时检查,或者让调用者对其传递的内容负责.无论哪种方式,请务必清楚地记录方法的期望和行为.


B旨在成为通配符的占位符,以便客户端可以获得单个对象,该对象既是a SomeClassA不必基于信任进行转换.客户端将不能访问到实现的实际类的名称SomeClassA

这似乎与我相矛盾.没有必要声明B调用者是否不可能知道它的评估结果.请记住:泛型方法的调用者提供其类型参数.因此,调用者决定B没有任何基础可以只是猜测 - 这永远不会是类型安全的.

看起来你真正希望你的方法返回的是某种类型既是a SomeClass又是a A,但这很棘手,因为它们不共享一个常见的超类型:

public static <A> SomeClass&A makeSomeClass(A thing) {...}
Run Code Online (Sandbox Code Playgroud)

(这是用于演示目的的无意义语法)

作为解决方法,请考虑表示a SomeClass和某些接口类型的替代方法.例如,候选接口可以有一个返回的常用方法SomeClass:

public interface IsSomeClass {
    SomeClass asSomeClass();
}

public interface Foo extends IsSomeClass { }
Run Code Online (Sandbox Code Playgroud)

的实施asSomeClass实际上将只返回this.然后你可以这样做:

public static <A extends IsSomeClass> A makeSomeClass(Class<A> type) {...}
Run Code Online (Sandbox Code Playgroud)

并且该方法的调用者将能够将返回的对象用作以下任一类型:

final Foo foo = makeSomeClass(Foo.class);
final SomeClass someClass = foo.asSomeClass();
Run Code Online (Sandbox Code Playgroud)

如果无法修改接口本身,那么另一个选择是使用包装类和组合:

final class SomeClassWrapper<A> {

    private final SomeClass someClass;
    private final A a;

    //constructor and getters, etc.
}
Run Code Online (Sandbox Code Playgroud)

并且您的方法将返回一个包装器实例,将实现实例分配给两者 someClass并且a:

public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}
Run Code Online (Sandbox Code Playgroud)