Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中将接口类型(不是实现类类型)作为参数传递_Java_Oop_Class_Methods_Arguments - Fatal编程技术网

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

在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

我正在开发一个“服务提供商”(非常类似于谷歌果汁)。 它的工作是将任意类\ 1或接口映射到*类\ 2*,该类\ 2*可以实例化并实现类\ 1(如果类\ 1是接口)或是/扩展类\ 1(如果类\ 1不是接口)

所以现在我有办法

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();
    }
}