2

我有以下两个文件:

水果.java:

package superClass;

public class Fruit { 
 protected static void printName() {
  System.out.println("My name is Khan");
 }

}

苹果.java:

package food;

import superClass.*;

public class Apple  {
 public static void main(String[] args) {
  int i, j;
  for(i = 0; i < 5; i++) {
   for(j = 0; j < i; j++) {
    System.out.print("*");
   }
   System.out.println();
  }
  printName(); // Call inherited member - NO ERROR, expected

  Fruit f = new Fruit();
  f.printName(); // Call instantiated member - ERROR, expected
 }

}

正如预期的那样,我无法从 Apple 类中访问受保护的方法 printName,因为它们位于不同的包中。我收到以下错误:

printName() has protected access in superClass.Fruit

完全正确。但是,如果我按如下方式从类 superClass 继承,我不会收到任何错误!

package food;

import superClass.*;

public class Apple extends Fruit {
 public static void main(String[] args) {
  int i, j;
  for(i = 0; i < 5; i++) {
   for(j = 0; j < i; j++) {
   System.out.print("*");
   }
   System.out.println();
 }
  printName(); // Call inherited member - NO ERROR, expected

  Fruit f = new Fruit();
  f.printName(); // Call instantiated member - NO ERROR, WHAT????
 }
}

为什么它允许我通过引用访问不同包中另一个类的受保护成员?这应该是非法访问,不是吗?

我很困惑!有人请帮忙。

该代码是使用 Java 1.6.0_18 编译的。

4

8 回答 8

4

您观察到的行为是因为 printName 是静态的。protected 修饰符在子类中提供该方法的可见性,但如果该方法是 non-static,则只能通过子类的实例调用该方法(您提出的问题“如果我从该类继承superClass 如下我没有得到任何错误!”)。JLS第6.6.2.1 节简洁地定义了这一点。

于 2010-09-01T17:17:36.473 回答
3

protected 修饰符允许在继承的类中访问。如果您只需要限制对某个包中的类的访问,则需要一个“包”修饰符,它只是一个空修饰符,即编写如下方法:

静态无效打印名称()

它将具有包可见性。

于 2010-03-03T09:18:22.783 回答
3

这是protected访问的定义:protected成员可以从子类访问,而不管它们在不同的包中。

这是对 Java 访问修饰符的引用。

注意:在 Java 中,约定是使用小写的包名,即superClass不遵守此约定。您可能会为此感到困扰——特别是如果您在文件和目录名称区分大小写的 *nix 平台上进行开发。

于 2010-03-03T09:18:44.637 回答
3

超类的受保护成员可以从子类访问,即使超类在另一个包中,但我们可以通过引用使用受保护成员的类来使用,因为此时该类是受保护成员的所有者。假设受保护的成员在

com.pack1 class A { protected int i;}
com.pack2 class D { System.out.println(i); System.out.println(a1.i); }

i完美但a1.i不完美,给出错误。在 D 类中,我们可以通过 d 的引用而不是 A 类的引用来使用受保护的成员

于 2011-11-23T06:40:49.417 回答
1

事情就是这样,当你说

printName(); // Call inherited member - NO ERROR, expected
Fruit f = new Fruit();
f.printName(); // Call instantiated member - NO ERROR, WHAT????

请记住 printName 是一个静态方法,所以即使编译器接受了表单

f.printName();

真实的形式永远是

Fruit.printName(); // protected accesor allows the use of the method
Apple.printName(); // or just
printName(); // at the end everything is the same to this call

所以最后你继承了静态方法,你只是对静态方法如何工作感到困惑,它们是类方法而不是实例,即使编译器没有抱怨编写表单

f.printName();

内部发生的真实事情是类访问。但可以肯定的是编译器会给出类似这样的警告:

Fruit 类型的静态方法 printName() 应该以静态方式访问

于 2013-09-20T17:24:42.153 回答
1

超类的protected成员可以从子类访问,即使超类在另一个包中。请参阅本页的第二部分和随附的表格/图表:

http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

于 2010-03-03T09:22:52.790 回答
0

您是否将 protected 与默认(又名包)修饰符混淆?后者限制对同一包的成员的访问。

Protected 限制对包的成员和从相关类继承的类的访问。

有关详细信息,请参见http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#62587

于 2010-03-03T09:22:32.573 回答
0

是的,您没有收到任何错误真是太好了……这可能违反了 Java 语言规范或错误……无论如何,这是正确的。这就是受保护的访问修饰符的定义。受保护类似于类成员从外部或其他类的可访问性的中间级别。我想这是在私人和公共之间。受保护的类成员可以访问(从类的子类)和(从其他类,只要它们属于同一个包)。只是一个想法!

于 2010-03-03T09:28:41.753 回答