Статические переменные и методы принадлежат java.ленг.Объект класса этого класса?

Я прочитал много вопросов по этой теме, и многие из них говорят, что статическое содержимое (static methodsи variables) принадлежит java.lang.Classобъекту (также известному как объект уровня класса, который живет в постоянном поколении), и причины этого

  1. В спецификации Java мы можем найти это «статическое содержимое принадлежит некоторой внутренней структуре класса, которая является общей для всех объектов и существует вне объектов».

Как упомянуто в §8.3.1.1 спецификации языка Java

Если поле объявлено статическим, существует ровно одно воплощение
поле, независимо от того, сколько экземпляров (возможно ноль) класса
может в конечном итоге быть создан. Статическое поле, иногда называемое классом
переменная, воплощается при инициализации класса (§12.4).

  1. java.lang.Class объект класса представляет собой внутреннюю структуру класса, существует ровно одно его воплощение и оно является общим для всех объектов.

  2. java.lang.Class объект создается в Perm Gen при загрузке и инициализации класса.

  3. java.lang.Class известен как объект уровня класса и статические переменные называются переменными класса, поскольку статические переменные лежат как состояние объекта уровня класса.

  4. При синхронизации статического метода нам необходимо получить блокировку объекта уровня класса, который снова java.lang.Classявляется экземпляром.

Как указано в §8.4.3.6,:

Для метода class (static) монитор, связанный с классом
используется объект для класса метода.

Из вышеизложенного можно сделать вывод о том, что статическое содержимое принадлежит java.lang.Classэкземпляру, но почему оно нигде не записано ясно в какой-либо спецификации?

А также если class A { static int b; }почему bне доступен через A.class.b?

Как вы докажете, что статические переменные и методы принадлежат Classобъекту?

И если статическое содержимое не принадлежит объекту класса, то где именно оно принадлежит? и почему многие ответы, блоги и учебники упоминают об этом?

2 ответа

  1. §8.3.1.1 спецификации языка Java гласит следующее:

    Если поле объявленоstatic, существует ровно одна инкарнация поля, независимо от того, сколько экземпляров (возможно, ноль) класса может в конечном итоге быть создано. staticПоле, иногда называемое переменной класса, воплощается при инициализации класса (§12.4).

    И §8.4.3.6 гласит::

    Для метода class (static) используется монитор, связанный с Classобъектом для класса метода.

    Ни один из них не указывает объект, который должен содержать staticполя.

    Как вы упомянули:

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

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

    Поэтому, к сожалению, утверждение, которое вы пытаетесь доказать, ложно.

  2. Вы, кажется, задаете, казалось бы, разрозненные вопросы как один вопрос. Это, пожалуй, главный источник вашего замешательства. Кроме того, имея дело со спецификациями языка, мы должны быть точными в отношении имен, чтобы свести к минимуму путаницу.

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

    Из вышеизложенного можно сделать вывод о том, что статическое содержимое принадлежит java.lang.Classэкземпляру, но почему оно нигде не записано ясно в какой-либо спецификации?

    §15.11 пытается указать, что доступ к статическим членам осуществляется с помощью первичного имени и идентификатора с помощью выражения Primary . Identifier.

    В простейшем случае спецификация говорит: тип первичного должен быть ссылочным типом T, или происходит ошибка времени компиляции . Это означает, что доступ к статическим членам осуществляется с помощью имени типа, который определяет члены.

    А также, если class A { static int b; }why is b не доступен через A.class.b?

    По той же причине, что и выше, A.classэто не ссылочный тип, который определяет статическое поле b. Тип является Aи, следовательноb, доступен только как A.b.

    И как программисты Java, мы благодарны дизайнерам Java за то , что мы можем получить доступ к статическим членам, таким как A‘S bпросто какA.b, не так ли?

    Несколько более длинное объяснение должно касаться отражательных возможностей Java, в частности, класса java.lang.Class. Это единственный класс в Java, экземпляры которого являются классами . Да, экземпляры java.lang.Classявляются классами. Таким образом, java.lang.Stringявляется экземпляром java.lang.Classтак же, как строка String s = "foo";является экземпляром класса java.lang.String. Программа:

    public class Main {
      public static void main(String[] args) {
        String s = "foo";
        System.out.println(String.class instanceof Class);  // statically
        System.out.println(Class.class.isInstance(String.class)); // dynamically
        System.out.println(s instanceof String); // statically
        System.out.println(String.class.isInstance(s)); // dynamically
      }
    }
    

    печать:

    true
    true
    true
    true
    

    Один вопрос может задержаться, и это именно тоA.class, что есть ? Спецификация определяет его как литерал класса:

    Литерал класса вычисляется для объекта класса для именованного типа (или для void), как определено определяющим загрузчиком класса (§12.2) класса текущего экземпляра.

    Таким образом, любые методы, которые могут быть вызваны на say String.class(помните, String.classявляется получателем здесь), являются методами, определенными на его классе, который является классом java.lang.Class. Таким образом, вы можете сделать String.class.isInstance(str)точно так же, как вы можете вызвать str.length()where stris an instance of Stringlength()является так называемым методом экземпляра, определенным в Stringклассе; различие метода экземпляра и метода класса здесь не имеет значения).

    Как вы докажете, что статические переменные и методы принадлежат классу object?

    От 1) выше, т. е. от того, что они доступны только через имя типа (т. е. classили interface) объявляет их. Здесь есть небольшая морщинка. Статический элемент также доступен через экземпляры типа, определяющего их, и следующий пример может удивить вас. Что делает эта программа:

    public class Main {
      static int foo = 22;
    
      public static void main(String[] args) {
          Main m = null;
          System.out.println(m.foo); // ** Don't Do This **
      }
    }
    

    Нет, не бросает NullPointerException. Доступ к статическим членам разрешен (хотя и не рекомендуется) через экземпляры класса, который их определяет . И так javacкак понимает спецификацию языка Java, как никто другой, он делает то, что хочет спецификация.

    Но обратите внимание, что если вы используете определяющий тип или экземпляр этого типа, он будет получать точно такое же значение статических полей и будет вызывать точно такой же статический метод во время выполнения. Это достаточно хорошее доказательство, чтобы убедиться, что статические члены действительно являются характеристикой типа (или класса), который их определяет.