Статические методы Java для доступа к закрытым переменным - PullRequest
16 голосов
/ 26 февраля 2011

У меня сложилось впечатление, что частные нестатические переменные могут быть доступны только с помощью методов, вызываемых для объекта, в котором находятся переменные, но это не так.Может ли кто-нибудь объяснить причины, по которым следующие компиляции и запускаются?

public class Sandbox {
    private String _privateString = "unmodified";
    public static void setPrivateString(String str, Sandbox s) {
        s._privateString = str;
    }
    public String toString()
    {
        return _privateString;
    }

    public static void main(String[] args) {
        Sandbox s = new Sandbox();
        setPrivateString("modified", s);
        System.out.println(s);
    }
}

Выход:

modified

РЕДАКТИРОВАТЬ: То же самоеверно в C #.

Ответы [ 5 ]

21 голосов
/ 26 февраля 2011

Закрытые переменные-члены класса A могут быть доступны (т.е. доступны для чтения / записи) с помощью любого метода класса A (статического или нестатического), так что в вашем примере, поскольку метод изменяет строкуявляется методом того же класса, к которому принадлежит член, ему предоставлен доступ к переменной.

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

3 голосов
/ 26 февраля 2011

Вы, кажется, путаете visibility с scope.Переменные экземпляра находятся в области видимости экземпляра, поэтому к ним нельзя получить доступ напрямую в статическом методе, но только с квалификатором ссылки на экземпляр: s._privateString в вашем случае.переменные экземпляра не видимы для статического метода внутри того же класса, поскольку private означает видимые внутри класса (для любого члена с любой областью действия).

3 голосов
/ 26 февраля 2011

Как упоминалось в некоторых других публикациях, система видимости Java основана на классах, а не на объектах.

Обратите внимание, что это используется в компиляторе: когда у вас есть вложенные классы, и вы получаете доступ к частномуполе внешнего класса, открытый синтетический статический метод генерируется, чтобы разрешить доступ.Обычно он называется «access $ 0» и т. Д. С помощью этих синтетических методов можно создать байт-код, который нарушает инкапсуляцию без Reflection API.Вы также можете получить к ним доступ из API Reflection, не предоставляя доступ частным пользователям.Много безумных вещей можно сделать ...

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

... Однако конечный программист обычно неТ нужно знать эту деталь.Среды IDE не включают синтетические методы в завершение кода, и я надеюсь, что компиляторы (кроме Jasmin) не позволят вам его использовать.Поэтому, если вы не генерируете байт-код и не используете Reflection API и игнорируете эти методы в трассировке стека, вам, вероятно, не нужно знать эту деталь.

3 голосов
/ 26 февраля 2011

Правило простое:

методы-члены класса могут получать доступ и изменять частные члены того же класса независимо от их видимости .

0 голосов
/ 10 мая 2019

Ваш код скомпилирован, потому что внутри setPrivateString (String str, Sandbox s) вы обращаетесь к закрытой переменной _privateString по ссылочной переменной s.

Нестатический член может получить доступ только к переменной экземпляра из статического API.

Проверьте этот код

public class Sandbox {

    public static void main(String[] args) {
        Sandbox s = new Sandbox();
        // testAccess();// If you uncomment this line you will get compile time error
        s.testAccess();//can only access in this way
    }

    private void testAccess() {
        System.out.println("can only access by instance variable from static method");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...