当前位置:  开发笔记 > 编程语言 > 正文

Java Covariants

如何解决《JavaCovariants》经验,为你挑选了4个好方法。

这是因为在Java成员变量不覆盖时,它们会影响(与方法不同).A和B都有变量x.由于c被声明为CovarientTest类型,因此getObj()的返回隐式为A,而不是B,因此得到A的x,而不是B的x.



1> Lawrence Dol..:

这是因为在Java成员变量不覆盖时,它们会影响(与方法不同).A和B都有变量x.由于c被声明为CovarientTest类型,因此getObj()的返回隐式为A,而不是B,因此得到A的x,而不是B的x.



2> Spoike..:

Java 不会覆盖字段(aka.属性或成员变量).相反,他们互相遮蔽.如果您通过调试器运行程序,您将x在任何类型的对象中找到两个变量B.

这是对正在发生的事情的解释.程序首先检索隐式类型的东西,A然后调用x假定来自的东西A.尽管它显然是一个子类型,但在您的示例中,类型的对象B是通过创建的SubCovariantTest,它仍然假设您在getObj()中返回隐式类型为A的内容.由于Java无法覆盖字段,因此测试将调用A.x而不是B.x.

CovariantTest c = new SubCovariantTest();
// c is assumed the type of CovariantTest as it is
// implicitly declared

System.out.println(c.getObj().x);
// In this method chain the following happens:

// c.getObj() will return object of type B
// BUT will assume it is an A

// c.getObj().x will return the x from A
// since in this context the compiler assumes 
// it is an A and make the call to A.x

它似乎是一个令人难以置信的陷阱,因为方法总是在Java中被覆盖(与C++和C#相比,它们不是).您通常不会遇到此问题,因为Java代码约定会告诉您永远不要直接访问字段.而是确保始终通过访问器方法(即getter)访问字段:

class A {
    private int x = 5;

    public int getX() { // <-- This is a typical accessor method
        return x;
    }
}

class B extends A {
    private int x = 6;

    @override
    public int getX() {
        // will be called instead even though B is implied to be A
        // @override is optional because methods in Java are always virtual
        // thus are always overridden
        return x;
    }
}

使此工作的代码如下:

c.getObj().getX();
// Will now call getX() in B and return the x that is defined in B's context.



3> 小智..:

将上面的A和B替换为:

class A {
    public int getX() { return 5; }
}

class B extends A {
    public int getX() { return 6; }
 }

这可能会回答你关于错误的问题;-)



4> starblue..:

在对象中有两个名为x的字段,一个来自A类,一个来自B类,它们隐藏了A中的字段.由于c的声明,字段x引用的是A中的字段.

在实践中,这不是一个问题,因为它是非常糟糕的风格

隐藏子类中的字段,

直接访问字段而不是通过方法.

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有