Squeak.ru - шаблоны программирования

Как написание classname.class может возвращать ссылку на объект java.lang.Class?

Насколько мне известно, всякий раз, когда класс загружается, JVM создает для него объект Class.class, который хранит всю метаинформацию загруженного класса.

Когда мы используем метод forName ("classname"), он сначала загружает "classname", а затем создает для него объект Class.class и возвращает ссылку на созданный объект Class.class.

Example.java задается как:

class Example
{
        static
        {
                System.out.println("Example Loaded");
        }
        Example()
        {
                System.out.println("Example Constructed");
        }
}

Use.java - это:

import java.lang.reflect.*;
class Use
{
        int i;
        public static void main(String[] args) throws Exception
        {
                Class c = Class.forName("Example");
                Constructor[] con = c.getDeclaredConstructors();
                for(Constructor x: con)
                {
                        System.out.println(x.getName());
                }
        }
}

Запуск Use.java выводит:

Example Loaded
Example

getClass () - это метод, который можно использовать только с объектами. Так что обязательно перед созданием объекта будет загружен класс и для него будет создан объект Class.class.

Согласно разделу «Класс и данные» в http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html, "Каждый раз, когда мы компилируем любой файл Java, компилятор вставляет общедоступное, статическое, последнее поле с именем class , типа java.lang.Class в передаваемом байтовом коде ". Мы можем использовать это поле как:

import java.lang.reflect.*;
class Use
{
        int i;
        public static void main(String[] args) throws Exception
        {
                Class c = Example.class;
                Constructor[] con = c.getDeclaredConstructors();
                for(Constructor x: con)
                {
                        System.out.println("Hello "+x.getName());
                }
        }
}

Вывод приведенного выше кода:

Hello Example

Статическое тело примера не выполняется. Означает, что класс Example не загрузился.

Я сомневаюсь:

Если класс не загрузился, то объект Class.class для него также не будет создан. Тогда откуда инструкция «Class c = Example.class» возвращает ссылку на Class.class?

26.04.2016

  • см. связанный вопрос, ваш класс Example не инициализируется при доступе к его статическому полю 26.04.2016

Ответы:


1

Существует разница между загрузкой класса и инициализацией класса. Класс может быть загружен, но не инициализирован. Это происходит в случае -2.

статические инициализаторы класса запускаются при инициализации класса, а не при его загрузке.

Class.forName (String className) загружает и инициализирует класс. Следовательно, в случае 1 будет напечатано Example Loaded.

В случае -2, поскольку вы не делаете ничего для запуска инициализации класса, Example Loaded не будет напечатан.

Также попробуйте Class c = Class.forName("Example", false, Sample.class.getClassLoader()); версию forName (которая только загружает класс, но не инициализирует его) и посмотрите, что произойдет.

Просто попробуйте получить доступ к статическому полю в классе 2 (тот же код) и посмотрите, что произойдет.

class Example
{
    static int i= 5;
        static
        {
                System.out.println("Example Loaded");
        }
        Example()
        {
                System.out.println("Example Constructed");
        }
}

public static void main(String[] args) {
    Class c = Example.class;
    Constructor[] con = c.getDeclaredConstructors();
    for(Constructor x: con)
    {
            System.out.println("Hello "+x.getName());

    }
    System.out.println(Example.i);

}

Также вы можете проверить, какие классы загружены , но не инициализированы, используя параметр java -verbose:class.

26.04.2016
  • Это означает, что объект Class.class для класса Example может быть создан, даже если он не инициализирован. Класс поля будет загружен в область метода с другой информацией о классе примера. В области методов JVM выбирает ссылку на класс на объект Class.class для примера. Я прав? 26.04.2016
  • @mynameisGYAN - Да. Объекты классов создаются в JVM по мере загрузки классов. 26.04.2016
  • @mynameisGYAN - Используйте javap -v Example.class и проверьте #1 в постоянном пуле :) 26.04.2016

  • 2

    Как сказал TheLostMind, «существует разница между загрузкой класса и инициализацией класса. Статические инициализаторы класса запускаются, когда класс инициализируется, а не когда класс загружается».

    Статические члены загружаются в область метода и, следовательно, в поле с именем «class».

    Но класс не инициализируется для доступа к переменной «static final».

    Example.java

    class Example
    {
            static final int i = 5;
            static
            {
                    System.out.println("Example Loaded");
            }
            Example()
            {
                    System.out.println("Example Constructed");
            }
    }
    

    Use.java

    import java.lang.reflect.*;
    class Use
    {
            public static void main(String[] args) throws Exception
            {
                    System.out.println(Example.i);
            }
    }
    

    Запуск результатов Use.class

    5
    

    Но если Example.i был

    static int i = 5;
    

    затем запустите результаты Use.class как:

    Example Loaded
    5
    

    То же самое происходит с полем «class». Как сказал TheLostMind, «Объекты классов создаются в JVM по мере загрузки классов». Поле «class» инициализировано компилятором для указания на класс объекта во время компиляции. Итак, получив доступ к Example.class, мы можем получить доступ к объекту класса. Но доступ к полю «класс» не приводит к инициализации класса, потому что это поле является статическим и окончательным.

    26.04.2016
    Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...