Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.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
铸造不';t使用类在java中工作<;T>;及<;T扩展A>;_Java_Generics - Fatal编程技术网

铸造不';t使用类在java中工作<;T>;及<;T扩展A>;

铸造不';t使用类在java中工作<;T>;及<;T扩展A>;,java,generics,Java,Generics,我对Java编译器有一个奇怪的问题。代码如下: private <T extends IdentifiedBusinessTransversalEntity> T getOrCreateTransversalEntity(Class<T> classT, String id) { ...} private <T extends IdentifiedBusinessDSEntity> T getOrCreateDSEntity(Class&l

我对Java编译器有一个奇怪的问题。代码如下:

private <T extends IdentifiedBusinessTransversalEntity> T 
    getOrCreateTransversalEntity(Class<T> classT, String id) {
...}

private <T extends IdentifiedBusinessDSEntity> T
    getOrCreateDSEntity(Class<T> classT, String id) {
...}

public abstract  class IdentifiedBusinessDSEntity extends
        BusinessDSEntity implements IdentifiedEntity {
...}

public abstract class IdentifiedBusinessTransversalEntity extends
                BusinessTransversalEntity implements IdentifiedEntity {
 ...}

public <T extends IdentifiedEntity> T getOrCreate(Class<T> classT, String id)
{
    if (IdentifiedBusinessDSEntity.class.isAssignableFrom(classT))
    {
        return getOrCreateDSEntity(classT.asSubclass(IdentifiedBusinessDSEntity.class),id);
    } else if (IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT))
    {   //must cast explicitly to T here but works well just above and is exactly the same. Strange
        return (T) getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class),id);
    }
    return null;
}
private T
GetOrCreateTraversalEntity(类classT,字符串id){
...}
私家侦探
getOrCreateDSEntity(类classT,字符串id){
...}
公共抽象类IdentifiedBusinessDSEntity扩展
BusinessDSEntity实现标识性{
...}
公共抽象类标识的BusinessTransversalEntity扩展
BusinessTransversalEntity实现了IdentifiedEntity{
...}
公共T getOrCreate(类classT,字符串id)
{
if(IdentifiedBusinessDSEntity.class.isAssignableFrom(classT))
{
返回getOrCreateDSEntity(classT.asSubclass(IdentifiedBusinessDSEntity.class),id);
}else if(IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT))
{//这里必须显式地强制转换为T,但在上面工作得很好,并且完全相同。奇怪
return(T)getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class),id);
}
返回null;
}
我不明白为什么在
getOrCreate
函数中,编译器允许第一次返回而不使用
(t)
,但不允许第二次返回。错误是:

类型不匹配:无法从
IdentifiedBusinessTransversalEntity
转换为
T

应该可以:
getOrCreateTRansversalEntity
返回
IdentifiedBusinessTransversalEntity
的子类,该子类实现了
IdentifiedEntity

最奇怪的是,第一回还行,这是完全对称的。有什么区别吗?

我试试看。这个解释是基于观察而不是明确的知识,所以如果我被纠正了,不要感到惊讶。我认为您混淆的是
T
返回类型声明的含义。在我看来,这个返回声明正在创建一个全新的类型,而不是描述一个已经声明的类型。换句话说,您可以将Class1作为
Class1扩展ClassA
,但是当您返回
T扩展ClassA
时,您不是描述Class1,而是一个全新的类(或类型)。您不能期望这个新类与Class1相同,而是说您返回了一个ClassX,其中
ClassX扩展了ClassA
:Class1和ClassX不是相同的类

看起来您正在尝试使用缓存实现工厂设计模式。这段代码可以做到这一点,应该与上面的代码非常相似。假设工厂应该生成接口实现,则无需将返回类型声明为扩展接口的类,只需返回接口即可

public class Factory {

    interface I {}

    List<I> iCache = new ArrayList<I>();

    abstract class ClassA {}
    abstract class ClassB {}

    class Class1 extends ClassA implements I {}
    class Class2 extends ClassB implements I {}

    I getOrCreateTypeA() { 
        for( I cls: iCache ) {
            if( cls instanceof ClassA ) return cls;
        }
        Class1 cls = new Class1();
        iCache.add(cls);
        return cls;
    }
    I getOrCreateTypeB() { 
        for( I cls: iCache ) {
            if( cls instanceof ClassB ) return cls;
        }
        Class2 cls = new Class2();
        iCache.add(cls);
        return cls;
    }

    I getOrCreate(Class<?> cls) {
        if ( ClassA.class.isAssignableFrom(cls)) {
            return getOrCreateTypeA();
        } else if ( ClassB.class.isAssignableFrom(cls)) {
            return getOrCreateTypeB();
        }
        return null;
    }

    void run() {
        I classI1 = getOrCreate(Class1.class);
        System.out.println(classI1);
        I classI2 = getOrCreate(Class2.class);
        System.out.println(classI2);
        I classI3 = getOrCreate(Class1.class);
        System.out.println(classI3);
        System.out.println(iCache);
    }

    public static void main(String... args) {
        new Factory().run();
    }
}
公共类工厂{
接口I{}
List iCache=new ArrayList();
抽象类ClassA{}
抽象类ClassB{}
类Class1扩展ClassA实现I{}
类Class2扩展了类B实现I{}
I getOrCreateTypeA(){
对于(I cls:iCache){
如果(ClassA的cls实例)返回cls;
}
Class1 cls=新的Class1();
添加(cls);
返回cls;
}
I getOrCreateTypeB(){
对于(I cls:iCache){
如果(B类的cls实例)返回cls;
}
Class2 cls=新的Class2();
添加(cls);
返回cls;
}
I获取或创建(类cls){
if(ClassA.class.isAssignableFrom(cls)){
返回getOrCreateTypeA();
}else if(ClassB.class.isAssignableFrom(cls)){
返回getOrCreateTypeB();
}
返回null;
}
无效运行(){
I classI1=getOrCreate(Class1.class);
系统输出打印项次(1级);
I Class2=获取或创建(Class2.class);
系统输出打印LN(Class2);
I classI3=getOrCreate(Class1.class);
系统输出打印项次(3级);
系统输出打印项次(iCache);
}
公共静态void main(字符串…参数){
新工厂().run();
}
}

该代码不应编译

我相信您要么犯了一个错误,使您相信它是有效的,要么您的编译器中有bug。
getOrCreate
中的两个返回语句都为我提供了Eclipse4.5.1和JavaC1.8.0中的编译错误

解释 编辑:我更改了这个解释,我想我一开始误解了这个问题

在解释中,我将
getAndCreate
类型参数的名称更改为
C
,以避免与其他类型参数混淆

问题是在
asSubclass
方法中,类是
C
的子类的信息丢失;剩下的唯一信息是该类是例如
IdentifiedBusinessDSEntity
的子类

asSubclass
具有以下类型:

<U> Class<? extends U> asSubclass(Class<U> clazz)
这将是类型安全的,并且使用该返回类型,您的代码将在编译时不使用强制转换。但是,Java中不允许使用多个类型参数作为边界

代码 以下是我用来调查问题的代码:

class Test {
    interface IdentifiedEntity {}
    class BusinessDSEntity {}
    class BusinessTransversalEntity {}

    private <T extends IdentifiedBusinessTransversalEntity> T getOrCreateTransversalEntity(Class<T> classT, String id) {
        return null;
    }

    private <T extends IdentifiedBusinessDSEntity> T getOrCreateDSEntity(Class<T> classT, String id) {
        return null;
    }

    public abstract  class IdentifiedBusinessDSEntity 
        extends BusinessDSEntity implements IdentifiedEntity {}

    public abstract class IdentifiedBusinessTransversalEntity 
        extends BusinessTransversalEntity implements IdentifiedEntity {}

    public <C extends IdentifiedEntity> C getOrCreate(Class<C> classT, String id) {
        if (IdentifiedBusinessDSEntity.class.isAssignableFrom(classT)) {
            // Error here. Note that the type of s does not contain C.
            Class<? extends IdentifiedBusinessDSEntity> s = classT.asSubclass(IdentifiedBusinessDSEntity.class);
            return getOrCreateDSEntity(s, id);
        } else if (IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT)) {
            // Also error here
            return getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class), id);
        }
        return null;
    } 
}
类测试{
接口标识性{}
类BusinessDSEntity{}
类业务横向属性{}
私有T getOrCreateTransversalEntity(类classT,字符串id){
返回null;
}
私有T getOrCreateDSEntity(类classT,字符串id){
返回null;
}
公共抽象类标识的BusinessDSEntity
扩展BusinessDSEntity实现IdentifiedEntity{}
公共抽象类标识的BusinessTransversalEntity
扩展BusinessTransversalEntity实现IdentifiedEntity{}
公共C getOrCreate(类classT,字符串id){
if(IdentifiedBusinessDSEntity.class.isAssignableFrom(classT)){
//此处出错。请注意,s的类型不包含C。
class Test {
    interface IdentifiedEntity {}
    class BusinessDSEntity {}
    class BusinessTransversalEntity {}

    private <T extends IdentifiedBusinessTransversalEntity> T getOrCreateTransversalEntity(Class<T> classT, String id) {
        return null;
    }

    private <T extends IdentifiedBusinessDSEntity> T getOrCreateDSEntity(Class<T> classT, String id) {
        return null;
    }

    public abstract  class IdentifiedBusinessDSEntity 
        extends BusinessDSEntity implements IdentifiedEntity {}

    public abstract class IdentifiedBusinessTransversalEntity 
        extends BusinessTransversalEntity implements IdentifiedEntity {}

    public <C extends IdentifiedEntity> C getOrCreate(Class<C> classT, String id) {
        if (IdentifiedBusinessDSEntity.class.isAssignableFrom(classT)) {
            // Error here. Note that the type of s does not contain C.
            Class<? extends IdentifiedBusinessDSEntity> s = classT.asSubclass(IdentifiedBusinessDSEntity.class);
            return getOrCreateDSEntity(s, id);
        } else if (IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT)) {
            // Also error here
            return getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class), id);
        }
        return null;
    } 
}
class Test {
    interface IdentifiedEntity {}
    class BusinessDSEntity {}
    class BusinessTransversalEntity {}

    private <R extends IdentifiedEntity, T extends IdentifiedBusinessDSEntity> 
        R getOrCreateDSEntity(Class<T> classT, Class<R> classR, String id)
    {
        // Verify that classT really is subclass of classR.
        classT.asSubclass(classR);
        return null;
    }

    private <R extends IdentifiedEntity, T extends IdentifiedBusinessTransversalEntity> 
        R getOrCreateTransversalEntity(Class<T> classT, Class<R> classR, String id)
    {
        // Verify that classT really is subclass of classR.
        classT.asSubclass(classR);
        return null;
    }

    public abstract  class IdentifiedBusinessDSEntity 
        extends BusinessDSEntity implements IdentifiedEntity {}

    public abstract class IdentifiedBusinessTransversalEntity 
        extends BusinessTransversalEntity implements IdentifiedEntity {}

    public <C extends IdentifiedEntity> C getOrCreate(Class<C> classT, String id) {
        if (IdentifiedBusinessDSEntity.class.isAssignableFrom(classT)) {
            return getOrCreateDSEntity(classT.asSubclass(IdentifiedBusinessDSEntity.class), classT, id);
        } else if (IdentifiedBusinessTransversalEntity.class.isAssignableFrom(classT)) {
            return getOrCreateTransversalEntity(classT.asSubclass(IdentifiedBusinessTransversalEntity.class), classT, id);
        }
        return null;
    }
}