Обратите внимание, что не всегда хорошая идея использовать эти скрытые функции; часто они удивляют и запутывают других, читающих ваш код.
Кевин Бурриллион
1
Вы (/ кто-то) должны, вероятно, аккуратно суммировать ответы в теле вопроса, как вопрос C #.
ripper234
Ответы:
432
Инициализация двойной скобки застала меня врасплох несколько месяцев назад, когда я впервые обнаружил это, никогда не слышал об этом раньше.
ThreadLocals обычно не так широко известны как способ хранения состояния для каждого потока.
Поскольку в Java JDK 1.5 реализованы чрезвычайно надежные и надежные инструменты параллелизма, помимо просто блокировок, они живут в java.util.concurrent, и особенно интересным примером является подпакет java.util.concurrent.atomic, который содержит потокобезопасные примитивы, которые реализуют сравнение -and-swap операция и может отображаться на реальные версии этих операций с аппаратной поддержкой.
Инициализация в двойных скобках ... странно ... Я бы с осторожностью воспринял эту конкретную идиому слишком широко, поскольку она фактически создает анонимный подкласс объекта, что может привести к путанице в задачах equals / hashcode. java.util.concurrent - действительно отличный пакет.
МБ.
6
Я преподавал Java, и это первый раз, когда я сталкиваюсь с этим синтаксисом ... который показывает, что вы никогда не прекращаете учиться = 8-)
Yuval
49
Обратите внимание, что если вы сохраняете ссылку на коллекцию, инициализированную с помощью этой идиомы «двойная скобка» (или если мы называем ее его реальным именем - анонимный класс с блоком инициализатора), вы неявно удерживаете ссылку на внешний объект, который может вызвать неприятную память утечки. Я бы рекомендовал избегать этого вообще.
Ддимитров
51
«Двойная инициализация» - это очень эвфемистическое имя для создания анонимного внутреннего класса, приукрашивания того, что на самом деле происходит, и его звучания, как если бы внутренние классы предназначались для использования таким образом. Это шаблон, который я предпочел бы оставаться скрытым.
Эриксон
11
Практически это не статический блок, а «блок инициализатора», который отличается, поскольку он выполняется в другое время (более подробную информацию см. По ссылке, которую я вставил в ответ)
Борис Терзич,
279
Совместное объединение в дисперсии параметров типа:
publicclassBaz<T extendsFoo&Bar>{}
Например, если вы хотите взять параметр, который является одновременно Comparable и Collection:
publicstatic<A, B extendsCollection<A>&Comparable<B>>boolean foo(B b1, B b2, A a){return(b1.compareTo(b2)==0)|| b1.contains(a)|| b2.contains(a);}
Этот придуманный метод возвращает true, если две заданные коллекции равны или если одна из них содержит данный элемент, в противном случае - false. Следует отметить, что вы можете вызывать методы как Comparable, так и Collection для аргументов b1 и b2.
Мое любимое использование для этого, когда вам нужен метод, который принимает добавляемую последовательность символов.
Нил Коффи
5
Возможно ли иметь «ИЛИ» вместо &?
mainstringargs
9
@Grasper: Нет, OR (непересекающееся объединение) в этом контексте не предусмотрено. Но вместо этого вы можете использовать непересекающийся тип объединения, например Either <A, B>. Этот тип является двойным для типа Pair <A, B>. Посмотрите на функциональную библиотеку Java или базовые библиотеки Scala для примера такого типа данных.
Apocalisp
5
Вы должны сказать, что вы ДОЛЖНЫ расширять только один класс и несколько интерфейсов -> открытый класс Baz <T расширяет Clazz & Interface1 & InterfaceI ... а не класс Baz <T расширяет Clazz1 & ClazzI>
JohnJohnGa
220
Я был удивлен инициализаторами экземпляра на днях. Я удалил некоторые методы, свернутые в коде, и в итоге создал несколько инициализаторов экземпляров:
static initializer called
static initializer2 called
instance initializer called
instance initializer2 called
one's constructor called
instance initializer called
instance initializer2 called
two's constructor called
Я думаю, это было бы полезно, если бы у вас было несколько конструкторов и вам нужен общий код
Они также предоставляют синтаксический сахар для инициализации ваших классов:
Преимущество этого перед явным методом, который должен быть вызван, состоит в том, что если кто-то позже добавляет конструктор, ему не нужно помнить, чтобы вызывать init (); это будет сделано автоматически. Это может предотвратить ошибки будущих программистов.
Мистер Блестящий и Новый 宇 宇
40
Также, в отличие от метода init (), он может инициализировать конечные поля.
Даррон
2
Что если вы расширите класс и создадите экземпляры для разных детей? Будет ли он вести себя так же?
Кеззер
12
Люди часто раздают сертификаты (например, stackoverflow.com/questions/281100/281127#281127 ) и особенно ставят под сомнение их технические достоинства. Но если бы здесь училось больше программистов для своего SCJP, это не было бы для многих «скрытой возможностью». ;-)
Jonik
12
Бьюсь об заклад, даже книга "Ява в течение 24 часов" имеет эту "очевидную особенность". читать дальше, ребята
:)
201
JDK 1.6_07 + содержит приложение под названием VisualVM (bin / jvisualvm.exe), которое представляет собой приятный графический интерфейс поверх многих инструментов. Это кажется более полным, чем JConsole.
И у него есть плагин (это вещь NetBeans), который позволяет ему использовать плагины Jconsole. Довольно мило.
Турбьёрн Равн Андерсен
VisualVM - лучшая вещь из нарезанного хлеба, правда! Жаль, что он не обладает всеми функциями при работе с JDK 1.5
sandos
Я нахожу VisualVM медленным или непригодным в некоторых обстоятельствах. Коммерческий YourKit не имеет этой проблемы, но, к сожалению, не является бесплатным.
Roalt
Более поздние версии Visual VM, начиная с JDK 1.6.0_22 и более поздних, значительно улучшены. Держу пари, что JDK1.7 имеет еще лучшую версию.
Что ж, я бы предпочел иметь возможность сделать это несколькими способами. Например, я видел людей, использующих System.exit (1); в коде сервлетов и EJB, но это не значит, что мы должны удалить System.exit (); от JDK, верно?
Георгий Болюба
31
При некоторых обстоятельствах в рамках конструкции вложенного цикла может быть полезно перейти к следующей итерации внешнего цикла. Это было бы разумным использованием этой функции.
alasdairg
75
Что особенно неизвестно многим программистам (и, вероятно, точно так же), так это то, что вы можете на самом деле помечать и выделять ЛЮБОЙ старый блок. Это не обязательно должен быть цикл - вы можете просто определить какой-то произвольный блок, присвоить ему метку и использовать разрыв с ним.
Нил Коффи
27
Это вообще не goto, оно может вернуться только к предыдущей итерации (т.е. вы не можете прыгнуть вперед). Это тот же механизм, который возникает, когда итерация возвращает false. Говорить о том, что в java есть goto, все равно, что говорить, что любой язык, чей компилятор создает инструкцию JUMP, имеет оператор goto.
Зомби
4
Таким образом, вы проводите собеседование, основываясь на мелочах Java, а не на способности решать проблемы и продумывать дизайн. Я позабочусь, чтобы я никогда не брал интервью у вашей компании. :)
Джавид Джамаэ
144
Как насчет ковариантных типов возвращаемых данных, которые существуют с JDK 1.5? Это довольно плохо публикуется, так как это несексуальное дополнение, но, насколько я понимаю, абсолютно необходимо для работы дженериков.
По сути, компилятор теперь позволяет подклассу сузить тип возвращаемого значения переопределенного метода, чтобы он был подклассом возвращаемого типа исходного метода. Так что это разрешено:
Вы можете вызвать метод подкласса valuesи получить отсортированный поток, безопасный Setдля Strings, без необходимости приведения к типу ConcurrentSkipListSet.
Я использую это много. clone () отличный пример. Он должен возвращать Object, что означает, что вы должны сказать, например, (List) list.clone (). Однако если вы объявите как List clone () {...}, то приведение не требуется.
Джейсон Коэн
142
Передача контроля в блоке finally исключает любые исключения. Следующий код не генерирует RuntimeException - он теряется.
publicstaticvoid doSomething(){try{//Normally you would have code that doesn't explicitly appear //to throw exceptions so it would be harder to see the problem.thrownewRuntimeException();}finally{return;}}
Это неприятно, но это также своего рода логическое следствие того, как, наконец, работает. Управление потоком try / catch / finally делает то, что предназначено, но только в определенных пределах. Точно так же вы должны быть осторожны, чтобы не вызвать исключение внутри блока catch / finally, или вы также выбросите исходное исключение. И если вы выполните System.exit () внутри блока try, блок finally не будет вызван. Если вы нарушаете нормальный поток, вы нарушаете нормальный поток ...
Нил Коффи
Не используйте наконец {return; } но, наконец, {код без возврата}. Это логично, поскольку, наконец, также предполагается выполнение при возникновении исключений, и единственным возможным значением возврата в качестве обработчика исключений должно быть игнорирование исключения и - действительно - возврат.
Extraneon
21
Это больше похоже на «уловку», чем на скрытую функцию, хотя есть способы, которыми ее можно использовать как единое целое, использование этого метода не будет хорошей идеей.
davenpcj
Eclipse выдает предупреждение, если вы делаете это. Я с Затмением. Если вы хотите поймать исключение ... тогда поймайте исключение.
Гелиос
Это то, что вы платите за грязный код, который возвращается из середины метода. Но все равно хороший пример.
Ростислав Матл
141
Никто не упомянул, что instanceof реализован таким образом, что проверка на нулевое значение не требуется.
Действительно потрясающая функция - делает перечисления OO и решает многие проблемы инициализации очень чистым способом.
Билл К
5
Enum как синглтон? Перечислить только одно значение?
Георгий Болюба
6
Георгий: Синглтон - это один экземпляр объекта, а не объект с одним значением.
dshaw
20
@ Георгий: см. Также пункт 3 «Эффективной Явы» Джошуа Блоха (2-е изд); «Хотя этот подход еще не получил широкого распространения, одноэлементный тип enum является лучшим способом реализации синглтона».
Джоник
3
Незначительный придурок: mAgeдолжен быть окончательным. В перечислениях редко встречается причина нефинальных полей.
Иоахим Зауэр
121
Типовые параметры для универсальных методов могут быть указаны явно так:
И, черт возьми, это безобразно и запутанно. И не имеет отношения к типу безопасности.
Крис Бродфут
8
Мне это нравится. Это делает ваш код немного более явным и, как таковой, более понятным для бедняги, которому придется поддерживать его через год или два.
extraneon
6
На самом деле это очень полезно в ситуациях, когда вы объявили статический универсальный метод, такой как public static <T> T foo(T t). Затем вы можете позвонитьClass.<Type>foo(t);
Finbarr
По некоторым причинам это не работает со статически импортированными методами. Интересно, почему.
Оксайт
Это особенно полезно при использовании троичных if с возвратом. Например return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList(). Это также полезно для некоторых вызовов методов, где простой Collections.emptyMap () может привести к ошибке компиляции.
Андреас Холстенсон
112
Вы можете использовать перечисления для реализации интерфейса.
publicinterfaceRoom{publicRoom north();publicRoom south();publicRoom east();publicRoom west();}publicenumRoomsimplementsRoom{
FIRST {publicRoom north(){return SECOND;}},
SECOND {publicRoom south(){return FIRST;}}publicRoom north(){returnnull;}publicRoom south(){returnnull;}publicRoom east(){returnnull;}publicRoom west(){returnnull;}}
Используя интерфейс, разработчики могут определять свои собственные стратегии. Используяenum средства, я могу определить коллекцию (из пяти) встроенных.
@ Ариан, это не безумие. ЭТОТ. ЯВЛЯЕТСЯ. JAVAAAAAAHHHH!
Slezica
1
Черт возьми, я с Адрианом. Это не Java. Это безумие. Я хочу использовать это.
Slezica
104
Начиная с Java 1.5, Java теперь имеет гораздо более чистый синтаксис для написания функций переменной арности. Таким образом, вместо того, чтобы просто передать массив, теперь вы можете сделать следующее
publicvoid foo(String... bars){for(String bar: bars)System.out.println(bar);}
бары автоматически преобразуются в массив указанного типа. Не огромная победа, но, тем не менее, победа.
Также Ctrl- \ в Unix. Или используйте jstack из JDK.
Том Хотин - tackline
9
Спасибо, вы только что научили меня, что у моей клавиатуры есть Breakклавиша.
Эми Б
2
В Windows CTRL-BREAK работает, только если у вас запущен процесс в текущем окне консоли. Вместо этого вы можете использовать JAVA_HOME / bin / jstack.exe. Просто предоставьте его с идентификатором процесса Windows.
Джавид Джамае
Я думал, что это убить -SIGQUIT
Ник Христов
@ Ник, да, SIGQUIT - это обычно сигнал № 3.
Крис Маццола
89
Несколько человек написали об инициализаторах экземпляров, вот хорошее применение для этого:
Каким-то образом, это немного похоже на то, как если бы ключевое слово «с» (фактически, функциональность) было добавлено в Java. Может быть очень удобно, недавно я проворчал, потому что инициализация массивов не была доступна для Коллекций. Спасибо!
PhiLho
15
Есть один побочный эффект от использования этого, хотя. Создаются анонимные объекты, что не всегда хорошо.
Амит
17
Хотя, посмотрев на это больше, я должен сказать, что меня странно привлекает естественное вложение, которое это обеспечивает, даже версия "Abused".
Билл К
4
Да, мне очень нравится «оскорбленная» версия, я думаю, что она действительно очень четкая и читаемая, но, возможно, это только я.
Барриед
3
Абсолютно согласен, иерархия кода, отражающая иерархию графического интерфейса, является огромным улучшением по сравнению с последовательностью вызовов методов.
opsb
88
Динамические прокси (добавлены в 1.3) позволяют вам определять новый тип во время выполнения, который соответствует интерфейсу. Это пригодилось удивительное количество раз.
Динамические прокси - отличная причина, чтобы выбрать написать интерфейс Foo и использовать его везде с классом «FooImpl» по умолчанию. Поначалу это может показаться уродливым («Почему бы просто не иметь класс с именем Foo?»), Но преимущества с точки зрения будущей гибкости и способности к моделированию для юнит-тестов удобны. Хотя есть способы сделать это и для неинтерфейсов, они обычно требуют дополнительных вещей, таких как cblib.
Дариен
82
окончательная инициализация может быть отложена.
Это гарантирует, что даже при сложном потоке логики возвращаемые значения всегда устанавливаются. Слишком легко пропустить случай и вернуть ноль случайно. Это не делает возврат нуля невозможным, просто очевидно, что это специально:
publicObject getElementAt(int index){finalObject element;if(index ==0){
element ="Result 1";}elseif(index ==1){
element ="Result 2";}else{
element ="Result 3";}return element;}
Это удивительно. Можно ли честно сказать: «Значение конечной переменной можно установить один раз», независимо от того, где оно происходит?
Дэвид Коэль
29
Да, но более строго: «Значение окончательной переменной должно быть установлено один раз»
Аллен Лалонд
6
+1 Согласитесь, это еще один ценный инструмент для выявления ошибок во время компиляции, и программисты, похоже, по какой-то причине его стесняются использовать. Обратите внимание, что, начиная с Java 5, «final» также имеет последствия для безопасности потоков, поэтому возможность установки конечной переменной во время конструктора неоценима.
Нил Коффи
4
Хотя для этого конкретного метода я бы просто использовал несколько возвратов. Фактически, в большинстве случаев, когда это применимо, я бы, вероятно, реорганизовал бы его в отдельный метод и использовал бы несколько возвратов.
ripper234
Мне это нравится! Я всегда удаляла последнее ключевое слово, потому что думала, что оно потерпит неудачу. Спасибо!
КАРАЗИ Иштван
62
Я думаю, что еще одна «упущенная из виду» особенность Java - сама JVM. Это, вероятно, лучшая доступная виртуальная машина. И он поддерживает множество интересных и полезных языков (Jython, JRuby, Scala, Groovy). Все эти языки могут легко и без проблем сотрудничать.
Если вы разрабатываете новый язык (как в случае с scala), вы сразу же получаете все имеющиеся библиотеки, и поэтому ваш язык «полезен» с самого начала.
Все эти языки используют оптимизацию HotSpot. ВМ очень хорошо контролирует и отлаживается.
На самом деле это не очень хорошая виртуальная машина. Он был разработан исключительно для запуска JAVA. Типичные динамические и функциональные языки плохо работают с ним. Если вы хотите использовать виртуальную машину, вы должны использовать .NET / Mono. Это было разработано для работы с КАЖДЫМ языком ...
Hades32
14
На самом деле JVM предназначена исключительно для запуска байт-кодов Java. Вы можете компилировать большинство современных языков в байт-код Java. Единственным недостатком Java Bytecode является поддержка динамического языка, указателей и хвостовой рекурсии.
mcjabberz
12
@ Hades32: на самом деле .NET VM очень похожа на JVM. Он только недавно получил поддержку динамических языков (с DLR), и Java 7 также собирается получить эту поддержку. И классический «КАЖДЫЙ язык» .NET (C #, Visual Basic .NET, ...) все имеют практически одинаковый набор функций.
Иоахим Зауэр
13
JVM не поддерживает дженерики, в то время как .NET VM поддерживает. JVM далеко не самый лучший.
Blindy
3
Не стоит сбрасывать со счетов жалобы на специфические языковые функции, которые не поддерживаются непосредственно JVM ... но я склонен думать, что стабильность, кросс-платформенная согласованность и хорошая производительность намного превосходят причины, по которым JVM получает дополнительные баллы. Я уже много лет работаю с серверной Java на многих платформах (включая AS / 400) и смог полностью забыть об этом - ошибки почти всегда есть в коде, который я могу исправить, и это просто не падает
Роб Уилан
58
Вы можете определить анонимный подкласс и напрямую вызвать метод для него, даже если он не реализует интерфейсы.
@Vuntic - он позволяет вам определить простой класс в контексте, в котором он необходим.
ChaosPandion
1
@ Chaos, а почему? Есть реальный пример, где это полезно?
Торбьерн Равн Андерсен
10
@Wouter - В этом случае метод, который вызывается для анонимного объекта ( start()), фактически не определен в подклассе ...
Аксель
На самом деле, это очень полезная функция, если вы расширяете базовый класс, который выполняет некоторую необходимую настройку, вызывает метод, который вы пишете, а затем делаете разбор. Начните с этого, вызвав метод в базовом классе (который я, вероятно, не назвал бы тем же именем). Есть пример использования (не определение) здесь
AmigoNico
56
asList в java.util.Arraysпозволяет получить хорошую комбинацию varargs, универсальных методов и автобокса:
вы хотите обернуть возвращенный список конструктором List, иначе int будет иметь фиксированный размер (так как он поддерживается массивом)
KitsuneYMG
2
Arrays.asListИмеет необычную особенность , что вы можете set()элементы , но не add()или remove(). Поэтому я обычно оборачиваю его в a new ArrayList(...)или в a Collections.unmodifiableList(...), в зависимости от того, хочу ли я изменить список или нет.
Кристиан Семрау
53
Использование этого ключевого слова для доступа к полям / методам, содержащим класс из внутреннего класса. В следующем, довольно надуманном примере мы хотим использовать поле sortAscending класса контейнера из анонимного внутреннего класса. Использование ContainerClass.this.sortAscending вместо this.sortAscending делает свое дело.
Это необходимо, только если вы скрыли имя (в вашем случае, с именем параметра метода). Если бы вы назвали аргумент как-нибудь еще, вы могли бы напрямую получить доступ к переменной члена sortAscending класса Container, не используя 'this'.
ск.
7
Еще полезно иметь ссылку на включающий класс, например. если вам нужно передать его какому-либо методу или разработчику.
PhiLho
Часто используется при разработке макетов Android, чтобы получить контекст, скажем, от слушателя кнопки, с помощью MyActivity.this.
Espinchi
52
Не совсем особенность, но забавный трюк, который я недавно обнаружил на какой-то веб-странице:
является допустимой программой Java (хотя она генерирует предупреждение). Если вы не понимаете почему, посмотрите ответ Грегори! ;-) Ну, подсветка синтаксиса здесь тоже подсказывает!
Это не совсем «скрытые функции» и не очень полезные, но в некоторых случаях может быть чрезвычайно интересным:
класс sun.misc.Unsafe - позволит вам реализовать прямое управление памятью в Java (вы даже можете написать самоизменяющийся код Java с это если сильно постараться)
Скорее всего, ваш оконный менеджер имеет что-то связанное с этим ключом. Gnome не привязывается к нему, поэтому я предполагаю, что вы используете KDE, который связывает его с «переключением на рабочий стол 13». Вы можете изменить его, перейдя в Панель управления, Региональные, Сочетания клавиш и удалив сопоставление для Shift-Ctrl-F1
Devon_C_Miller
40
Каждый файл класса начинается с шестнадцатеричного значения 0xCAFEBABE чтобы идентифицировать его как действительный байт-код JVM.
Я голосую за java.util.concurrent с его параллельными коллекциями и гибкими исполнителями, позволяющими среди прочих пулов потоков, запланированных и скоординированных задач. DelayQueue - мой личный фаворит, где элементы становятся доступными после указанной задержки.
java.util.Timer и TimerTask можно смело положить на отдых.
Кроме того, не совсем скрыто, но в другой упаковке, чем другие классы, связанные с датой и временем. java.util.concurrent.TimeUnit полезен при преобразовании между наносекундами, микросекундами, миллисекундами и секундами.
Он читается намного лучше, чем обычный someValue * 1000 или someValue / 1000.
Проблема с утверждением заключается в том, что он должен быть включен во время выполнения.
Extraneon
10
Но если он отключен, значит, его там нет. Вы можете добавить в код столько утверждений, сколько захотите, и у вас не будет никакого снижения производительности, если они отключены.
Рави Валлау
5
Я считаю, что это хорошая вещь об утверждении: его можно отключить без штрафа.
andref
проблема в том, что если вы случайно внедрили побочный эффект в утверждении, вы должны включить утверждение, чтобы ваша программа работала ...
Chii
Чтобы определить, включены ли подтверждения, вы можете использовать {boolean assertsOn = false; assert assertsOn = true; if (assertsOn) {/ * комплексная проверка * /}}. Это также позволяет регистрировать или выдавать исключение, если состояние assert не ожидается.
Фернаколо
37
Не совсем часть языка Java, но дизассемблер javap, поставляемый с Sun JDK, широко не известен и не используется.
Конструкция for-each также применима к массивам, где она скрывает переменную индекса, а не итератор. Следующий метод возвращает сумму значений в массиве int:
// Returns the sum of the elements of aint sum(int[] a){int result =0;for(int i : a)
result += i;return result;}
Я думаю, что использование iздесь очень запутанно, так как большинство людей ожидают, что я буду индексом, а не элементом массива.
cdmckay
Итак ... int sum (int [] array) {int result = 0; for (int element: array) {result + = element; } вернуть результат; }
Дрю
28
Единственное, что сводит меня с ума - это то, что было бы действительно очень легко создать ключевое слово для доступа к значению счетчика циклов, но вы не можете. Если я хочу зациклить два массива и внести изменения в секунду на основе значений в первом, я вынужден использовать старый синтаксис, поскольку у меня нет смещения во втором массиве.
Джерико
6
Жаль, что он не работает и с перечислениями, как те, что используются в JNDI. Это вернулось к итераторам там.
Extraneon
3
@extraneon: взгляните на Collections.list (перечисление <T> e). Это должно помочь с повторяющимися перечислениями в цикле foreach.
Вернер Леманн
34
лично я обнаружил java.lang.Voidочень поздно - улучшает читаемость кода в сочетании с обобщениями, напримерCallable<Void>
не совсем. в какой-то момент вам нужно быть конкретным: Executors.newSingleThreadExecutor (). submit (new Callable <Void> () {..}) - вы не можете создать новый Callable <?> (), вам нужно указать явный тип - таким образом, это альтернатива Callable <Object>.
Рахель Люти
4
Void более специфичен, чем Object, поскольку Void может быть только нулем, Object может быть чем угодно.
Ответы:
Инициализация двойной скобки застала меня врасплох несколько месяцев назад, когда я впервые обнаружил это, никогда не слышал об этом раньше.
ThreadLocals обычно не так широко известны как способ хранения состояния для каждого потока.
Поскольку в Java JDK 1.5 реализованы чрезвычайно надежные и надежные инструменты параллелизма, помимо просто блокировок, они живут в java.util.concurrent, и особенно интересным примером является подпакет java.util.concurrent.atomic, который содержит потокобезопасные примитивы, которые реализуют сравнение -and-swap операция и может отображаться на реальные версии этих операций с аппаратной поддержкой.
источник
Совместное объединение в дисперсии параметров типа:
Например, если вы хотите взять параметр, который является одновременно Comparable и Collection:
Этот придуманный метод возвращает true, если две заданные коллекции равны или если одна из них содержит данный элемент, в противном случае - false. Следует отметить, что вы можете вызывать методы как Comparable, так и Collection для аргументов b1 и b2.
источник
Я был удивлен инициализаторами экземпляра на днях. Я удалил некоторые методы, свернутые в коде, и в итоге создал несколько инициализаторов экземпляров:
Выполнение
main
метода покажет:Я думаю, это было бы полезно, если бы у вас было несколько конструкторов и вам нужен общий код
Они также предоставляют синтаксический сахар для инициализации ваших классов:
источник
JDK 1.6_07 + содержит приложение под названием VisualVM (bin / jvisualvm.exe), которое представляет собой приятный графический интерфейс поверх многих инструментов. Это кажется более полным, чем JConsole.
источник
Подстановочные знаки Classpath начиная с Java 6.
Вместо того
См. Http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html.
источник
Для большинства людей, у которых я беру интервью на должности разработчиков Java, маркированные блоки очень удивляют. Вот пример:
Кто сказал, что
goto
в Java это просто ключевое слово? :)источник
Как насчет ковариантных типов возвращаемых данных, которые существуют с JDK 1.5? Это довольно плохо публикуется, так как это несексуальное дополнение, но, насколько я понимаю, абсолютно необходимо для работы дженериков.
По сути, компилятор теперь позволяет подклассу сузить тип возвращаемого значения переопределенного метода, чтобы он был подклассом возвращаемого типа исходного метода. Так что это разрешено:
Вы можете вызвать метод подкласса
values
и получить отсортированный поток, безопасныйSet
дляString
s, без необходимости приведения к типуConcurrentSkipListSet
.источник
Передача контроля в блоке finally исключает любые исключения. Следующий код не генерирует RuntimeException - он теряется.
От http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
источник
Никто не упомянул, что instanceof реализован таким образом, что проверка на нулевое значение не требуется.
Вместо того:
просто используйте:
источник
free
загрузкой илиdelete
загрузкой в C / C ++. Такая фундаментальная концепция.Разрешение методов и конструкторов в перечислениях удивило меня. Например:
Вы даже можете иметь «постоянное тело определенного класса», которое позволяет определенному значению перечисления переопределять методы.
Больше документации здесь .
источник
mAge
должен быть окончательным. В перечислениях редко встречается причина нефинальных полей.Типовые параметры для универсальных методов могут быть указаны явно так:
источник
public static <T> T foo(T t)
. Затем вы можете позвонитьClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Это также полезно для некоторых вызовов методов, где простой Collections.emptyMap () может привести к ошибке компиляции.Вы можете использовать перечисления для реализации интерфейса.
РЕДАКТИРОВАТЬ: Годы спустя ....
Я использую эту функцию здесь
https://github.com/peter-lawrey/Java-Thread-Affinity/blob/master/src/main/java/vanilla/java/affinity/AffinityStrategies.java
Используя интерфейс, разработчики могут определять свои собственные стратегии. Используя
enum
средства, я могу определить коллекцию (из пяти) встроенных.источник
Начиная с Java 1.5, Java теперь имеет гораздо более чистый синтаксис для написания функций переменной арности. Таким образом, вместо того, чтобы просто передать массив, теперь вы можете сделать следующее
бары автоматически преобразуются в массив указанного типа. Не огромная победа, но, тем не менее, победа.
источник
Мое любимое: сбросить все трассировки стека потоков в стандартный вывод.
Windows: CTRL- Breakв вашем окне Java CMD / консоли
UNIX:
kill -3 PID
источник
Break
клавиша.Несколько человек написали об инициализаторах экземпляров, вот хорошее применение для этого:
Это быстрый способ инициализации карт, если вы просто делаете что-то быстрое и простое.
Или используя его для создания прототипа рамы быстрого качания:
Конечно, этим можно злоупотреблять:
источник
Динамические прокси (добавлены в 1.3) позволяют вам определять новый тип во время выполнения, который соответствует интерфейсу. Это пригодилось удивительное количество раз.
источник
окончательная инициализация может быть отложена.
Это гарантирует, что даже при сложном потоке логики возвращаемые значения всегда устанавливаются. Слишком легко пропустить случай и вернуть ноль случайно. Это не делает возврат нуля невозможным, просто очевидно, что это специально:
источник
Я думаю, что еще одна «упущенная из виду» особенность Java - сама JVM. Это, вероятно, лучшая доступная виртуальная машина. И он поддерживает множество интересных и полезных языков (Jython, JRuby, Scala, Groovy). Все эти языки могут легко и без проблем сотрудничать.
Если вы разрабатываете новый язык (как в случае с scala), вы сразу же получаете все имеющиеся библиотеки, и поэтому ваш язык «полезен» с самого начала.
Все эти языки используют оптимизацию HotSpot. ВМ очень хорошо контролирует и отлаживается.
источник
Вы можете определить анонимный подкласс и напрямую вызвать метод для него, даже если он не реализует интерфейсы.
источник
start()
), фактически не определен в подклассе ...asList в
java.util.Arrays
позволяет получить хорошую комбинацию varargs, универсальных методов и автобокса:источник
Arrays.asList
Имеет необычную особенность , что вы можетеset()
элементы , но неadd()
илиremove()
. Поэтому я обычно оборачиваю его в anew ArrayList(...)
или в aCollections.unmodifiableList(...)
, в зависимости от того, хочу ли я изменить список или нет.Использование этого ключевого слова для доступа к полям / методам, содержащим класс из внутреннего класса. В следующем, довольно надуманном примере мы хотим использовать поле sortAscending класса контейнера из анонимного внутреннего класса. Использование ContainerClass.this.sortAscending вместо this.sortAscending делает свое дело.
источник
MyActivity.this
.Не совсем особенность, но забавный трюк, который я недавно обнаружил на какой-то веб-странице:
является допустимой программой Java (хотя она генерирует предупреждение). Если вы не понимаете почему, посмотрите ответ Грегори! ;-) Ну, подсветка синтаксиса здесь тоже подсказывает!
источник
Это не совсем «скрытые функции» и не очень полезные, но в некоторых случаях может быть чрезвычайно интересным:
класс sun.misc.Unsafe - позволит вам реализовать прямое управление памятью в Java (вы даже можете написать самоизменяющийся код Java с это если сильно постараться)
источник
При работе в Swing мне нравится скрытый Ctrl- Shift-F1 функция.
Он сбрасывает дерево компонентов текущего окна.
(Предполагая, что вы не связали это нажатие клавиши с чем-то другим.)
источник
Каждый файл класса начинается с шестнадцатеричного значения 0xCAFEBABE чтобы идентифицировать его как действительный байт-код JVM.
( Объяснение )
источник
Я голосую за java.util.concurrent с его параллельными коллекциями и гибкими исполнителями, позволяющими среди прочих пулов потоков, запланированных и скоординированных задач. DelayQueue - мой личный фаворит, где элементы становятся доступными после указанной задержки.
java.util.Timer и TimerTask можно смело положить на отдых.
Кроме того, не совсем скрыто, но в другой упаковке, чем другие классы, связанные с датой и временем. java.util.concurrent.TimeUnit полезен при преобразовании между наносекундами, микросекундами, миллисекундами и секундами.
Он читается намного лучше, чем обычный someValue * 1000 или someValue / 1000.
источник
CountDownLatch
иCyclicBarrier
- так полезен!Ключевое слово assert на уровне языка .
источник
Не совсем часть языка Java, но дизассемблер javap, поставляемый с Sun JDK, широко не известен и не используется.
источник
Добавление конструкции для каждого цикла в 1.5. Я <3 это.
И может использоваться во вложенных экземплярах:
Конструкция for-each также применима к массивам, где она скрывает переменную индекса, а не итератор. Следующий метод возвращает сумму значений в массиве int:
Ссылка на документацию Sun
источник
i
здесь очень запутанно, так как большинство людей ожидают, что я буду индексом, а не элементом массива.лично я обнаружил
java.lang.Void
очень поздно - улучшает читаемость кода в сочетании с обобщениями, напримерCallable<Void>
источник