Pull to refresh

Comments 75

Спасибо, статья интересная, я тоже кое что из нее почерпнул. Но есть возражения по поводу «Удобной инициализации коллекций» и эффекта Double Bracer в целом. Дело в том что каждый такой «эффект» порождает в приложении новый анонимный класс, а слишком большое их число это не очень хорошо.
> новый анонимный класс

Помимо этого, насколько мне известно, блок инициализации во время компиляции копируется автоматически в начало каждого конструктора текущего класса, что весьма неэффективно.

Вообще не рекомендуется к использованию как статический, так и не статический блок инициализации.
Тут только сказано, что данный блок вызывается после конструктора суперкласса (что логично), про копирование ни слова.

А вот про рекомендуемость использования блоков инициализации я спорить не буду, потому как своего однозначного мнения еще не сложил.
Извиняюсь, наверное это меня попутало:

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
На тестировании скорость загрузки классов не так критична как на боевом приложении, поэтому там пожалуй это очень элегантное решение.
удобно, но в продакшене на боевом коде (не тестирующем) это дает большой оверхед
Красота, как говорится, требует жертв. Это не для узких мест, а вообще, как мне кажется, профайлинг и рефакторинг решает подобные проблемы.

То, что я поведал, более относится к возможностям, чем к потребностям. Кто, программируя для Java, печётся о таких мелочах? Возьмите даже функциональные и не только языки, которые компилируются в байт-код JVM. Их замыкания пока (надеюсь) реализуются именно посредством анонимных классов. И никто особо не жалуется, поскольку бесполезно:)
Если ищете каверзные вопросы, то есть их много в книге Kathy Sierra SCJP Study Guide. К ней прилагается мок экзамен.

Одному мне кажется, что хабровчане стали активно учить жаву?
> Одному мне кажется, что хабровчане стали активно учить жаву?
Она того стоит. Кроме того на базе Java появляется много новых технологий, которые возможно в будущем будут очень популярны и знание особенностей самой Java поможет лучше понять их.
Или наоборот, от невостребованности, пишут статьи для Хабра, делать то нечего :)

Скорее просто тенденция у джава-кодеров проявлять стабильную активность.
Джава в будущем обязательно будет иметь свою нишу.
Забавно, т.е. сейчас она ее не имеет?
Тоже заметил. Что ни день то статья. Радует.
«Малоизвестные особенности» — это очень громкое заявление. Все что перечислено прекрасно описано и разжевано в документации и учебниках по Java.
Если в процессе изучения языка освоить хотя бы: «The Java™
Language Specification» (James Gosling, Bill Joy, Guy Steele and Gilad Bracha), «Thinking in Java» (Bruce Eckel) и «Effective Java» (Joshua Bloch) то никаких откровений этот пост не принесет.
Господа, читайте книги. Учиться языку на обрывочных статьях контрпродуктивно.
Вы абсолютно правы. Читая пост, испытывал дежавю, как будто «Thinking in Java» перечитывал.
О, хорошо, что обновил комментарии. Именно, блоки инициализации, синтаксис метки, про модификации массивов итд — это начальные знания фактически или следуют из очевидных свойств самого языка, в любой книге по Java есть. Или, может, просто не принято теперь книжки читать? Не понимаю…
Книжки читать принято. Но они, как известно, стоят денег. Раздачи PDF на торрентах не считаем. И такого рода статьи сподвигают тех, кому раньше «не хватало времени» и у кого «не было необходимости», все ж таки купить эти книги и как следует их изучать. ИМХО, польза очведина.
Откровенно говоря, не понимаю почему PDF (djvu etc.) не считается :(
Книги, действительно стоят немалых денег и поэтому 80% информации стараюсь получить из электронных источников. Буквы там точно такие же :)
Ничего против электронных источников не имею. Но мне кажется, что их тоже стоит покупать, если автор не указал обратного. Нет?:)
Буду искренен — мне никогда не приходила в голову такая мысль.
Также не стоит забывать, что не все книги есть в продаже в силу своей специфичности или возраста.
Указанные выше точно без труда можно найти на Amazon и тому подобных сервисах. Обычно продают как бумажный вариант, так и сверстаный в PDF иди DJVU. Попробуйте покупать, вам понравится :)
Хм… вообще как бы, многие люди электронные книги тоже покупают…
К сожалению и, может, стыду документацией «Language specification» не зачитывался, я её как справочник обычно использую.

А вот по книгам «Effective Java» и «Thinking in Java» (всем рекомендую) я даже конспект составлял. Первым делом, перед тем как писать эту статью, я его перечитал и перелистал эти книжки. Пункт третий этой статьи, если не ошибаюсь, у Брюса Эккеля и почерпнул. Остальные пункты не из этих книг.

Выводы и примеры (за исключением одного) делал сам, исходя из своего понимания платформы Java. А заголовок действительно немного неудачный… для Java-гуру, коим я не являюсь (пока). Для всех же остальных, считаю, самое оно.
Уверяю Вас, что первые 4 пункта есть у Эккеля. Могу ручаться за 4-е издание.
А можете указать главу и цитату про, пусть будет, второй пункт. Может я слишком плохо искал.
И где там упоминается зачем, собственно, нужны вложенные классы в интерфейсы?
Не спора ради.
Я ведь так и знал, что до этого дойдёт! :)
Глава 10 «Внутренние классы». Страница №260, второй абзац заголовок «Классы внутри интерфейсов».
Вот, точно! Я в статье хотел и о тестировании ещё написать, но никак не мог вспомнить и найти источник. Но, на мой и не только мой взгляд, вовсе не для этого нужны классы в интерфейсах. По крайней мере не только для этого.

И согласитесь, Брюс не писал об истинном, ООП-применении их. И, хотя книга его замечательна, она не без недостатков. Примеры в ней, по-моему, оставляют желать лучшего. Собственно из них мало что понятно.

Не пытаясь возвысить себя, тем более над ним, замечу, что примеры я подбирал достаточно долго и тщательно. И если из них очевидны представляемые идиомы, значит я достиг своей цели.
UFO landed and left these words here
Жаль, а я старался. Почти в каждом из них есть скрытый смысл(:
UFO landed and left these words here
по роду деятельности приходится кодить как на Java, так и на C#. И, ей богу, очень хватало ИНОГДА быстрой инициализации коллекций (описанной в первом пункте), как это можно ыбло провернуть в C#.
А про ковариацию — вообще круть. Жду такой же плюшки в C# (может есть уже?), чтоб не писать постоянно приведение типа.
Очень полезно!
в C# есть уже нечто подобное, просто чуть длиннее и чуть менее красиво.
object ICloneable.Clone()
{
	return CloneEntity();
}
public MyClass Clone()
{
	return CloneEntity();
}

Таким образом метод clone(); у объекта типа MyClass будет возвращать уже тип MyClass

P.S.
Простите за оффтоп.
Ну, на практике в Шарпе все равно более коротко получается даже с кастом:

var foo = new Covariance();
var bar = foo.Clone() as Covariance;


Хотя, конечно, компилятор мог бы уже и сам предполагать ковариантные типы.
Для быстрой инициализации можно использовать удобные классы из гугловской библиотеки guava

Sets.newHashSet(E... elements) 


в коде это выглядело бы так:

Set<String> names = Sets.newHashSet("one", "two", "three");


Выглядит намного читабельнее, чем инициализация через {{}}
Да, безусловно. Жаль, что Google и Oracle «поссорились». Было бы намного лучше, если бы скооперировались, тем более, что Google, в Java вносит/вносил наибольший вклад (в сравнении с другими корпорациями).

Глядишь — и гугловские библиотеки стали бы частью стандарта.
вот это и настораживает, нужно использовать какие-то другие библиотеки, не входящие в офф.JDK. Хочется как всегда стандартных средств, пусть даже и предлагает альтернативу Гугль
В своё время говорили, что C# — лишь клон Java и призван отвлекать на себя её разработчиков. Теперь C# в части синтаксиса вырвался далеко вперёд. Но такая ситуация сложилась уже давно. Не потому ли Sun, чувствуя свою/Явы гибель раскрыла исходные коды?
Когда Oracle приобрела Sun, развитие языка сдвинулось с мёртвой точки. Глядишь в восьмой части реализуют весь обещанный «сахарок».
Бросьте, синтаксис — это ещё не весь язык. Java окружена огромнейшей экосистемой, которая не даст ей погибнуть ещё очень долго, и вообще предпосылок для её гибели не наблюдается. Если разработчики и начнут перебегать в стан Microsoft, то уж точно не из-за того, что в C# раньше, чем в Java, появляются какие-нибудь там замыкания или континуации.
Ну вообще так оно и есть, про C# и Java :) Вернее я разделяю такую точку зрения, да и альтернатива нужна была в самое своё время.
А по поводу консерватизма синтаксиса Java всегда думал, что язык довольно таки лаконичный, что новые конструкции не добавляются в угоду чистоты этого самого синтаксиса, ну или тщательно обдумываются. Особенно так кажется, когда смотришь на всё новые и новые фичи C# (сахарок, да и просто синтаксиса) волей-неволей кажется, что скоро из C# сделают второй C++, когда он станет чересчур перегружен диалектикой, да и этим самым сахаром.
Новые конструкции не добавляются ввиду тормознутого JCP и общего курса партии на максимальную обратную совместимость. Майкрософту легче, они сами себе хозяева, да и проблему с обратной совместимостью решили немного по-другому — установкой множества версий .NET, которые могут работать параллельно и не мешать друг другу. Поэтому платформа .NET более динамична, чем Java.
Ну точно так же можно на одной машине иметь много версий Java.
мне кажется тут дело не в том, что можно иметь несколько JVM, а в том, что каждая из них обратно-совместима.
Кстати, у MS видимо что-то сменилось с видением совместимости, на заре маячит .NET 4.5, который идет на замещение 4.0 и никак иначе, новость как раз промелькала, что разрабы тестят новый дотнет на предмет полной совместимости с 4.0. В случае же с 3.5 такого не было
Но нельзя задать используемую версию на уровне приложения. Чтобы оно говорило: «Мне нужна Java 5, а то, что у тебя тут стоит Java 7, меня не волнует». Обратная совместимость Java, увы, небезупречна.
Как бы там ни было, Java в отличие от C# обратно совместима начиная с версии 1.2. И, за некоторыми исключениями, write once, run anywhere, как и обещали. Что не скажешь о Шарпе с его постоянно появляющимися новыми и новыми версиями. Применимо ли к нему название DLL-hell?
Зря, по-моему, сановцы изменили нотацию версий. По сути Ява как была второй, так и осталась. Кардинальных изменений не было пока.
ну это просто маркетинговый ход такой, выдавать версию JDK за версию языка. Мало кто задумывается, что Java всё ещё вторая. А у MS и язык и платформа имеют свои версии, хоть и слегка синхронизированы (.NET 3.0/3.5 — C# 3.0, .NET 4.0 — c# 4.0) ввиду того, что язык писался специально для платформы.
У Sun изначально с версиями что-то неладное творилось, кто там у них пил/курил уже неизвестно :) JDK 1.0,1.1,1.2,1.3,1.4,5,6,7… Java 1.0, 1.1, 1.2=>2… JRE 1.1, 1.2,...,1.7 (вроде всё в порядке)
К сожалению, нестатическими блоками инициализации нельзя инициализировать объекты, подлежащие сохранению в БД, так как JPA-провайдер «не узнаёт» анонимный класс.
Зато эту особенность языка Java удобно использовать при написании DSL или fluent API.
На самом деле было бы интересно собрать в одну статью изящные примеры применения различных особенностей и плюшек Java из крупных фреймворков и проектов с открытыми исходниками. Это же по сути приемы проектирования, только на уровне языка.
Спасибо за статью. Думаю статья полезна всем «живописцам», как начинающим, так и умудрённым опытом. Весьма полезно вспомнить особенности Java, про которые забываешь даже при постоянном кодировании. А после долгого перерыва — тем более.
Отличная статья. Только закончил читать Кея Хорстмана, там это все описывается замечательно, так, что просто повторил :) Полезно на начальных этапах, а то к концу книг кое-что из начала уже подзабыл.
Еще очень понравился синтаксис с нестатическими блоками, буду пользоваться… главное не переборщить.)
А что за книгу вы читали, если не секрет? Не слышал/не помню о такой.
Осмелюсь предположить, что Core Java — Fundamentals.
Да, Core Java, 2 тома. У нас она в переводе правда называется Java 2 Основы 1 том, и 2 том тонкости программирования.
Надо будет ознакомиться. Спасибо. Больше книжек, хороших и разных.
Практическая ценность от таких прыжков весьма сомнительна и нарушает принципы структурного программирования.
А по-моему, ничем не отличается от return из эдакой неявной функции.
Я имел в виду использование break не по делу, то есть как в последнем примере. А по поводу return некоторые теоретики считают, что одна функция — один выход, с чем я, лично, не согласен.
ну ка расскажите подробнее, почему не согласны? Я один из таких теоретиков который в 99% случаев делает один return из метода. Не люблю, когда метод может закончиться в любой момент в зависимости от какого-нибудь условия, что усложняет его понимание. Так с чем не согласны?
Касательно 5-го пункта: ключевое слово finalи как его использовать не является малоизвестный особенностью Java. Если вам действительно хочется защитить массив от изменений, то воспользуйтесь List<Integer> вместо int[] и отдавайте клиенту защищенную оболочку через Collections.unmodifiableList(List).
Поверьте мне, я знаю о способах защиты от изменений, включая и тот, когда на каждую единицу данных расходуется до нескольких десятков байт дополнительно (как пример, коллекции-контейнеры примитивных типов).
Если вы знакомы с языком C++, то должны ощущать разницу между, к примеру, const int * ptr; и int * const ptr;
В Java, к моему сожалению, для примитивов есть только первый способ, а для ссылок — только второй. И, что печально, оба они имеют одинаковое представление: final type variable;
Однако во всё том же C++ есть и третий вариант:
const int * const ptr;.
Было бы не плохо, если бы в Java можно было бы также иметь все три варианта:
final type для неизменяемых ссылок,
const type для неизменяемых значений,
final const type и/или const final type для неизменяемых и ссылок, и значений.
В целях обратной совместимости для примитивных типов final и const могли бы быть синонимами.
Переложить на компилятор контроль за соблюдением константности сущностей — гора с плеч для рядового программиста, особенно если функциональные принципы программирования стоят не на последнем месте.
Об этом я, вероятно невразумительно, пытался объяснить в пятом пункте этой статьи.
а как быть с reflection? тут компилятор уже бессилен.
Reflection не предназначен для рядового программирования. Это чёрный вход, нужный, к примеру, для инспектора объектов в IDE. Ничего с ним не поделаешь, и использовать его не по делу не нужно, только в особых случаях. Учитывая его, прямо сказать, кощунственные накладные расходы.
Да уж прям кощунственные? Почитайте статью Шипилева здесь, на Хабре, о оверхеде рефлекшена.
>> мы можем элегантно инициализировать коллекцию
элегантно? Не сказал бы. Если хочется сахарку — лучше использовать какие-нибудь либы или велосипеды (см тут)
Этот блог прямо обрел дыхание в последнее время.
Ещё из малоизвестных особенностей:
«1,2,3,,».split(",").length() ===> 3
Вы ошиблись. У массива нет метода length(), зато есть поле length.
Откровенно говоря, мне трудно представить, где такое могло бы понадобиться. Ведь вычисления над литералом можно произвести и не в real-time.
Буду знать. Спасибо.
Упс, да, .length
А понадобится это может при парсинге каких-нибудь конфигов (в *nix много подобных ",,"), например передаётся в строке через запятую несколько значений, и некоторые из них могут быть пустые. split(",") не учтёт конечные пустые строки. Надо использовать split(",", -1).
Глупый вопрос — вы готовитесь сдавать OCJCP (или как он там правильно пишется) экзамен? Насколько я помню почти всё это может быть проверено вопросами. Ну и прочитать (хотя бы разик) умные книжки по Java — никогда не помешает.
К собеседованию он готовится. Экзамены, наверное, уже давно сдал )
Отличная статья. Пишите еще больше тонкостей технологий, это освобождает разработчиков от излишней опеки архитекторов которые решают за нас как нам нужно кодить. Как говориться если из явы нельзя отстрелить себе ногу, но уж очень сильно хочется, то можно использовать рикошет пули от стального предмета. Правда целится придется очень точно и не просто, но это нужно для того, что случайно так сделать ни у кого не получилось. Что есть true ;)
Хорошая статья. Про нестатичный блок иннициализации я то ли подзабыл, то ли не знал. Для анонимных классов это единственная возможность проиннициализироваться.
Only those users with full accounts are able to leave comments. Log in, please.