Почему он называется «литерал класса», когда он функционирует больше как объект? - PullRequest
0 голосов
/ 06 июня 2019

Например:

Класс c = String.class;

Приведенный выше оператор присваивает объекту переменную c, если это так, почему мыназвать classname.class "литерал", когда он функционирует как объект?

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Литерал - это специальный синтаксис, который компилятор непосредственно понимает как значение, в отличие от того, что он производит значение с использованием некоторых операций. В отличие от, например, String.CASE_INSENSITIVE_ORDER, String.class не обращается к свойству объекта класса String - он является объектом класса String. Вы можете увидеть это в разборке:

class Test {
  public static Class classProperty = Test.class;
  public static String stringProperty = "foo";

  public static void main(String args[]) {
    String a = "bar";
    String b = Test.stringProperty;
    Class x = Test.class;
    Class y = Test.classProperty;
  }
}

компилируется в:

class Test {
  public static java.lang.Class classProperty;

  public static java.lang.String stringProperty;

  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String bar
       2: astore_1
       3: getstatic     #3                  // Field stringProperty:Ljava/lang/String;
       6: astore_2
       7: ldc           #4                  // class Test
       9: astore_3
      10: getstatic     #5                  // Field classProperty:Ljava/lang/Class;
      13: astore        4
      15: return

  static {};
    Code:
       0: ldc           #4                  // class Test
       2: putstatic     #5                  // Field classProperty:Ljava/lang/Class;
       5: ldc           #6                  // String foo
       7: putstatic     #3                  // Field stringProperty:Ljava/lang/String;
      10: return
}

Здесь вы можете видеть, что Test.stringProperty и Test.classProperty действуют как средства доступа к свойствам (используя getstatic), в то время как Test.class и "bar" обрабатываются как литералы (непосредственно загружая их значение с помощью ldc, «постоянная нагрузки»).


Наконец, «литерал» не противопоставляется «объекту», а «не-буквальному» - оцениваемому значению. Противоположностью «объекта» в Java является «примитив». Эти две совершенно разные оси. Вот несколько примеров:

  • 1 - примитивный литерал (в частности, int)
  • "foo" - литерал объекта (в частности, String)
  • 3 - 2 - примитивный не-литерал (хотя это простой случай, так что компилятор предварительно вычислит и обработает его как литерал 1)
  • "fo" + "o" - объект не-литерал (то же самое, компилятор оптимизирует его как литерал "foo")
  • x + y (при условии x и y равны int) - примитивный не-литерал (который не может быть оптимизирован)
  • x + y (при условии x и y равны String) - объект не-литерал (который нельзя оптимизировать)

аналогично

  • Test.class - литерал объекта (в частности, класса Class)
  • new Test().getClass() - объект не-литерал (в частности, класса Class)
1 голос
/ 06 июня 2019

Согласно Javadoc для java.lang.Class:

В классе нет открытого конструктора. Вместо этого объекты Class создаются автоматически виртуальной машиной Java при загрузке классов и при вызове метода defineClass в загрузчике классов.

Кроме того, если вы прочитаете Javadoc, вы увидите, что Class не предоставляет никаких методов мутации открытого сеттера.

Таким образом, экземпляры Class не следуют обычному циклу объектов создания и по большей части не могут быть изменены. Следовательно, String.class ведет себя больше как буквальное значение, чем обычный объект Java.

...