Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.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_Scala_Generics_Groovy_Type Inference - Fatal编程技术网

如何从Java中的通配符类推断相关的类型变量?

如何从Java中的通配符类推断相关的类型变量?,java,scala,generics,groovy,type-inference,Java,Scala,Generics,Groovy,Type Inference,我需要从带有两个类型参数的库中调用genericf函数,如下所示: public <D extends Data<K> & Property<P>, K extends Key<D>, P extends Object> void f(Class<D> classD, K key) { ... } 现在,我的程序需要调用f函数,但是,我有: Class<?> cla

我需要从带有两个类型参数的库中调用generic
f
函数,如下所示:

    public <D extends Data<K> & Property<P>, K extends Key<D>, P extends Object> 
    void f(Class<D> classD, K key) {
        ...
    }
现在,我的程序需要调用
f
函数,但是,我有:

    Class<?> clazz = ...;
    Object key = ...;
    // I know clazz and key can satisfy the constraints
    // but cannot see the exact class.

    f(clazz, key);
    // This is what I want to invoke but this statement alone
    // will lead to compile time failures.
Class clazz=。。。;
对象键=。。。;
//我知道clazz和key可以满足约束条件
//但看不到确切的类别。
f(clazz,key);
//这是我想调用的,但仅此语句
//将导致编译时失败。
我可以创建一些满足需求的本地接口,并将两个参数转换为它们,如下所示。它可以通过编译器,但会导致强制转换错误

    public interface MyData<P> extends Property<P>, Data<MyKey<P>> {
    }

    public interface MyKey<P> extends Key<MyData<P>> {
    }
公共接口MyData

扩展属性

,数据{ } 公共接口MyKey

扩展密钥{ }

因此,我的问题是,是否有可能从Java(或Groovy/Scala)中的通配符推断出正确的类型
D
K


谢谢你的帮助

没有任何方法可以从
Class
K
Object
推断
Class
。泛型通配符和对象类型实际上意味着编译器没有关于这些变量类型的任何附加信息

当然,当您尝试将
对象
强制转换为
MyKey
时,如果它不是一个对象,您将得到
ClassCastExceptions

但是如果您知道
clazz
是一个
key
是一个
MyBar
,给定一个扩展
Data
MyFoo
和一个扩展
key
MyBar
,您可以添加一些强制转换:

f((类)clazz,(MyBar)对象);
编译器将警告您类型安全,但这是传递
类和
对象的代价。

A
类不覆盖有界类型
,而
对象也不能覆盖有界
K扩展键。您可以在方法签名中指定这些类型(因为您不能在变量中声明它们):

公共类类型{
公开的
空f(D类,K键){
}
公共静电
void main(字符串[]args){
类型t=新类型();
类klazz=null;
K key=null;
t、 f(克拉兹,钥匙);
}
}
接口数据{}
接口属性{}
接口键{}
在groovy中,您可以动态删除以下类型:

class Types {

    def f(Class<?> classD, key) {
        "foobar"
    }

    static main(args) {
        def t = new Types()
        Class<?> klazz = null
        Object key = null
        assert t.f(klazz, key) == "foobar"
    }
}


interface Data<T> {}
interface Property<T> {}
interface Key<T> {}
类类型{
def f(D类,钥匙){
“foobar”
}
静态干管(args){
def t=新类型()
类klazz=null
对象键=空
断言t.f(klazz,key)=“foobar”
}
}
接口数据{}
接口属性{}
接口键{}
public class Types {

    public 
        <D extends Data<K> & Property<P>, K extends Key<D>, P extends Object> 
    void f(Class<D> classD, K key) {

    }

    public static 
        <D extends Data<K> & Property<P>, K extends Key<D>, P extends Object>
    void main(String[] args) {
        Types t = new Types();
        Class<D> klazz = null;
        K key = null;
        t.f(klazz, key);
    }

}

interface Data<T> {}
interface Property<T> {}
interface Key<T> {}
class Types {

    def f(Class<?> classD, key) {
        "foobar"
    }

    static main(args) {
        def t = new Types()
        Class<?> klazz = null
        Object key = null
        assert t.f(klazz, key) == "foobar"
    }
}


interface Data<T> {}
interface Property<T> {}
interface Key<T> {}