Доступ к частному члену Java

Доступ к частному члену на уровне класса или на уровне объекта. Если он находится на уровне объекта, следующий код не должен компилировать

    class PrivateMember {
   private int i;
   public PrivateMember() {
      i = 2;
   }
   public void printI() {
      System.out.println("i is: "+i);
   }
   public void messWithI(PrivateMember t) {
      t.i *= 2;
   }
   public static void main (String args[]) {
      PrivateMember sub = new PrivateMember();
      PrivateMember obj = new PrivateMember();
      obj.printI();
      sub.messWithI(obj);
      obj.printI();
   }
}

Просьба пояснить, действительно ли доступ к члену я объекта obj в методе messWithI() для sub

Ответ 1

Как сказал DevSolar, он находится на уровне верхнего уровня.

От раздел 6.6 Спецификации языка Java:

В противном случае, если член или конструктор объявляется приватным, тогда доступ разрешен тогда и только тогда, когда происходит в теле верхней части (§7.6), который охватывает декларация участника или конструктор.

Обратите внимание, что нет указания на то, что он ограничен членами для определенного объекта.

Начиная с Java 7, компилятор больше не разрешает доступ к частным членам переменных типа. Поэтому, если у метода была подпись типа public <T extends PrivateMember> void messWithI(T t), то было бы ошибкой компилятора получить доступ к t.i. Однако это не повлияет на ваш конкретный сценарий.

Ответ 2

Обратите внимание, что вам даже не нужен доступ на уровне источника к беспорядку с частными полями. Используя java.lang.reflect.AccessibleObject.setAccessibe(), весь код может получить доступ ко всем закрытым членам всего другого кода, если вы не укажете политику безопасности, которая запрещает ее.

private сам по себе не является функцией безопасности!. Это просто сильный намек другим разработчикам, что что-то является внутренней детализацией реализации, которая не должна зависеть от других частей кода. p >

Ответ 3

Ни. Частный доступ привязан к классу верхнего уровня, поэтому вы можете получить доступ к закрытым членам другого класса в том же классе верхнего уровня:

class PrivateAccess {
    static class InnerOne {
        private int value;
    }

    static class InnerTwo {
        int getOne ( InnerOne other ) {
            return other.value;
        }
    }
}

Обычное значение класса доступа означает, что у вас есть доступ к рядовым другим экземплярам того же типа. В Java частный доступ определяется лексически, а не по типу.

Ответ 4

Уровень класса. Идея состоит в том, что код класса (но не более того) знает, как обращаться с объектами этого класса.

Если у вас есть доступ к исходному коду класса в любом случае, у вас мало смысла "скрывать" что-либо от вас.

Ответ 5

Как утверждали другие, частный доступ по умолчанию ( "закрытый пакет" ), защищенный и, возможно, в модуле JDK 7 основаны на классах (существуют очень странные правила вложения вложенных классов, которые я не могу запомнить). Но почему?

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

Ответ 6

Чтобы добавить к ответу DevSolar, я ожидал, что messWithI будет объявлен как статический как таковой:

public static void messWithI(PrivateMember t) {
  t.i *= 2;

} Мне было трудно даже понять, что вы пытаетесь сделать без "статического" намека... И это также облегчает ответ на ваш первоначальный вопрос - это то, что частные члены не ограничены в объеме, чтобы просто рассматриваемый экземпляр.

Ответ 7

На той же странице говорится, что в подразделе 6.6.8 вы также можете найти следующее утверждение:

Частный член класса или конструктор доступен только внутри тела класса верхнего уровня, который включает объявление члена или конструктора. Это не унаследовано подклассами.

Частный член класса, доступ которого мы оцениваем здесь: i.

public void messWithI() - это метод, который существует внутри тела класса верхнего уровня, где я был объявлен, а именно, PrivateMember.

Ваша конструкция соответствует приведенному выше утверждению, и поэтому она работает без проблем.

Это другой способ сказать то же самое, что и Джон и Дессолар.

Модификаторы доступа для членов класса связаны с тем, где код написан (в каком пакете и в каком классе), независимо от того, какой член получает доступ: член класса или член экземпляра.

Логически, вы не можете использовать член экземпляра класса, если у вас нет экземпляра класса, но это другая проблема, связанная с жизненным циклом члена.