我需要在java中使用父类的父对象强制转换类对象,同样的行为在C#中工作。
在C#中,我可以将类对象强制转换为父类的父对象。
在java中我无法实现这种行为。
如何在java中实现这一点?。提前感谢
答案 0 :(得分:1)
Java中的通用类型参数是不变。这意味着Iterable<Cat>
不是Iterable<Species>
的子类型(反之亦然),即使Cat
是Species
的子类型。
C#允许泛型类型将其类型参数声明为不变量,协变量或逆变量。如果您声明Foo<out T>
,则它将是协变的,即如果Foo<A>
是Foo<B>
的子类型,则A
是B
的子类型;如果您声明Foo<in T>
,它将是逆变的,即如果Foo<B>
是Foo<A>
的子类型,则A
是B
的子类型。声明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中,子类可以使用父类的方法,但是父类通常不能使用子类的方法,但是有一些技巧可以用于此目的。
一般情况下,人们可以使用父母的东西,但父母不允许使用孩子的东西,你可以这样认为。