Кстати, пометка HotSpotIntrinsicCandidate не означает, что это на самом деле интринсик, и уж точно не «позволяет ВМ создавать для них высокопроизводительный машинный код». Чтобы сделать интринсик одной пометки мало. И помечено существенно больше методов, чем на самом деле интринсиков (на то оно и «candidate»). Поэтому закладываться на это не стоит.
Кстати, можно ещё приложиться к Arrays.asList. Там вроде SubList вообще специально не реализован, а мог бы быть.
А-а-а, ты везде!!! Приходишь на работу — там новые фичареквесты от тебя. Идёшь почитать, что в джаве делается, а там письма от тебя в мейлинг-листе. Хочешь передохнуть, заглядываешь на Хабр, и тут ты!!!
Ну сами они волшебным образом не заработают, конечно. Но я бы не сказал, что прямо всех инспекций. Вот с лямбдами до сих пор попадаются недоработки. Например, раньше если в поддереве искался return, то только классы надо было игнорировать, а теперь ещё и лямбды. Некоторые инспекции могут быть не обновлены и принять return внутри лямбды за выход из неё. Хотя их уже мало осталось. А есть способ лучше?
Странно, что здесь не упоминается ни JNR, ни тем более JNR-x86asm, а ведь это неплохое решение, которое уже работает. А ещё стоит покопать в проект Panama, Володю Иванова потыкать. Они там тоже ассемблер прямо в джаве пишут, причём почти без накладных расходов на переход туда и обратно.
Да, эта будет только для джавы. Кросс-языковые инспекции (Java-Kotlin) есть, но пока очень мало. Там же не только синтаксис, но и семантика существенно различна. Например, в Java мы всегда считаем, что плюс не создаст побочных эффектов (строго говоря, может, если вызовется странный toString), а в Котлине плюс может быть перегружен. Тонкостей множество даже между такими близкими языками.
Про Optional уже были статьи на Хабре. Например, вот постарее или вот совсем недавно. Когда пишете новую статью, полезно хотя бы себе самому ответить, что она добавит к уже существующим статьям, а в чём повторится.
Не совсем красиво я выразился, пожалуй. Нулевые функции — это читерство, а вот функции, принимающие или возвращающие null — вполне законны. Очевидно, что flatMap должно соответствовать операции bind. Вопрос: какая операция соответствует операции return? Предположим, что Optional.ofNullable. Тогда f = Optional::of нарушает закон (return v) >>= f ≡ f v для v = null. В терминах Java слева Optional.ofNullable(null).flatMap(f) => empty(), а вот f.apply(null) — NPE. Ладно, предположим, что return — это Optional.of. Тогда возьмём f = Optional::ofNullable и снова получим несоответствие.
Более интересные эффекты проявляются с операцией map (аналог хаскеловского fmap). Пусть есть две функции:
UnaryOperator<Object> f = x -> null;
UnaryOperator<Object> g = x -> "foo";
Возьмём произвольный непустой Optional opt. Композиция fmap подразумевает, что opt.map(f).map(g) эквивалентно opt.map(g.compose(f)), а это не так: первый — это всегда empty, а второй — это Optional.of("foo").
Флаг truncated должен быть равен true, если текст слишком длинный, то есть если выполняется условие if (len > kMaxShortPrintLength).
Я это понял, глядя глазами в код в течение минуты. Но ведь наверняка у вас на условии if (len > kMaxShortPrintLength) есть ещё одна сработка вроде "expression 'len > kMaxShortPrintLength' is always false". Разве нет? Если так, то сразу становится очевидно, что вторая сработка — следствие первой, надо просто в каждом методе смотреть предупреждения по порядку.
Потому что всегда есть риск переобучения, даже ненарочный. К примеру, вы придумали алгоритмы A, B, C, D. Обучили их все на данных 2016 года и проверили на данных 2017. A, B, C не сработали, а D показал какую-то корреляцию. Вы идёте и рекламируете всем алгоритм D, говорите, что он хорошо предсказывает. Хотя на самом деле в выборке из достаточно большого количества случайных алгоритмов всегда найдётся такой, который при обучении на данных 2016-го года продемонстрирует с данными 2017-го года корреляцию не хуже некоторой наперёд заданной. Вот надо оценить, при создании этого алгоритма сколько вы алгоритмов перепробовали (если к примеру, вы варьировали некоторый настроечный параметр алгоритма, то каждое значение настроечного параметра — это по сути новый алгоритм). Если вы в процессе создания предсказывающего алгоритма перебрали на порядки меньше алгоритмов, чем требуется по теории вероятности, чтобы случайно предсказать результат, то, возможно, ваш алгоритм не полное фуфло. К сожалению, не каждый учёный делает такие выводы. Не каждый вообще фиксирует все свои ошибочные шаги и несработавшие идеи, а без этого не оценишь шансы переобучения. Ведь если бы любая из несработавших идей случайно сработала, вы бы на ней остановились, поэтому их наличие повлияло на результат.
В проектах где много открытых тикетов и авторы сами заинтересованы в новых контрибьюторах, обычно есть какой-нибудь специальный тэг на тикетах типа «good first issue» — несложная вещь, до которой просто руки не дошли, но новичок вполне может с ней справиться.
Но помните, что не все проекты вообще заинтересованы в новых контрибьюторах.
Вы меня неправильно поняли. Опечатка в интерфейсе — это «действительно баг». А использование в коде одной конструкции вместо другой, которая такой же длины, такой же понятности и, вероятно, даёт исчезающе малый прирост производительности, — это косметика. Я про косметику в коде, а не в том как приложение выглядит для пользователя.
Есть контракты, но они довольно ограничены. Здесь можно написать @Contract("null -> false"), и это будет учитываться. А вот информация о длине массива во внешний метод не попадёт.
-XX:ReservedCodeCacheSize
Кстати, пометка
HotSpotIntrinsicCandidate
не означает, что это на самом деле интринсик, и уж точно не «позволяет ВМ создавать для них высокопроизводительный машинный код». Чтобы сделать интринсик одной пометки мало. И помечено существенно больше методов, чем на самом деле интринсиков (на то оно и «candidate»). Поэтому закладываться на это не стоит.Кстати, можно ещё приложиться к Arrays.asList. Там вроде SubList вообще специально не реализован, а мог бы быть.
А-а-а, ты везде!!! Приходишь на работу — там новые фичареквесты от тебя. Идёшь почитать, что в джаве делается, а там письма от тебя в мейлинг-листе. Хочешь передохнуть, заглядываешь на Хабр, и тут ты!!!
Ну сами они волшебным образом не заработают, конечно. Но я бы не сказал, что прямо всех инспекций. Вот с лямбдами до сих пор попадаются недоработки. Например, раньше если в поддереве искался return, то только классы надо было игнорировать, а теперь ещё и лямбды. Некоторые инспекции могут быть не обновлены и принять return внутри лямбды за выход из неё. Хотя их уже мало осталось. А есть способ лучше?
Странно, что здесь не упоминается ни JNR, ни тем более JNR-x86asm, а ведь это неплохое решение, которое уже работает. А ещё стоит покопать в проект Panama, Володю Иванова потыкать. Они там тоже ассемблер прямо в джаве пишут, причём почти без накладных расходов на переход туда и обратно.
Да, эта будет только для джавы. Кросс-языковые инспекции (Java-Kotlin) есть, но пока очень мало. Там же не только синтаксис, но и семантика существенно различна. Например, в Java мы всегда считаем, что плюс не создаст побочных эффектов (строго говоря, может, если вызовется странный toString), а в Котлине плюс может быть перегружен. Тонкостей множество даже между такими близкими языками.
Я пока не особо оценил Котлин. Кроме того, я занимаюсь поддержкой языка Java, поэтому для догфудинга разумно самому писать на этом же языке.
Да, на мой взгляд проще понять ー Optional без всяких аналогий, чем вникнуть в эту уйму объектов и взаимодействий между ними…
Про Optional уже были статьи на Хабре. Например, вот постарее или вот совсем недавно. Когда пишете новую статью, полезно хотя бы себе самому ответить, что она добавит к уже существующим статьям, а в чём повторится.
Не совсем красиво я выразился, пожалуй. Нулевые функции — это читерство, а вот функции, принимающие или возвращающие null — вполне законны. Очевидно, что flatMap должно соответствовать операции bind. Вопрос: какая операция соответствует операции return? Предположим, что
Optional.ofNullable
. Тогдаf = Optional::of
нарушает закон(return v) >>= f ≡ f v
для v = null. В терминах Java слеваOptional.ofNullable(null).flatMap(f) => empty()
, а вотf.apply(null)
— NPE. Ладно, предположим, что return — этоOptional.of
. Тогда возьмёмf = Optional::ofNullable
и снова получим несоответствие.Более интересные эффекты проявляются с операцией
map
(аналог хаскеловского fmap). Пусть есть две функции:Возьмём произвольный непустой Optional opt. Композиция fmap подразумевает, что
opt.map(f).map(g)
эквивалентноopt.map(g.compose(f))
, а это не так: первый — это всегда empty, а второй — этоOptional.of("foo")
.Я это понял, глядя глазами в код в течение минуты. Но ведь наверняка у вас на условии
if (len > kMaxShortPrintLength)
есть ещё одна сработка вроде "expression 'len > kMaxShortPrintLength' is always false". Разве нет? Если так, то сразу становится очевидно, что вторая сработка — следствие первой, надо просто в каждом методе смотреть предупреждения по порядку.Думаю, количество звёзд коррелирует с забюрократизированностью проекта.
https://www.jetbrains.com/help/idea/running-inspections-offline.html
А если у вас правильный CI, то всё будет работать из коробки :-)
Но помните, что не все проекты вообще заинтересованы в новых контрибьюторах.
Да, со скриншотами не очень получилось. Шрифт явно не подходящий. В следующий раз учту :-)
Если метод статический, скорее всего контракт сам выведется. Посмотрите по ctrl+q.
Есть контракты, но они довольно ограничены. Здесь можно написать
@Contract("null -> false")
, и это будет учитываться. А вот информация о длине массива во внешний метод не попадёт.