在java中将接口类型(不是实现类类型)作为参数传递
我正在开发一个“服务提供商”(非常类似于谷歌果汁)。 它的工作是将任意类\ 1或接口映射到*类\ 2*,该类\ 2*可以实例化并实现类\ 1(如果类\ 1是接口)或是/扩展类\ 1(如果类\ 1不是接口) 所以现在我有办法在java中将接口类型(不是实现类类型)作为参数传递,java,oop,class,methods,arguments,Java,Oop,Class,Methods,Arguments,我正在开发一个“服务提供商”(非常类似于谷歌果汁)。 它的工作是将任意类\ 1或接口映射到*类\ 2*,该类\ 2*可以实例化并实现类\ 1(如果类\ 1是接口)或是/扩展类\ 1(如果类\ 1不是接口) 所以现在我有办法 public <T> void map(Class<T> key, Class<? extends T> service) 这可以完美地编译,不会出现错误(IChild扩展了IParent)。 当然,稍后,当我想: IParent obj
public <T> void map(Class<T> key, Class<? extends T> service)
这可以完美地编译,不会出现错误(IChild扩展了IParent)。
当然,稍后,当我想:
IParent obj = sp.getService(IParent.class); //look for IParent mapping and instantiate the proper object
我收到java.lang.InstanceionException
所以问题是:
如何声明map()方法,使编译器检查第二个参数是否是实现或扩展第一个参数的类,而不是接口?
(重点是获取编译时错误。我已经知道如何在运行时检查此错误)
谢谢。
PS:是的,谷歌搜索了很多,几乎什么也没找到
UPD.:
谢谢大家抽出时间。
也许再多说几句,这是怎么回事:
目标是开发一种机制(ServiceProvider类),它将帮助我避免应用程序中的紧耦合、硬依赖。
因此,我制定/采用了以下理念:
“如果你想交付一个‘单元’(一个可重用的软件)——声明所有公共接口;
执行是你的私事,我们一点也不在乎;
如果有人想使用您的设备,他们应通过以下方式向服务提供商请求:
1.在启动时,他们使用sp.map(IYuorInterface.class,实现it.class的类);
2.iyuornterface obj=sp.getService(iyuornterface.class);
您负责使ClassImplementingIT类“可实例化”(构造函数、安全性、类不是抽象的等等);如果不是,则可以获取运行时异常
好处是什么
很明显,在任何给定时间,任何其他开发人员都可以重新实现IYuorInterface,并将其映射到ServiceProvider,然后所有应用程序都将使用它,而无需更改一行代码。
(需要时最简单的情况是单元测试)
所以我的观点/问题是:map()方法中的第二个参数必须是表示类的Class类型,而不是接口,并且应该与第一个参数“赋值兼容”
换句话说,当我进行映射时(isometerface.class,Something.class);某物的对象(实例)应该可以像这样使用:
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的类对象似乎同时代表类和接口,在编译时无法区分是真正的类还是接口
但是无论如何——感谢大家。您可以使用
public boolean isConcrete(Class<?> input)
{
if (input.isInterface())
return false;
if (Modifier.isAbstract(input.getModifiers()))
return false;
return true;
}
public boolean isConcrete(类输入)
{
if(input.isInterface())
返回false;
if(Modifier.isAbstract(input.getModifiers()))
返回false;
返回true;
}
据我所知,无法在编译时检查类
对象是否表示可实例化的类
即使在类的情况下,它也可能是抽象的,或者可能缺少无参数构造函数
作为替代,我建议您使用工厂对象而不是类本身。如果您可以传递工厂而不是第二个参数,该怎么办
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();
}
}
接口界面{
void go();
}
类IIinterfaceImpl实现IIinterface{
public void go(){}
}
接口工厂{
T createInstance();
}
类FactoryImpl实现工厂{
@凌驾
公共接口createInstance(){
//您需要返回一个IInterface实例,它只能是一个类
返回新的IInterfaceImpl();
}
}
您已经声明了map(),因此第二个参数是类实现或扩展第一个参数。InstanceionException显示创建实例时出现问题(例如,没有空构造函数)。您应该提供getService()的源代码,IParent和堆栈跟踪。我认为您在这方面运气不佳:有时,编译器不可能知道第二个参数的确切值,例如,sp.map(IParent.class,someMethodThatReturnsAssderivedFromiParent());
将编译,但返回值直到运行时才知道。我认为在运行时检查第二个参数是最好的选择。我不明白。如果实现是您的业务,为什么客户端必须提供实现类?这是运行时;OP需要编译时”(关键是要得到编译时错误。我已经知道如何在运行时检查它)“@TheCat这是运行时检查,我99%肯定他已经知道了。
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();
}
}