需要在java中使用父类的父对象强制转换类对象

时间:2017-08-17 12:49:43

标签: java c# generics casting

我需要在java中使用父类的父对象强制转换类对象,同样的行为在C#中工作。

在C#中,我可以将类对象强制转换为父类的父对象。

C#代码: enter image description here

在java中我无法实现这种行为。

Java代码: enter image description here

如何在java中实现这一点?。提前感谢

2 个答案:

答案 0 :(得分:1)

Java中的通用类型参数是不变。这意味着Iterable<Cat>不是Iterable<Species>的子类型(反之亦然),即使CatSpecies的子类型。

C#允许泛型类型将其类型参数声明为不变量,协变量或逆变量。如果您声明Foo<out T>,则它将是协变的,即如果Foo<A>Foo<B>的子类型,则AB的子类型;如果您声明Foo<in T>,它将是逆变的,即如果Foo<B>Foo<A>的子类型,则AB的子类型。声明IEnumerable的类型参数是协变的(即<out T>,因此IEnumerable<Cat>可以是IEnumerable<Species>的子类型。

使用通配符在Java中实现协方差和逆变。 ? extends通配符是协变的,而? super通配符是逆变的。 PECS 规则(生产者extends,消费者super)可引导您使用它们。 Iterable接口实际上是其类型参数T的生成者(它有一个返回Iterator<T>的方法,后者又有一个返回T的方法;以及没有方法将T作为参数);因此,它应始终与? extends通配符一起使用。因此,您应该使用Iterable<? extends Something>代替Iterable<Something>

所以,如果你像这样声明Animal

abstract class Animal extends Species {
    public Iterable<? extends Cat> elements();
}

然后你可以像这样使用它:

Iterable<? extends Species> childNodes;

childNodes = (currentElement != null) ? currentElement.elements() : null;

顺便说一下,C#中的IEnumerable接口同样实际上是它的类型参数的生成者,这就是他们将它声明为协变的原因。

答案 1 :(得分:-1)

Java和C#不同,让我用代码解释一下:

package test;
class A {
    {
        System.out.println(1);
    }
}
class B extends A {
    {
        System.out.println(2);
    }
}
class C extends B {
    {
        System.out.println(3);
    }
}
public class MainClass {
    public static void main(String[] args) {
        A c = new C();
    }
}

这里我们可以创建父类的对象,并使用子类实例化或初始化该对象,但反向不是真的。 即C c = new A();

此行将抛出java.lang.ClassCastException。

因为在java中,子类可以使用父类的方法,但是父类通常不能使用子类的方法,但是有一些技巧可以用于此目的。

一般情况下,人们可以使用父母的东西,但父母不允许使用孩子的东西,你可以这样认为。