尝试将对象存储在该类型的变量中时,类型不兼容

我不明白为什么我可以返回一个实现接口的对象,但编译器在尝试将该对象存储在该类型的变量中时会抱怨。


简单的界面:


public interface ITest {


}

现在是一个实现该接口的简单类:


public class Test implements ITest {


}

好吧,我的理解是:ATest 是 ITest


现在问题是:


public class Tester {

    public static void parameterTest(ITest test) {


    }


    public static ITest returnValueTest() {

        return new Test(); // no compiler error here

    }


    public static void main(String[] args) {

        Test test = new Test();


        Tester.parameterTest(test);


        test = Tester.returnValueTest(); // compiler complains here

    }

}

该变量test来自类型Test,因此ITest。我可以Tester.parameterTest(ITest test)毫无怨言地把它传递给你。


但是尝试从变量中检索值Tester.returnValueTest()并将其放入变量中test会失败


Incompatible types: ITest cannot be converted to Test


尽管该方法返回一个Test编译器不会抱怨的对象。


为什么这样?为什么我可以返回一个Test对象并符合方法的返回类型ITest,但不能将这个返回的对象放入类型的变量中Test?


莫回无
浏览 102回答 2
2回答

慕少森

您没有返回一个Test对象,而是返回一个ITest实例。所有Test对象都实现ITest,但并非所有ITest实例都必须是Test对象。

繁花不似锦

说得更彻底一点:我的误解是,我认为对象的继承是“较小的适合较大的”的问题,但这是错误的思维方式。对象是关于接口的。Lifeform假设我们有一个可以的类grow(),并且说我们有一个Dog可以Lifeform的类bark()。以某种方式返回Lifeform“适合” Dog,但并非在所有情况下都满足规范,Dog因为并非每个都Lifeform可以bark()。由于“变量的类型”的含义无非是“放心,所包含的对象实现了该类型指定的接口”,将“不是 a”放入Lifeform类型Dog变量Dog中将违反这一保证。因此,在这种情况下,如果方法返回Lifeformby 签名,则不能将其放入类型变量中Dog,因为它不一定是 aable Dogto bark()。您可以向编译器保证,返回的对象是Dog通过强制转换返回的,那么它就不会抱怨。换句话说,通过强制转换,您可以告诉编译器他可以“放心,返回的Lifeform是一个Dog可以bark()”。因此,在我的特殊情况下,我可以返回 aTest因为它实现了接口ITest,并且每个人都可以确定,返回的对象将遵循 的规范ITest,因此编译器不会抱怨。但是,Test除非编译器确信该对象确实实现了Test. 所以我们必须投射它,一切都是彩虹和独角兽。Test test = (Test) Tester.returnValueTest();但我们应该小心这一点,因为它比仅使用正确类型的变量更容易出错。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java