Java защищенный модификатор не работает должным образом - PullRequest
2 голосов
/ 03 марта 2010

У меня есть следующие два файла:

Fruit.java:

package superClass;

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

}

Apple.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
 }

}

Как и ожидалось, у меня нет доступа к защищенному методу printName из класса Apple, поскольку они находятся в разных пакетах. Я получаю следующую ошибку:

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.

Ответы [ 8 ]

4 голосов
/ 01 сентября 2010

Вы наблюдаете поведение из-за того, что printName является статическим. Защищенный модификатор обеспечивает видимость этого метода в подклассе, но , если метод нестатический , вызов этого метода возможен только через экземпляр подкласса (проблема, о которой вы говорили) если я наследую от класса superClass следующим образом, я не получаю никакой ошибки! "). Раздел JLS 6.6.2.1 определяет это кратко.

3 голосов
/ 23 ноября 2011

Защищенные члены суперкласса доступны из подкласса, даже если суперкласс находится в другом пакете, но мы можем использовать ссылку на тот класс, в котором используется защищенный член, поскольку в данный момент этот класс является владельцем защищенного члена. Предположим, защищенный член в

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

i идеально, но a1.i не идеально, выдает ошибку. В классе D мы можем использовать защищенный член по ссылке, а не по ссылке класса A

3 голосов
/ 03 марта 2010

Это определение protected доступа: protected члены доступны из подклассов, независимо от того, находятся ли они в другом пакете.

Вот ссылка на модификаторы доступа Java .

Примечание: в Java принято использовать имена пакетов в нижнем регистре, т. Е. superClass не придерживается этого соглашения. Это может вас укусить - особенно если вы разрабатываете на * nix платформах, где имена файлов и каталогов чувствительны к регистру.

3 голосов
/ 03 марта 2010

защищенный модификатор разрешает доступ в унаследованных классах. Если вам нужно ограничить доступ к классам только в определенном пакете, вам нужен модификатор «package», который является просто пустым модификатором, т.е. метод записи, такой как:

static void printName ()

и он будет иметь видимость пакета.

1 голос
/ 20 сентября 2013

Вот вещь, когда вы сказали

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();

Реальная вещь, происходящая внутри, это доступ к классу. Но уверен, что компилятор выдает предупреждение, подобное этому:

Статический метод printName () из типа Fruit должен быть доступен статическим способом

1 голос
/ 03 марта 2010

Члены суперкласса protected доступны из подкласса, даже если суперкласс находится в другом пакете. См. Вторую часть этой страницы и прилагаемую таблицу / схему:

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

0 голосов
/ 03 марта 2010

Да, хорошо, что вы не получили никакой ошибки ... это могло быть нарушением спецификации языка Java или ошибкой ... В любом случае, это правильно. это определение модификатора защищенного доступа. Защищенный - это как промежуточный уровень доступности членов класса извне или из других классов. я полагаю, это между частным и публичным. Защищенные члены класса доступны (из подклассов класса) и (из других классов, если они принадлежат одному пакету). просто мысль!

0 голосов
/ 03 марта 2010

Вы путаете защищенный с модификатором по умолчанию (он же пакет)? Последнее ограничивает доступ для членов одного пакета.

Защищено ограничивает доступ к членам пакета и классам, унаследованным от рассматриваемого класса.

Подробнее см. http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#62587

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...