Важнейшая мысль: объектная (ссылочная) идентичность нужна только для поддержки изменяемости объектов. Объект может изменить состояние, но по ссылке мы всегда можем проверить, что это «тот же» объект. Поэтому типы-значения будут строго неизменяемые.
Предполагаемые варианты использования типов-значений:
- Числа: комплексные, беззнаковые, 128-битные, с фиксированной запятой и т. д. Все, что не описывается имеющимися примитивами.
- Алгебраические типы:
Optional<T>,Choice<T,U>, перечисления (enum) - Кортежи (пары, тройки, …)
- Итераторы, курсоры
- Кортежи (пары, тройки, …)
- «Уплощение» сложных структур.
- Можно использовать типы-значения везде, где сейчас можно объекты и примитивы: локальные переменные, поля, элементы массива, аргументы методов.
- В обычной ситуации аллокация в регистрах, на стеке, поле-значение это не ссылка, а прямо байты полей в родительском объекте. Хотя у ВМ есть право таки создать значение в куче, напр. если она считает, что так будет лучше, не может иначе обеспечить атомарность, не хватает стека, и т. д. Массивы с элементами типа-значения должны быть «плоскими».
- При необходимости (напр. при передаче в метод, который хочет Object) неявные приведение (boxing) к обычному объекту-двойнику (как сейчас с примитивами).
- Не просто структурки с полями: можно объявлять методы как в обычном объекте, переопределять
equals(),toString(). Вызов метода не (обязательно) приводит к приведению к обычному объекту. Инкапсуляция полей возможна. - Компилятор или ВМ генерирует
equals(),hashCode(),toString(),compareTo()по полям, если не переопределены в коде. - Типы-значения сами (а не только их «обычные» объектные двойники) могут реализовывать интерфейсы. Т. е. передача в метод, который хочет, допустим,
Comparableне обязательно приводит к оборачиванию значения в объект. - Можно объявлять поля типа-значения как
volatile. - Типы-значения могут содержать и обычные объектные поля (которые не обязаны быть рекурсивно неизменяемыми, как сами значения), и поля других типов-значений. Но: не могут содержать поля своего же типа.
Ограничения (должно быть запрещено или вызывать оборачивание в объект-двойник):
- Тип-значение не может наследовать ни классу, ни другому типу-значению, от типа-значения ничего нельзя наследовать. (Хотя, возможно, будет возможность наследовать от «чисто абстрактных» классов, например от
java.lang.Number.) - Вызов
wait(),notify(),clone()илиfinalize()на значении. - Вызов
System.identityHashCode()к значению. - Присвоение переменной типа-значения
null. - Приведение к
Objectили любому супертипу. - Применение рефлексии к значению.
- Запарки с атомарностью (напр. на платформе нельзя обеспечить атомарность чтения/записи, если общий размер типа-значения больше машинного слова, или двойного слова).
Синтаксис
Объявление типа-значения максимально приближено к обычным классам:
final __ByValue class Point { public final int x; public final int y; public Point(int x, int y) { this.x = x; this.y = y; } public boolean equals(Point that) { return this.x == that.x && this.y == that.y; } }
Уродливое __ByValue специально для того, чтобы никто не воспринимал это как окончательный синтаксис. Может, будет аннотация типа @ValueType. Объявление полей финальными — либо обязательно, либо неявное, как сейчас методы в интерфейсах можно объявить без public, но они все равно будут публичными. То же касается и модификатора класса.
Создание значения:
Point p = __MakeValue(x, y);
Тут вместо __MakeValue будет либо название типа без new, либо ничего, т. е. создание значения — просто скобочки с аргументами.
Поддержки специальных литералов (типа 0 + 1i для комплексных чисел или 1u для беззнаковых), а также перегрузки операторов (что было бы полезно тоже в первую очередь для числовых типов), скорее всего, не будет.
Надо понимать, что массивы, java.lang.String, java.lang.Integer и т. д. для бинарной совместимости в типы-значения преобразованы не будут. Так что существующий код магически не ускорится. По крайней мере, не в разы. Внутренний тип java.util.HashMap.Entry, например, поменять вполне могут.
Возможно, сделают отдельную сущность для массивов-значений, которые могут заменить varargs на уровне языка.
| Объект | Значение | |
| Содержит что-то разное | Объект | Типы-значения |
| Одинаковое | Массивы | Массивы-значения? |
Generics
Самый важный вопрос. В текущем виде дженерики — фича времени компиляции, и никаких типов-значений они поддерживать не будут. Но раз уж сказал «А» (типы-значения), то говори и «Б», поэтому рано или поздно дженерики переделают.
Мой прогноз:
- Для Java 9 уже есть одна «главная» фича — модуляризация, Oracle явно делает на нее ставку, вероятность увидеть ее в Java 9 близка к 100%.
- Если в Java 9 дженерики оставят «как есть», шанс увидеть типы-значения в этой версии 30%.
- Если решат выкатить типы-значения и обновленные дженерики одновременно, в лучшем случае это случится в Java 10.
Я знаю, этот блог читает много сотрудников Oracle, которые куда внимательнее следят за списками рассылки и вообще ближе к теме, буду рад если они внесут важные уточнения.
ссылка на оригинал статьи http://habrahabr.ru/post/222113/
Добавить комментарий