TGViewer
Dev Easy Notes Dev Easy Notes @dev_easy_notes · 2.91K subscribers
Post #231 3.46K
Два друга @JvmWildcard и @JvmSuppressWildcards.

В комментах накинули вопрос про @JvmSuppressWildcards. Тоже довольно неочевидная штука, но порой приходится разбираться. Суть в чем, Java и Kotlin полностью совместимы, что означает что из Java можно вызывать Kotlin, и наоборот. На стыке этих двух языков начинаются приколы, например в Kotlin все типы делятся на Nullable и NotNullable, а в Java такого разделения нет. 

Работа дженериков тоже немного отличается. Буквально в предыдущем посте я описывал, что ковариантность и контравариантность в Kotlin может работать на уровне классов, а не ссылок. И вот пример:

class Box<out T>(val value: T)

fun box(value: Integer): Box< Integer> = Box(value)
fun unbox(box: Box<Number>): Number = box.value


Как видите в Box дженерик помечен как out, что означает ковариантность на уровне всех объектов. Только это работает на уровне Kotlin. Если попытаемся вызвать метод box из Java, то он вернет Box без дженерика. Это как бы немного нарушает логику ковариантности которую обещает Kotlin. При этом в методе unbox автоматически появится wildcard. В итоге в Java получим вот это:

Box box(Integer value)
Number unbox(Box<? extend Number>)


В целом все не так страшно, однако иногда охото подкрутить это поведение. Например, мы не хотим, чтобы в методе unbox автоматически проставлялся wildcard. Или же напротив проставлялся в результатах функции, в методе box. И вот для этого, нужны наши волшебные аннотации. Как всегда, лучше на примере.

Делаем в Kotlin:  

fun box(value: Integer): Box<@JvmWildcard Integer> = Box(value)

Получаем в Java:

Box<? extend Integer> box(Integer value)

Делаем в Kotlin:  

fun unbox(box: Box<@JvmSuppressWildcards Number>): Number = box.value

Получаем в Java:

Number unbox(Box<Number> box)

Сравните эти две полученные функции с дефолтным поведением и суть станет ясна.

Где это нужно на практике? У меня такое было только при работе с Dagger. Фишка в чем, в том что Dagger работает на базе Kapt. Если вдруг не знали, то kapt работает в два приседания. Сперва он перегоняет весь код в Java Stub и только потом генерит нужный код. Поэтому он такой долгий и по этой причине иногда нужно делать подсказки компилятору, когда пишем модули на Kotlin. В противном случае кодогенератор начинает чудить и падать.
  • 🔥 23
  • 👍 4
  • 🤔 1
More from @dev_easy_notes
  1. Sep 24, 2026На всякий случай напомню напомню, если такую хуйню видите, сразу в бан кидаете. Вы скорее…
  2. Aug 4, 2026Короче, поясню, я давно ничего не пишу, потому что заебался) возможно я скоро вернусь, как…
  3. Aug 4, 2026Post #596
  4. Apr 17, 2026Меня вот что еще дико бесит, через год я буду уже как 10 лет в индустрии и все равно, кажд…
  5. Apr 15, 2026video post
  6. Apr 9, 2026Как оценить работу модели? Часто вижу высказывания в стиле: вот новый клод стал тупее, или…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →