简体   繁体   English

Java编译器在看到关键字extends时会做什么?

[英]What does the Java compiler do when it sees the keyword extends?

Consider the following code. 请考虑以下代码。

A.java, main package: A.java,主要包装:

package pkgs.main;

public class A {
    protected int x;
}

B.java, test package: B.java,测试包:

package pkgs.test;
import pkgs.main.A;

public class B extends A {
}

When the javac compiler is run, does it do something roughly like this: 当运行javac编译器时,它是否像这样做:

A.java, main package: A.java,主要包装:

package pkgs.main;

public class A {
    protected int x;
}

B.java, test package: B.java,测试包:

package pkgs.test;
import pkgs.main.A;

public class B extends A {  
    // Some "flag/code" that says:
    // Must be aware that the following new and seperate copy of x 
    // has originated from class A, which is inside a package called main.
    protected int x;
}

The reason why I ask is that I'm trying to understand if it's essential that a subclass must be aware of all of the "properties/attributes" of its inherited members, in order to operate. 我之所以要问的是,我试图了解子类必须知道其继承成员的所有“属性/属性”才能运行。 If that is true, then would this kind of programming inheritance differ slightly from inheritance found in the "real world"? 如果这是真的,那么这种编程继承会与“现实世界”中的继承略有不同吗? For example, I inherit various properties from my parents, but I can be completely ignorant of all of this information. 例如,我从父母那里继承了各种属性,但我完全不知道所有这些信息。 (Say if my parents were to pass away, I could continue to operate.) Whereas, I wonder if Java's inheritance isn't independent in this sense, if a child subclass must always be aware of where it got its inherited members from, in order to correctly operate. (如果我的父母要去世,我可以继续操作。)然而,我想知道Java的继承在这个意义上是不是独立的,如果子类必须始终知道它从哪里得到它的继承成员,为了正确操作。

The thing is, I get confused when reading about inheritance in programming books. 问题是,在阅读编程书籍中的继承时,我感到困惑。 They provide examples involving real world objects such animals and cats and dogs etc, but based on the paragraph above, I'm wondering if there is a subtle "mechanism difference" between Java inheritance, and inheritance examples given in Java books that involve these types of real world objects. 它们提供了涉及动物,猫和狗等现实世界对象的示例,但基于上面的段落,我想知道Java继承与Java书籍中涉及这些类型的继承示例之间是否存在微妙的“机制差异”现实世界的对象。

The problem that I'm having with Java is that I don't understand why I'm allowed to do the following. 我与Java有关的问题是我不明白为什么我被允许执行以下操作。 The code below is some simple "calling code" in a "Main class" involving the two classes (A and B) already defined above. 下面的代码是“主类”中的一些简单的“调用代码”,涉及上面已经定义的两个类(A和B)。

Main.java, main package: Main.java,主要包:

package pkgs.main;
import pkgs.test.B;

// Just some method inside the "main class"
void method() {
    B b = new B();
    b.x ++;  //   <--- why is this allowed?
}

This "calling code" is inside a package called main, and class B is defined inside a different package called test. 这个“调用代码”在一个名为main的包中,而类B在一个名为test的不同包中定义。 This calling code is not extending class B, so why does Java allow access to B's protected member x? 这个调用代码没有扩展B类,那么为什么Java允许访问B的受保护成员x?

Is the explanation because the protected member x was originally declared inside class A, which is in the same package as the calling code? 的解释是,因为受保护的成员x原本A级,这在同一个包调用代码内声明的? If true, would that roughly match my earlier thoughts, where I said this about class B: 如果是真的,那么这大致符合我之前的想法,我在这里谈到了B类:

public class B extends A {  
    // Some "flag/code" that says:
    // Must be aware that the following new and seperate copy of x 
    // has originated from class A, which is inside a package called main.
    protected int x;
}

What does the Java compiler do when it sees the keyword extends? Java编译器在看到关键字extends时会做什么?

Nothing in your case. 在你的情况下没有。

This calling code is not extending class B, so why does Java allow access to B's protected member x? 这个调用代码没有扩展B类,那么为什么Java允许访问B的受保护成员x?

It's about accesibility. 这是关于可访问性的。 According to the Java Language Specification (see JLS7: http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf ) 根据Java语言规范(参见JLS7: http ://docs.oracle.com/javase/specs/jls/se7/jls7.pdf)

6.6.1 Determining Accessibility 6.6.1确定可访问性

... ...

Otherwise, if the member or constructor is declared protected, then access is permitted only when one of the following is true: 否则,如果成员或构造函数被声明为protected,则只有在满足以下条件之一时才允许访问:

  • Access to the member or constructor occurs from within the package containing the class in which the protected member or constructor is declared. 从包含声明受保护成员或构造函数的类的包中发生对成员或构造函数的访问。

  • Access is correct as described in §6.6.2. 如第6.6.2节所述,访问是正确的。

... ...

you can access the protected field 'x' from the same package. 您可以从同一个包中访问受保护的字段“x”。 But if you declare a new field 'x' in class 'B' (which hides 'A.x') then you can't access 'x' (in the form b.x++; ) from the package 'main'. 但是如果你在类'B'中声明一个新字段'x'(它隐藏'A.x'),那么你就不能从'main'包中访问'x'(格式为b.x++; )。

// Some "flag/code" that says:
// Must be aware that the following new and seperate copy of x 
// has originated from class A, which is inside a package called main.
protected int x;

No. There isn't a 'new and separate x'. 没有。没有'新的和单独的x'。 It is the 'x' inherited from class A. It's the same thing. 它是从A类继承的'x'。它是一样的。 That could explain all your confusion. 这可以解释你所有的困惑。

if a child class must be aware where it got its inherited members from 如果一个子类必须知道从哪里得到它的继承成员

Of course. 当然。

Is the explanation because the protected member was originally declared inside class A? 是解释因为受保护的成员最初是在A类中声明的吗?

Yes. 是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM