Возможен ли доступ к частному полю Java при наличии ссылки? - PullRequest
9 голосов
/ 27 октября 2011

Сегодня я натолкнулся на следующую «странную» особенность - если у вас есть ссылка на объект из класса A в теле класса A, вы можете получить доступ к закрытым полям этого объекта, то есть:

public class Foo{
   private int bar;
   private Foo foo;
   public void f()
   {
       if(foo.bar == bar) // foo.bar is visible here?!
       {
            //
       }
   }
}

У кого-нибудь есть хорошее объяснение по этому поводу?

Ответы [ 7 ]

19 голосов
/ 27 октября 2011

Модификаторы доступа работают на уровне класса, а не на уровне экземпляра: весь код в одном классе может получить доступ к закрытым членам всех экземпляров класса.

Ничего особенно странного в этом нет.

5 голосов
/ 27 октября 2011

Так и должно быть.

Ссылаясь на Спецификацию языка Java :

Элемент (класс, интерфейс, поле или метод) ссылки (класс, интерфейс или массив)Тип или конструктор типа класса доступен только в том случае, если тип доступен, а член или конструктор объявлен для разрешения доступа:

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

Поскольку f () является членом Foo, он имеет право доступа к закрытым членам Foo.Это не удивительно для меня.

1 голос
/ 27 октября 2011

Имеет смысл, если вы подумаете о намерении модификатора 'private' скрыть детали реализации.

Попробуйте представить его в терминах "это должно быть приватно для этого класса" (что в Java равнозначно«это должно быть приватно для этого исходного файла»), а не «это должно быть приватно для этого экземпляра».

0 голосов
/ 11 апреля 2015

@Michael ответ правильный. Поведение аналогично для .NET для кода @asenovm.

Кроме того, то же самое относится и к внутренним классам Java. Даже если вы определили переменную как приватную, вы можете получить к ней доступ. Я удивился, когда впервые столкнулся, потому что он отличается от C#.

public class WrapperClass
{

  public static  class NotThreadsafe {
        private int x = 0;
       //....          
    }

    public static void main(String[] args) {           
    final NotThreadsafe nts=new NotThreadsafe(); 
     int x = nts.x ; // !!! THIS IS ACCESSIBLE AS WELL FOR JAVA BUT NOT.NET
    }
}

Это не то же самое для C# вложенных классов. Если вы вставите этот код в Visual Studio, он не будет работать. Компилятор беспокоится об уровнях доступа.

0 голосов
/ 27 октября 2011

Эти ключевые слова ориентированы на класс, а не на объект.Так что он просто смотрит и видит: «О, объект класса Foo пытается получить доступ к закрытому объекту в Foo. Ну, это нормально».

0 голосов
/ 27 октября 2011

Потому что приватный означает не приватность снаружи объекта, а приватность других классов. Вы находитесь внутри Foo, поэтому вы можете видеть бар.

Таким образом, частные Конструкторы работают в Singletons и т. Д.

...