Перейти к содержимому
Технологии IT обновлён 27.02.2024

Javanese Online

Описание на 450 символов для Telegram канала "Javanese Online":

Добро пожаловать в канал "Javanese Online"! Здесь вы найдете самые интересные статьи, новости, наблюдения и советы, связанные с языком программирования Java. Мы постоянно обновляем канал, чтобы предоставить вам актуальную информацию о последних тенденциях и разработках в мире Java. Независимо от вашего уровня опыта, вы найдете полезные материалы, которые помогут вам расширить свои знания и навыки в программировании на Java. Мы стремимся создать сообщество, где вы сможете обмениваться своими идеями, задавать вопросы и получать ответы от опытных профессионалов. Присоединяйтесь к "Javanese Online", чтобы оставаться в курсе последних новостей и развиваться вместе с нами в мире Java!

Публикации канала

В подвале клуба любителей Kotlin обнаружен static Эмпирически доступ к статикам на примере Java можно определить так: слева от . или :: стоит тип. Class.staticField Class.staticMethod() Class::staticMethod var cls = Class // error Отсутствие static на примере Kotlin: при доступе к членам слева от . или :: всегда стоит выражение. obj.prop obj::prop WithCompanion.func() WithCompanion::func // можно передать, присвоить: val cmp = WithCompanion Есть одно исключение: энамы. SomeEnum.Constant SomeEnum::Constant val expr = SomeEnum // error Если у энам-класса нет компаньона, то имя класса не будет выражением. А следовательно, enum-константы (а ещё values(), entries, valueOf()) — это статические члены! В спеке языка они называются static member callables.

Открыть в Telegram

Mike's IDE Extensions-0.35-base.jar 387.1 KB 🔌 Навалил фиксов 🔴 убрал фолдинг для backing property (фича появилась в языке) 🔴 убрал инспекцию @TargetApi → @RequiresApi (аналогичная появилась в Android Lint) 🟡 поправил хинты для вараргов и апкастов 🟡 починил фриз при анализе векторов 🟡 заткнул «Heavyweight property delegation» в тестах 🟢 добавил проверки pathData в строковых литералах 😼 GitHub 🛒 JB Marketplace

Открыть в Telegram

Корень корня всех зол Потрясающая археологическая работа по поиску истоков известнейшей фразы о преждевременной оптимизаци. Tl;dr заявление о том, что 97% кода можно не оптимизировать, но нужно знать, какие именно 3% кода «горячие», строится на анализе существовавших на момент написания статьи программ, которые по современным меркам считались бы очень простыми и маленькими. Зачастую там действительно был один основной цикл, а производительность всего остального не имела значения.

Открыть в Telegram

Selector expression На стыке функций-расширений и функционального типа есть такой замечательный конструктор типа: T.() -> R. Выражения таких типов спокойно кастятся к (T) -> R и обратно, а func(args) привычно раскрывается в func.invoke(args). Но у варианта-расширения есть и особый синтаксис: receiver.func(args). Он логичный, понятный и консистентен с написанием типа и синтаксисом вызова расширений. val b = String::isBlank "".b() А ещё он открывает нам знатный инсайд: между receiver. и (args) может находиться не только идентификатор, но и переменная, вернее, выражение! Для начала — несколько бесполезных способов записать "".isBlank(): • "".(String::isBlank)() — function reference • "".(fun String.() = isBlank())() — анонимная функция • "".({ s: String -> s.isBlank() } as String.() -> Boolean)() — лямбда • "".(providePredicate())() — произвольный вызов, возвращающий функцию Уверен, что это побочка, вызванная там, как устроен синтаксис expr.variable(). Тем не менее, в следующем примере: value .validate() .let { val t = if (simple) transform else provideComplicatedTransform() it.t(args) } .serialize() можно избавиться от let с лишней переменной: value .validate() .( if (simple) transform else provideComplicatedTransform() )(args) .serialize() что читается более последовательно и выглядит менее мусорно.

Открыть в Telegram

Что значит «no-cache», хвостовики, 1xx коды состояния, опечатки и прочие необычности в привычном HTTP. В статье с просторов интернета: HTTPWTF. Необычное в обычном протоколе.

Открыть в Telegram

Что в сигнатуре тебе моей? Есть в kotlin-stdlib функция text.ifEmpty { default }. Реализована она крайне просто: if (isEmpty()) defaultValue() else this. Интересна же функция тем, как она обходится с типами: "".ifEmpty { "" } // String "".ifEmpty { null } // String? stringBuilder.ifEmpty { "" } // CharSequence & … "".ifEmpty { 1 } // Comparable<*> & Serializable Такой вывод типов следует из сигнатуры. Давайте разберём поэтапно, в чём там волшебство. Например, если бы сигнатура была String.ifEmpty(() -> String): String то такое использование было бы невозможно: stringBuilder.ifEmpty { null } ❗️ ресивер должен быть строкой, а не билдером, ❗️ лямбда должна возвращать строку, а не null. То есть к функции можно сформулировать такие требования: 🔹 тип ресивера должен быть как можно шире. Функция isEmpty() объявлена у CharSequence — он-то нам и нужен, 🔹 тип дефолта должен быть ещё шире: там хоть null, хоть попугаи, хоть козявки — мы с ними никак не взаимодействуем, 🔹 возвращаемый тип должен сужаться по типам параметров: если там нет нуллов — их не должно быть на выходе и так далее. Пусть будет такая сигнатура: fun <C : CharSequence, T, R> C.ifEmpty(() -> T): R. Что будем писать в where? Объединений и пересечений в Котлине нет, то есть на месте R нельзя написать ни C & T, ни C | T. Интуитивно хочется написать R : C, R : T. Но это неверно: тут написано «возврат у́же, чем ресивер, и у́же, чем дефолт». У нас же требование противоположное: C и T должны «пролезть» на выход, через R. Правильное напрваление — C : R, T : R. Правда, компилятор корёжит, что C и так : CharSequence, куда тут ещё баунд. Настоящая сигнатура: @kotlin.internal.InlineOnly public inline fun <C, R> C.ifEmpty( defaultValue: () -> R, ): R where C : CharSequence, C : R { Ошибку компиляции здесь затыкает приватная аннотация InlineOnly. Нам так делать нельзя, зато можно @Suppress("BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER"). Обсуждение синтаксиса, который позволял бы писать подобные сигнатуры без изврата: KT-209 YouTrack Add lower bounds for generic type parameters (at first consider it) : KT-209 Use case (from 'Programming in Scala' by M.Odersky & others): Imagine we want to create covariant immutable queue (it can be covariant because it's immutable), but we have an append method, that spoils everything: class Queueᐸout Tᐳ { ... fun append(x: T):…

Открыть в Telegram

— Добро пожаловать на курс экстремистского программирования! — Может, экстремального? — Может...

Открыть в Telegram

Двуязычный API Положим, есть функция на Kotlin: fun <R> exec(f: () -> R): R её, конечно, можно использовать из Java: exec(() -> { return Unit.INSTANCE; }); но выглядит это убого. Для создания более дружелюбного интерфейса можно сделать следующее: 1. добавить перегрузку с «родным» для Java функциональным интерфейсом fun <R> exec(f: Supplier<R>): R 2. добавить частный случай для R = Unit fun exec(f: Runnable) 3. спрятать ЪКотлинЪ-вариант от Джавы @JvmSynthetic fun … либо сделать его менее заметным @JvmName("exec_4k") fun … 4. сделать ЪДжаваЪ-вариант менее заметным в Котлине @JvmName("exec") fun exec_4j(… Итого: @JvmName("exec_4k") fun <R> exec(f: () -> R): R = f() @JvmName("exec") fun <R> exec_4j(f: Supplier<R>): R = f.get() @JvmName("exec") fun exec_4j(f: Runnable) = f.run()

Открыть в Telegram

Mike's IDE Extensions-0.34-base.jar 392.8 KB 🔌 Поддержка K2 готова, а вместе с ней • улучшен фикс в инспекции по ловле регекспов [а-яА-Я] • жалуюсь на "#ЦЦВВЕЕТТ".toColorInt() так же, как на Color.parseColor • блюду порядок сортировки атрибутов стиля при вызове context.withStyledAttributes так же, как и для context.obtainStyledSttributes В целом получился чисто технический релиз, основная фишка лишь в том, что теперь плагин работает 😌

Открыть в Telegram

Роберт Лафоре. Структуры данных и алгоритмы Java, второе издание Чувствуется, что Java — не родной, не любимый язык автора: кодстайл не соблюдается, классы и файлы порой называются со строчной буквы. Имена методов часто не передают их сути. Первый же пример кода (с. 32) не скомпилируется. Скоупы переменных чересчур широкие. Положение фигурных скобок выбрано рандомом (попробуй разбери вложенность на с. 167). Вместо стандартного toString (EJ3*, Item 12) у многих классов есть функция, которая печатает содержимое в stdout. Наличие псевдополя length у массивов игнорируется, хотя во введении в Джаву автор объяснял про него. Модификатор final не используется. int[] после создания вручную заполняется нулями. Ну и так далее — короче, с языком полный провал. С момента выхода оригинала (2003, SAMS, времена Java 1.4) до перевода в моих руках (2019, Питер, Java 11) прошла целая эпоха. Было очень наивными решением издавать книгу без изменений. Например, для демонстрации материала автор написал несколько апплетов — олды здесь? Непосвещённый читатель задолбается их запускать. Также автор по какой-то причине упоминает классы Stack, Vector и Hashtable. Хоть дженерики пока не появились, но привычные нам коллекции тогда уже завезли. Работа с массивами. Понимаю, что пример, где делают всё ручками, быть должен — это закон жанра. Но как насчёт использования методов indexOf*, System.arraycopy, Arrays.binarySearch в дальнейшем? Без них в реальном мире жить неуютно, как и говорить о сортировке, не упоминая компараторов. Везде, где автор использует массивы, нет примеров ресайза — а неискушённый читатель может и не знать про Arrays.copyOf. Не понятно, что автору мешало в своих коллекциях сделать инициализацию готовым массивом. Десять строчек с arr.insert() — это ж боль. Кстати, видите утечку памяти на с. 77? А она есть! См. EJ3*, Item 29, первый листинг. Дэку уделён один абзац — мол, такая штука есть, но не очень нужна. На самом деле ArrayDeque (кольцевой буфер) — это самая универсальная коллекция во всём Котлине: она тебе и вектор, и обе очереди. О хорошем. В книге доходчиво объясняется асимптотика, вплоть до изображений графиков и разъяснения, что такое логарифм — если кто не знал, а потом забыл. Алгоритмы сортировки хорошо объясняются на словах и вдобавок визуализируются. Деревья и графы визуализируются — а это очень важно для понимания темы. Двоичные деревья (поиска и пирамида a.k.a. куча), красно-чёрные, В-деревья — это всё очень интересно и увлекательно (хотя к-ч я так до конца и не понял). Есть перевод математических выражений в префиксную нотацию, есть префиксное дерево. Можно было бы и про AST немного поговорить :) Связанный список. Автор утверждает, что эта структура данных, в отличие от вектора, использует память эффективно, ведь пустой хвост массива отсутствует. Посчитаем? Полупустой массив занимает 2n памяти. Узлы же, в каждом из которых есть ссылка на данные, следующий узел, невидимая ссылка на класс и пэддиннг, занимает 4n. Частота и сложность аллокаций, локальность — тут только свернуться клубочком и плакать. Ещё один момент из реальной жизни забыт: проверки корректности входных данных. Книжный стек считает, что пользователь сам проверит, не пустой ли он. Наивно! (EJ3*, Item 49) В рекомендациях по выбору структуры данных делается нелепое допущение: проще — лучше, ведь тебе придётся реализовывать алгоритм самому! Доходит до того, что вектор при малом объёме данных стоит предпочесть хэш-таблице. На деле же критерий выбора звучит так: нужен порядок вставки или доступ по ключу? Вердикт: интересная книга. Читать только под присмотром взрослых. *EJ3 — Joshua Bloch. Effective Java, Third Edition *Arrays.indexOf не существует. Его надо написать один раз либо использовать методы из ArraysKt

Открыть в Telegram

По-явански: Довольно интересная книга, и, как видно по закладкам, вызывающая у меня обилие разнообразных реакций. Близко к сердцу пришлась мысль, что большое — хрупко: оно сложное, внесение изменений аукается неожиданными последствиями, а внезапные встряски могут всё… Ещё тезис: не доверяйте людям, которые не рискуют собственной шкурой. Например, инвестиционные рекомендации ценны только тогда, когда исходят от человека, сделавшего на этом состояние. Это обобщение принципа, который я давно исповедую: обучать должен только тот, поднялся на практике предмета, а не на преподавании. Легко учить убивать драконов: никто не заявит, что твои приёмы против них неэффективны. Только вот в этом лесу нет никаких драконов.

Открыть в Telegram

Голос из-под шторки | Миша Левченко: Антихрупкость – Нассим Талеб Довольно интересная книга, и, как видно по закладкам, вызывающая у меня обилие разнообразных реакций. Близко к сердцу пришлась мысль, что большое — хрупко: оно сложное, внесение изменений аукается неожиданными последствиями, а внезапные встряски могут всё разрушить непредсказуемым образом. Что в очередной раз возвращает нас к философии Unix. :)

Открыть в Telegram

Почти онлайн Сейчас вышки LTE с коронавирусными чипами от меня далековато, поэтому порой бывает так, что в руках при включённом экране я вижу только локальные данные, а интернет неожиданно ловится в кармане. Телеграм пользуется моментом, а остальные приложения заставляют меня страдать. Офлайн можно обработать следующими способами, от самого халтурного до наиболее предпочтительного: 1. Что-то пошло не так. Выйди и зайди нормально. 2. Сломалось, вот тебе утешительная кнопочка retry. 3. Не сработало, но мы дождёмся интернета и попробуем снова. Оставайтесь на линии. 4. Иногда таймаутится, но мы будем долбиться в сеть, вдруг сработает. 5. Готово! Можешь уходить, твоё действие сохранено и стоит в очереди на отправку. Вход в банк — это уровень 1: будешь вводить пин-код снова и снова, пока не повезёт поймать волну. Отправка сообщения в Телеграме — уровень 5: нажал кнопку — и забыл, больше ничего делать не нужно. Не сейчас — так через час. А если нет — то завтра или через неделю, мы всё записали и ждём момента.

Открыть в Telegram

В Java нет UB и утечек памяти Это действительно так с точки зрения C/C++: целочисленное переполнение определено, разыменование нуля — тоже. Компилятор не делает вид, что этого не может быть. Если ссылку на объект потеряли, то и объекта скоро не станет. Но мы же не в C/C++? В другой среде термины могут трактоваться иначе. Если запустить несколько потоков, какой стартанёт первым? Одному планировщику известно. Если один поток пишет в массив, а второй читает, что он там увидит? Зависит от архитектуры процессора, размера кэшей и снова от планировщика. Ну чем не UB? Если навечно зарегистрировать какой-нибудь слушатель, который удерживает временный объект, можно ли сказать, что последний утёк? Разрешаю. Вот и выходит, что UB есть и утечки есть. В Си — сишные; в Джаве — джавовые.

Открыть в Telegram

Голос из-под шторки | Миша Левченко: Писать "потенциально-тестируемый" код, но не писать на него тесты – пустая трата времени. Да.

Открыть в Telegram

Зигота В Андроиде зиготой называется процесс, от которого форкаются процессы приложений. Он содержит уже загруженный код SDK, а код приложения загружается после форка. В биологическом же смысле зигота содержит уже готовый ДНК организма, унаследованный от обоих родителей. Таким образом, зигота в Андроиде — на самом деле яйцеклетка, в которую в процессе запуска (оплодотворения) после форка внедряется код приложения (сперматозоида).

Открыть в Telegram

idea.plugin-0.33.jar 411.4 KB Выпустил новую версию плагина для IDE: • аллокации вараргов теперь бросаются в глаза, • <vector pathData теперь переписываем умнее, например, Ll может заменяться на HhVv, а несколько таких команд — склеиваться в одну, • ну и фиксы, конечно же, • а релиз теперь, помимо Маркетплейса, можно найти здесь и там. K2, к сожалению. будет уже когда-нибудь потом.

Открыть в Telegram

Варианты корутин В разных языках корутины ведут себя по-разному. Вот краткий обзор. C#, JavaScript Eager & parallel by default: async-функция возвращает уже запущенный Task/Promise, а await приостанавливает выполнение до завершения задачи. + async не является отдельным видом функций, а просто намекает, что возвращается фьюча – забытый await приводит к параллельному выполнению Go Fire and forget: go statement запускает указанную функцию отдельно. + «неокрашенные» функции – для возврата значения нужна обвязка в виде канала Kotlin Sequential by default: suspend-функция может приостанавливаться. Для параллельного запуска нужен отдельный вызов корутин-билдера — async, launch. – suspend-функции нельзя вызывать из обычных, иерархия функциональных типов разделяется + параллельность явная Rust Lazy: async-функция возвращает фьючу, но запускается она только после .await. + async-функции можно вызывать из обычных + и они явно await-ятся либо явно spawn-ятся параллельно – у тебя там локальная переменная не-Send-типа, так что struct для фьючи сгенерить не получилось, извиняй, братан

Открыть в Telegram

Уведомление об уведомлении Письмо на почту: %username% назначил вас исполнителем задачи %taskname% Сообщение от коллеги: Привет! Перекинул на тебя задачу https://… Было? Бесит? 🥲 Мы ведь не знаем, как у наших коллег настроены уведомления. Но со стороны трекера задач #идея напрашивается очень простая: отвечать на действие пользователя всплывашкой вида «мы отправили уведомление исполнителю на почту» или даже «мы кинули уведомление исполнителю прямо в лицо браузер». Всё! Ты знаешь, что коллега увидел. Или коллега знает, что ты увидел.

Открыть в Telegram

Комментарии

0

Комментарии пишут вошедшие — так видно, кто автор.

Войти

Комментариев пока нет

Будьте первым, кто расскажет о канале другим.

Пожаловаться на канал

Расскажите, что не так: модератор проверит канал и примет решение. Подпись не нужна, но почту можно оставить — тогда ответим.

Причина Что не так (необязательно) Почта для ответа (необязательно)
Открыть в Telegram