Сейчас уже интереснее, какое-то API вырисовывается. Маленькое замечание по имени — вместо toList() лучше asList(). Предлог to традиционно сигнализирует о преобразовании, а адаптеры именуются начиная с as.
Метод convertToImmutableList — это очень грязно. Чистое и понятное API гораздо лучше сомнительного прироста производительности. Но если уж вы это делаете, позвольте дать несколько советов.
Во-первых, сейчас семантика метода совершенно плохая. Он делает что-то, если что-то сработает, в зависимости от типов коллекций. А если не сработает, то результат будет другим. Надёжная система на это никогда не пойдёт. Гораздо разумнее сделать одинаковую семантику, и хачить только производительность. Можно сделать, например, метод drainToImmutableList(Collection<T> c), который всегда перегружает данные в неизменяемый список и очищает исходный (вызывая c.clear()). Для такого метода можно сделать быстрый путь для ArrayList. Он будет работать так же, даже если рефлекшн не сработает.
Во-вторых, рекомендую заменить original instanceof ArrayList<?> на original.getClass().equals(ArrayList.class). Мало ли кто какой наследник сделал и каких гарантий он ожидает в этом наследнике.
В-третьих, вы зря инициализируете поля безусловно в статическом инициализаторе. В Java 9+ пользователь библиотеки получит в консоль предупреждение о том, что используется нелегальный рефлекшн, просто когда он воспользуется вашей библиотекой, даже если не будет использовать этот спорный метод. Внутри библиотеки вы не можете это отключить, пользователю придётся писать дурацкие ключики при запуске JVM. Не каждый будет рад. Надо сделать это лениво (например, используя Initialization on demand holder idiom), чтобы не страдали те, кто не хочет использовать сомнительные методы.
Ещё я бы не делал пакет internal, а вместо этого сделал package-private классы в том же пакете, чтобы в Java 8 оно не торчало наружу. Package-private именно для этого и существует.
List.remove тоже поддержал (добавил требование, что индекс должен быть от 0 до длины списка), хотя здесь простой пример, всё известно заранее. Не факт, что в реальной жизни пригодится.
Не то чтобы ожидается, что работать не будут. Однако большинство нормальных использований либо ничего не сломают, либо сломают компиляцию. А чтобы сохранить компиляцию, но сломать рантайм, надо подумать. Так что да, для фана и тренировки мозга.
Говорит: «Блин, ну что такое, я вот всё сделал, выложил, никто не ревьюит». Ну да, никто не ревьюит. Сейчас июль, половина джавовского офиса в отпусках. Вот выйдут из отпусков и проревьюят.
Скорее всего делали не сами, а взяли готовое решение на специализированных сайтах. Либо купили один раз у кого-то давно и до сих пор используют. Персонально под каждого клиента код править — подороже будет услуга.
Насчёт джавы вы неправы. По ссылке по сути способы с помощью программы на Java сгенерировать ассемблерный код, а потом результат слинковать динамически с текущим рантаймом. Если у языка имеется интероп а нативным кодом, то такую конструкцию построить всегда можно, но это не является ассемблерный вставкой само по себе. Да и интероп у джавы довольно поганенький.
Простая задачка. Первая ошибка — это ссылка на необъявленный символ “Hello, а вторая — ссылка на необъявленный символ world”. Других ошибок нет. Вот и компилятор со мной согласен:
Hello.java:1: error: cannot find symbol
class Hello { void main() { System.out.println(“Hello, world”); } }
^
symbol: variable “Hello
location: class Hello
Hello.java:1: error: cannot find symbol
class Hello { void main() { System.out.println(“Hello, world”); } }
^
symbol: variable world”
location: class Hello
2 errors
Ещё текущая реализация жестоко ломает
subList
. Пример:А можно ещё веселее:
Сейчас уже интереснее, какое-то API вырисовывается. Маленькое замечание по имени — вместо
toList()
лучшеasList()
. Предлогto
традиционно сигнализирует о преобразовании, а адаптеры именуются начиная сas
.Метод
convertToImmutableList
— это очень грязно. Чистое и понятное API гораздо лучше сомнительного прироста производительности. Но если уж вы это делаете, позвольте дать несколько советов.Во-первых, сейчас семантика метода совершенно плохая. Он делает что-то, если что-то сработает, в зависимости от типов коллекций. А если не сработает, то результат будет другим. Надёжная система на это никогда не пойдёт. Гораздо разумнее сделать одинаковую семантику, и хачить только производительность. Можно сделать, например, метод
drainToImmutableList(Collection<T> c)
, который всегда перегружает данные в неизменяемый список и очищает исходный (вызываяc.clear()
). Для такого метода можно сделать быстрый путь дляArrayList
. Он будет работать так же, даже если рефлекшн не сработает.Во-вторых, рекомендую заменить
original instanceof ArrayList<?>
наoriginal.getClass().equals(ArrayList.class)
. Мало ли кто какой наследник сделал и каких гарантий он ожидает в этом наследнике.В-третьих, вы зря инициализируете поля безусловно в статическом инициализаторе. В Java 9+ пользователь библиотеки получит в консоль предупреждение о том, что используется нелегальный рефлекшн, просто когда он воспользуется вашей библиотекой, даже если не будет использовать этот спорный метод. Внутри библиотеки вы не можете это отключить, пользователю придётся писать дурацкие ключики при запуске JVM. Не каждый будет рад. Надо сделать это лениво (например, используя Initialization on demand holder idiom), чтобы не страдали те, кто не хочет использовать сомнительные методы.
Ещё я бы не делал пакет internal, а вместо этого сделал package-private классы в том же пакете, чтобы в Java 8 оно не торчало наружу. Package-private именно для этого и существует.
Всё так. Мы в джаве в аналогичном коде даже квик-фикс предлагаем:
Никто не знает, "Анну Каренину" уже запретили?
Неожиданно, кстати, обнаружилась польза от контракта для remove — подсветилось
res.remove(res.size())
. Видимо, никогда не выполнялась эта ветка.Всё же по-моему, от нулла больше реальных ошибок, чем от дженериков со стиранием.
А, кстати да. Я и забыл, что я сам это сделал.
List.remove тоже поддержал (добавил требование, что индекс должен быть от 0 до длины списка), хотя здесь простой пример, всё известно заранее. Не факт, что в реальной жизни пригодится.
Про метод-референс мы говорим, что а-та-та будет:
Ну сравнение c
new Integer()
понятно что подозрительное:x = (Integer)null
— дело святое (конечно, варнинг исчезает, если тип Object):Кое-что из остального поддержать можно, но не факт, что нужно...
Может быть в Чокурдах до сих пор так же дела обстоят и всё дело не в другом времени, а в другом месте?
Не то чтобы ожидается, что работать не будут. Однако большинство нормальных использований либо ничего не сломают, либо сломают компиляцию. А чтобы сохранить компиляцию, но сломать рантайм, надо подумать. Так что да, для фана и тренировки мозга.
Лучше всего написать в саппорт. Я не специалист по гредлу.
Вот, например.
В тестах у нас их полно. Мне кажется, в тестах они наиболее оправданны. Некоторые только ради них пишут тест на груви или Котлине.
Ну свежие апишечки он в конце перечислил, а это не часть джепов. Просто прямо скажем ничего нового в этой вашей джаве 13 не появилось :-)
Уже сентябрь кончается, а воз и ныне там.
Вон Саймон уже написал.
Скорее всего делали не сами, а взяли готовое решение на специализированных сайтах. Либо купили один раз у кого-то давно и до сих пор используют. Персонально под каждого клиента код править — подороже будет услуга.
Насчёт джавы вы неправы. По ссылке по сути способы с помощью программы на Java сгенерировать ассемблерный код, а потом результат слинковать динамически с текущим рантаймом. Если у языка имеется интероп а нативным кодом, то такую конструкцию построить всегда можно, но это не является ассемблерный вставкой само по себе. Да и интероп у джавы довольно поганенький.
Некогда по конфам разъезжать, надо баги фиксить, вон их сколько!
Простая задачка. Первая ошибка — это ссылка на необъявленный символ
“Hello
, а вторая — ссылка на необъявленный символworld”
. Других ошибок нет. Вот и компилятор со мной согласен: