在java中传递接口类型(不实现类类型)作为参数

时间:2013-04-17 09:21:05

标签: java oop class methods arguments

我正在开发一个“服务提供商”(非常类似于Google果汁)。 它的工作是将任意class_1或接口映射到* class_2 *,可以实例化并实现class_1(如果class_1是接口)或者是/ extends class_1(如果是class_1)不是一个界面。)

所以目前我有方法

public <T> void map(Class<T> key, Class<? extends T> service)

代码的问题是我可以将接口类型映射到接口类型,如

ServiceProvider sp = new ServiceProvider();
sp.map(IParent.class, IChild.class);

这完美编译没有错误(IChild扩展IParent)。 当然,后来,当我想:

IParent obj = sp.getService(IParent.class); //look for IParent mapping and instantiate the proper object

我收到了java.lang.InstantiationException。

所以问题是:

如何声明map()方法,以便编译器检查第二个参数是类实现或扩展第一个参数而不是接口? (重点是编译时错误。我已经知道如何在运行时检查)

感谢。 PS:是的 - 搜索了很多,几乎没有发现。

UPD: 谢谢大家的时间。 也许关于这一切的更多话语: 目标是开发机制(ServiceProvider类),它将帮助我避免在我的应用程序中紧密耦合,硬依赖。 所以我开发/采用了以下理念: “如果你想提供'单位'(可重复使用的软件) - 声明所有公共接口; 实施是您的私营企业,我们根本不关心; 如果有人想使用您的设备,他们应该从ServiceProvider请求它 1.在启动时,他们使用sp.map(IYuorInterface.class,TheClassImplementingIt.class); 2. IYuorInterface obj = sp.getService(IYuorInterface.class); 你负责使TheClassImplementingIt类'可实例化'(构造函数,安全性,类不是抽象等);如果不是 - 可以获得运行时异常。

有什么好处?

很明显 - 在任何给定时间,任何其他开发人员都可以重新实现IYuorInterface映射它与ServiceProvider,然后所有应用程序将使用它而无需更改单行代码。 (最简单的情况是需要它 - 单元测试)

所以我的观点/问题是:map()方法中的第二个参数必须是Class类型,它表示一个Class,而不是Interface,它应该与第一个参数“赋值兼容”。

换句话说,当我做map(ISomeIterface.class,Something.class)时; Something的对象(实例)应该像这样使用:

ISomeIterface obj = sp.getService(ISomeIterface.class);
//or in other words, just for example -- the Something can be used like this:
ISomeIterface obj = new Something();

这就是为什么工厂,如某些答案所暗示的那样不可接受,ServiceProvider类已经是一种“工厂”


..似乎Java的Class对象同时代表了类和接口,并且在编译时没有办法区分真正的类或接口..

但无论如何 - 感谢所有人。

3 个答案:

答案 0 :(得分:0)

您可以使用

查明Class是否是具体的,可实例化的类
public boolean isConcrete(Class<?> input)
{
    if (input.isInterface())
         return false;

    if (Modifier.isAbstract(input.getModifiers()))
         return false;

    return true;
}

答案 1 :(得分:0)

据我所知,如果Class对象代表一个可实现的类,则无法在编译时检查。

即使在类的情况下,它也可能是抽象的,或者它可能缺少一个无参数的构造函数。

作为替代方案,我建议您使用Factory对象而不是类本身。

答案 2 :(得分:0)

如果不是第二个参数,你可以改为通过工厂。

interface IInterface{
    void go();
}

class IInterfaceImpl implements IInterface{
    public void go(){}
}

interface Factory<T>{
    T createInstance();
}

class FactoryImpl implements Factory<IInterface>{

    @Override
    public IInterface createInstance() {
        //you need to return an instance of IInterface, which can only be a class
        return new IInterfaceImpl();
    }
}