为什么这段代码是正确的(编译器不抱怨它)

时间:2017-11-18 09:50:32

标签: java

我展示的是我写的例子,这是因为我不理解java puzzlers中的一些事情:

public class A {

    public A foo() {return new A();}

}

package library;

public class C extends A {
    static  class X extends A {}

    @Override
    public A foo(){
        return new X();
    }
}

package library;

public class B extends A {
    public static class Y extends A { }

    @Override
    public A foo(){
        return new Y();
    }

}

package client;

import library.A;
import library.B;
import library.C;

class Client {

    public static void main (String[] args){
        A b = new B();
        A c = new C();

        A bb = b.foo();
        A cc = c.foo();

        cc.hashCode(); // for me, it should causes compile error

    }
}

如您所见,foo方法是公开的。

A cc = c.foo(); - cc是非公开类型X的实例 A bb = b.foo(); - bb是公共类型Y

的实例

因此,当我们调用cc.hashCode()时,我们从来自不同包的非公共类型调用公共方法。为什么这是正确的?

为什么我这么认为

在java puzzlers的书中我找到了:

  

您无法合法地从另一个成员访问非公开类型的成员   封装

此外,

  

如果使用反射,可以避免这一整类问题   仅用于实例化并使用接口来调用方法   实现它们的类,并提供高级别的类型安全性。

任何人都可以解释一下吗?这在人类语言中意味着什么?

1 个答案:

答案 0 :(得分:1)

  

任何人都可以解释一下吗?这在人类语言中意味着什么?

说明:

  1. Java Puzzlers的书可能指的是其他东西。 (但谁知道:你还没有给我们上下文。)

  2. Java Puzzlers一书并非旨在成为Java语言的规范,教科书或教程。因此,我们不应该尝试使用它......我们不应将其解释视为完整或明确。

  3. 实际上你可以调用非公共类的方法,如果它们实现或覆盖在公共超类或非公共类的接口中声明的方法。

    < / LI>

    技术解释是

    A cc = c.foo();
    

    正在访问foo()中声明的A方法,该方法是public类。在非公共类中重写foo()的事实不会使重写方法不可访问。如果确实如此,那将违反可替代性原则,这是使多态性 1 起作用的原则。

    或者更简单地说。

    1. cA
    2. 的一个实例
    3. 每个A都有一个foo()方法。
    4. A::foo()声明可见的任何内容都必须能够在A的任何实例上查看该方法。
    5. 如果可以看到它,它可以调用它。
    6. 1 - 严格来说,我们在这里谈论的是亚型多态性。还有其他种类的多态性以及哪些LSP不适用。