Статьи

Проект Valhalla: первый взгляд на встроенные типы LW2

Я кратко изложил недавний прогресс проекта Valhalla LW2 по « встроенным типам », который недавно был опубликован в моем блоге « Прогресс Valhalla LW2 — встроенные типы ». В этом посте я иллюстрирую некоторые концепции, обобщенные в этом посте, с примерами кода, выполненными для недавно выпущенной сборки Valhalla Early Access Build jdk-14-valhalla + 1-8 (2019/7/4) . Все примеры кода, представленные в этом посте, доступны на GitHub .

Вики- страница OpenJDK « LW2 » предоставляет иллюстративный пример встроенных типов через исходный код для класса « InlineType ». Мой пример вносит некоторые незначительные изменения и дополнения в этот класс и доступен на GitHub как класс с именем InlineTypeExample . При рассмотрении этого исходного кода сразу выделяются следующие элементы: наличие inline ключевого слова и наличие символа ? в универсальном параметре Comparable.

В исходном коде моего адаптированного класса InlineTypeExample предпринята попытка extend класс встроенного типа, закомментировав другой класс, поскольку это приводит к ошибке компилятора: error: Inline type may not extend another inline type or class

Аналогично, этот исходный код также имеет метод, который пытается установить поле целого числа класса встроенного типа, закомментированное, потому что это также не будет компилироваться: error: cannot assign a value to final variable

В текущей сборке Valhalla LW2 мне разрешено делать класс встроенных типов Serializable, и он все еще успешно компилируется.

Другим иллюстративным классом, размещенным на GitHub, является Lw2Demonstration который сравнивает и сравнивает характеристики класса встроенного типа (и его экземпляров) с предоставленным JDK классом java.lang.Integer (и его экземплярами) и с простой встроенной оболочкой Integer ( и его экземпляры). Этот демонстрационный класс вызывает рефлексивные методы (некоторые из которых являются новыми для сборки Valhalla на основе JDK 14) для типов « class » всех трех вещей (встроенный тип, Integer и пользовательская оболочка Integer ) и вызывает некоторые «общие» методы [ toString () , equals (Object) , hashCode () ] для экземпляров всех трех типов.

Два метода закомментированы в классе Lw2Demonstration поскольку каждый из них пытается выполнить функциональность для встроенного типа, который не поддерживается для встроенных типов. Один из этих методов пытается синхронизироваться с переменной встроенного типа. При попытке скомпилировать эту синхронизацию встроенного типа появляется следующее сообщение об ошибке компилятора: error: unexpected type ... required: reference ... found: InlineTypeExample

Другая попытка назначить встроенный тип для null . При попытке скомпилировать это, следующее сообщение об ошибке встречается: error: incompatible types: <null> cannot be converted to InlineTypeExample

Следующий метод из Lw2Demonstration записывает несколько характеристик метаданных типов классов.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * Provides metadata extracted from the provided instance of
 * {@link Class} as a single {@link String}.
 *
 * @param classToInvokeInlineMethodsOn Class for which metadata
 *    is to be extracted and returned in {@link String} format;
 *    should NOT be {@code null}.
 * @return Single string representation of metadata extracted
 *    from the provided {@link Class} instance.
 * @throws NullPointerException Thrown if {@code null} is
 *    provided for my sole parameter.
 */
public static String extractClassMetadata(final Class classToInvokeInlineMethodsOn)
{
   Objects.requireNonNull("Provided Class must be non-null to extract its metadata.");
 
   final String className = classToInvokeInlineMethodsOn.getSimpleName();
   final String outputPrefix = "\n" + className + ".class.";
   return outputPrefix + "getName(): " + classToInvokeInlineMethodsOn.getName()
      + outputPrefix + "getSimpleName(): " + classToInvokeInlineMethodsOn.getSimpleName()
      + outputPrefix + "getCanonicalName(): " + classToInvokeInlineMethodsOn.getCanonicalName()
      + outputPrefix + "toGenericString(): " + classToInvokeInlineMethodsOn.toGenericString()
      + outputPrefix + "getTypeName(): " + classToInvokeInlineMethodsOn.getTypeName()
      + outputPrefix + "getComponentType(): " + classToInvokeInlineMethodsOn.getComponentType()
      + outputPrefix + "isInlineClass(): " + classToInvokeInlineMethodsOn.isInlineClass()
      + outputPrefix + "isIndirectType(): " + classToInvokeInlineMethodsOn.isIndirectType()
      + outputPrefix + "isNullableType(): " + classToInvokeInlineMethodsOn.isNullableType()
      + outputPrefix + "isPrimitive(): " + classToInvokeInlineMethodsOn.isPrimitive()
      + outputPrefix + " final?: " + isFinal(classToInvokeInlineMethodsOn);
}

Некоторые из методов, вызванных в экземпляре Class в предыдущем методе, являются новыми для ранней сборки доступа Valhalla LW2 на основе JDK 14. К ним относятся isInlineClass() , isIndirectType() и isNullableType() .

Основной демонстрационный класс Lw2Demonstration создает экземпляры класса встроенного типа InlineTypeExample , java.lang.Integer , предоставляемого JDK, и пользовательской оболочки для Integer . Затем демонстрация запускает экземпляры этих трех классов и определений классов через одни и те же методы и записывает результаты для каждого из них, чтобы их можно было сравнить и сопоставить. Вот результат запуска этого примера для сборки раннего доступа Valhalla, упомянутой в начале этого поста.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
InlineTypeExample.class.getName(): dustin.examples.valhalla.lw2.InlineTypeExample
InlineTypeExample.class.getSimpleName(): InlineTypeExample
InlineTypeExample.class.getCanonicalName(): dustin.examples.valhalla.lw2.InlineTypeExample
InlineTypeExample.class.toGenericString(): public final inline class dustin.examples.valhalla.lw2.InlineTypeExample
InlineTypeExample.class.getTypeName(): dustin.examples.valhalla.lw2.InlineTypeExample
InlineTypeExample.class.getComponentType(): null
InlineTypeExample.class.isInlineClass(): true
InlineTypeExample.class.isIndirectType(): false
InlineTypeExample.class.isNullableType(): false
InlineTypeExample.class.isPrimitive(): false
InlineTypeExample.class. final?: true
InlineTypeExample: toString(): [dustin.examples.valhalla.lw2.InlineTypeExample someIntegerValue=1]
InlineTypeExample: hashCode(): 1303372796
Inline Type Example ==: true
 
Integer.class.getName(): java.lang.Integer
Integer.class.getSimpleName(): Integer
Integer.class.getCanonicalName(): java.lang.Integer
Integer.class.toGenericString(): public final class java.lang.Integer
Integer.class.getTypeName(): java.lang.Integer
Integer.class.getComponentType(): null
Integer.class.isInlineClass(): false
Integer.class.isIndirectType(): true
Integer.class.isNullableType(): true
Integer.class.isPrimitive(): false
Integer.class. final?: true
Integer: toString(): 1
Integer: hashCode(): 1
Integer Type Example ==: false
 
IntegerWrapper.class.getName(): dustin.examples.valhalla.lw2.IntegerWrapper
IntegerWrapper.class.getSimpleName(): IntegerWrapper
IntegerWrapper.class.getCanonicalName(): dustin.examples.valhalla.lw2.IntegerWrapper
IntegerWrapper.class.toGenericString(): public class dustin.examples.valhalla.lw2.IntegerWrapper
IntegerWrapper.class.getTypeName(): dustin.examples.valhalla.lw2.IntegerWrapper
IntegerWrapper.class.getComponentType(): null
IntegerWrapper.class.isInlineClass(): false
IntegerWrapper.class.isIndirectType(): true
IntegerWrapper.class.isNullableType(): true
IntegerWrapper.class.isPrimitive(): false
IntegerWrapper.class. final?: false
IntegerWrapper: toString(): dustin.examples.valhalla.lw2.IntegerWrapper@5442a311
IntegerWrapper: hashCode(): 1413653265
Integer Wrapper Example ==: false

Вывод, показанный выше, демонстрирует некоторые из объявленных характеристик встроенного типа. Наиболее интересными являются фокусы следующей таблицы.

Характерная черта Целочисленное обертывание типа Inline java.lang.Integer Custom Integer Wrapper
В линию? правда ложный ложный
Косвенное? ложный правда правда
Nullable? ложный правда правда
Финал? правда правда ложный
== Действительно для равенства? правда ложный ложный
toString() Неявно настроенный Явно настроенный Использует объект
hashCode() Неявно настроенный Явно настроенный Использует объект

Чтобы скомпилировать и выполнить эти примеры, мне нужно было предоставить компилятору Java и программе запуска некоторые специальные аргументы. В частности, я скомпилировал с --enable-preview , -Xlint:preview и -source 14 . Для выполнения демонстрации я передал флаг --enable-preview в панель запуска Java.

Обновленная сборка раннего доступа Valhalla [ Build jdk-14-valhalla + 1-8 (2019/7/4) ] предоставляет удобный готовый двоичный файл для разработчиков Java, заинтересованных в испытании встроенных типов прототипов Valhalla LW2. Этот пост продемонстрировал некоторые из этих текущих концепций встроенных типов LW2 с использованием этой сборки. Реми Форакс предоставил еще много примеров на GitHub ( forax / valuetype-lworld ).

Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Проект Valhalla: первый взгляд на встроенные типы LW2

Мнения, высказанные участниками Java Code Geeks, являются их собственными.