Хитрые задачи по Java

    Совсем недавно я сдал OCA Java SE 7 Programmer I. За время подготовки успел решить огромное количество задач и извлечь из них много тонких моментов языка. Самые интересные и ловкие — сохранял на будущее. И вот у меня накопилась небольшая личная коллекция, лучшую часть которой я здесь и опишу.

    В замечательной статье Знаешь ли ты JAVA, %username% и её второй части автор тоже поделился опытом после подготовки. Однако я пришёл к выводу, что могу добавить что-то своё. Так и зародилась эта статья.


    Задачи

    Итак, начнём. Я разбил все хитрости на маленькие задачки, которые составил специально для вас. Тонкости языка выделяются в чистом виде — без лишних наворотов и заблуждений, как это было в тестах. Также я рекомендую вам сначала ответить на вопрос с точностью до символа и записать куда-нибудь, а потом уже смотреть правильный ответ. Интересно, сколько пользователей, решивших этот тест, ответит больше чем на половину? И не забывайте, что все эти примеры ориентированы на Java 7.

    1)Скомпилируется ли данный код и если да — то каким будет вывод?
    long year = 201l;
    System.out.print(year);  
    
    Ответ
    201
    Пояснение
    Я специально выключил подсветку — чтобы не было заметно подвоха. Иначе последняя буква визуально выделялась бы — а в ней вся соль вопроса.

    В английском языке строчная буква l очень похожа на цифру 1. И этим примером я хочу вас предостеречь — никогда не используйте l маленькую для обозначения long-литералов, хотя Java это позволяет. И вообще не используете её там, где потенциально может быть единица. Просто возьмите за правило использовать прописную L, как это и делает большинство программистов.

    Если посмотреть внимательно, то можно заметить, что единицы визуально чуточку отличаются. Совсем капельку. Но мы же с вами хотим продумать всё до мелочей, не так ли?

    Вывод будет — 201, а не 2011, как может показаться на первый взгляд.

    2)Скомпилируется ли данный код и если да — то каким будет вывод?
    int[][] array = {{1, 2, 3}, {0, 0, 0,},};       
    System.out.println(Arrays.deepToString(array)); 
    Ответ
    [[1, 2, 3], [0, 0, 0]]
    Пояснение
    Заблуждение обычно вызывают две «лишних» запятых в конце.

    Когда я первый раз увидел такой код в одном из тестов, я твёрдо решил, что код не скомпилируется — и оказался не прав. Некоторые из вас могут предположить, что не указанные элементы будут заполнены значением по-умолчанию — и это будет тоже неверно.

    А вывод будет простой — [[1, 2, 3], [0, 0, 0]]. Получается, что компилятор просто игнорирует одну лишнюю запятую в конце массива. Причём именно одну — две подряд уже вызовут ошибку компиляции.

    Описание этой ситуации я без проблем нашёл в спецификации языкаA trailing comma may appear after the last expression in an array initializer and is ignored.

    А на практике — сделано для удобства при ручном копировании из одного массива в другой. Если бы компилятор не позволял ставить лишнюю запятую — то в некоторых случаях приходилось бы добавлять запятую в конце, когда мы копируем и вставляем значения из одного массива в конец другого — или удалять лишнюю в конце.

    3)Скомпилируется ли данный код и если да — то каким будет вывод?
    double $ = 0XD_EP2F;
    System.out.print($);
    Ответ
    888.0
    Пояснение
    Вы наверно будете уверены в том, что этот код не скомпилируется. А вот и нет! он вполне рабочий.

    Когда я изучал Java, я сразу взял на заметку, что из подчёркиваний и экспоненциальной формы для HEX можно сделать что-то дикое. Этот пример, конечно же, не для использования в реальных проектах — а для тренировки ваших знаний. Я думаю, это самый сложный пример и изюминка статьи. Первые два были лёгкой разминкой. Кто-нибудь ответил правильно с первого раза?

    В этом примере заключены два интересных момента. Первое — это название переменной. Называть переменную долларом весьма забавно. Но никогда, никогда так не делайте в реальных проектах. Хотя компилятор не запрещает такой подход — он не рекомендован, так как доллар используется в технических целях. Например, для наименования анонимных и вложенных классов. MyClass$MyInnerClass, или же MyClass$1. И можно без труда устроить коллапс имён — один класс назвать просто MyClass$MyInnerClass, а другой — MyClass с вложенным MyInnerClass — и они будут иметь одинаковое имя. Так что включать в свои переменные доллар — не рекомендуется.

    Также вполне корректен такой код
    double  _ = 8.0;

    А теперь давайте разберём второй момент — непосредственно сам литерал. Я наворотил его, как только мог. Для начала легко заметить, что это число записано в шестнадцатеричной форме. Но ведь она допускает только A,B,C,D,E,F в качестве букв — кажете вы. Откуда тогда P? И причём тут знак подчёркивания?

    Обо всём по-порядку. F в конце означает, что этот литерал — типа float. И у нас он автоматически приводится к типу double. Далее очень интересный момент — P2. Если мы хотим записать шестнадцатеричное число в экспоненциальной форме — мы не сможем использовать E+N, потому что E у нас может использоваться в самом числе и может возникнуть неоднозначность. Зато никто не мешает нам использовать BinaryExponentIndicator — указываем p и степень. Число будет умножено на 2 в указанной степени. В данном случае — на 4.

    А вот символ подчёркивания — очень удобное нововведение Java 7. Мы просто можем вставлять его в число и разделять им, например, разряды, или группировать цифры. Компилятор его просто вырежет — он нужен для более удобного чтения, не более.

    Итак, чтобы точно ответить на вопрос, нам нужно вспомнить, что System.out.print выводит переменную типа double в обычной, десятичной форме. Следственно, нам нужно перевести из шестнадцатеричного вида в десятичный. Это уже совсем тривиальная задача. DE16 = 22210. Далее, умножаем 222 на 22 и получаем 888. Наконец не забываем, что для типа double при отсутствии дробной части дописывается точка и ноль. Вот и ответ — 888.0.

    4)Скомпилируется ли данный код и если да — то каким будет вывод?
    public class Main{;
        public static void main(String[] args) {
            System.out.println(new Main().$_$()[2]);
        }
    
        ;short $_$()[] {{{
            return new short[007];
        }}};
    };
    
    Ответ
    0
    Пояснение
    Первое, что бросается в глаза — это использование точек с запятой там, где их можно не использовать. Например после объявления класса (как в С++). Или же между членами класса. Зачем компилятор дал возможность ставить их там — я так и не выяснил. Но это вполне допустимо.

    Имя метода — вполне допустимый идентификатор. А вот возвращаемый тип здесь не short а массив из short. Компилятор разрешает 2 формы объявления массива — квадратные скобки до идентификатора и после. Причём первый случай предназначен как-раз для метода. А что если попробовать второй случай для метода? Он тоже корректен, но выглядит ужасно, поэтому никогда не используйте его в реальных проектах. Но такая возможность есть.

    Далее — внутри метода просто два вложенных блока кода, которые можно безболезненно убрать. И в итоге — метод просто возвращает массив из short длинной в 7 элементов, который инициализируется нулями и элемент с индексом 2 равен 0. Ах да, 007 — это восьмеричный литерал. Но это тоже ни на что не влияет.

    5)Скомпилируется ли данный код и если да — то каким будет вывод?
    public class Main {
        public static void main(String[] args) {
            ((Main) null).haбra();
        }
    
        static void haбra() {
            System.out.println("Hello habrahabr!");
        }
    }
    Ответ
    Hello habrahabr!
    Пояснение
    Внимательные читатели заметят, что в названии метода присутствует русская буква б. Мало того, что Java позволяет полностью писать название идентификаторов на языках, отличных от английского, так мы ещё можем перемешивать буквы из разных языков.

    Важный момент, который я хотел донести до вас — можно случайно напечатать не тот символ из другого языка и потом долго и мучительно искать ошибку. Например, английская a и русская а визуально неотличимы (по крайней мере, в этом шрифте). Если единицу можно отличить от l хоть как-то, то тут всё значительно хуже. Представьте себе ситуацию — вы по каким-либо причинам случайно в конце в названии класса или метода набрали русскую букву вместо английской. Или что более вероятно — редактировали уже существующее латинское название с русской раскладкой. Похожих букв между этими языками довольно много, так что шанс ошибиться вполне есть. Автозаполнение будет вставлять интернациональный идентификатор и всё будет отлично работать. Но вот если вы попробуете вызвать метод или получить класс через рефлексию — получите ошибку, которую будет не так просто обнаружить. Скорее, вы будете искать её в другом, так как названия будут визуально совпадать — потеряете время и силы.

    Я хотел добавить ещё один пример, в котором два на внешний вид одинаковых идентификатора будут содержать внешне идентичные буквы из разных алфавитов, но по коду разные и посему идентификаторы будут также разные. И заставить объяснить, почему код вызывает ошибку компиляции. Но это было бы слишком жестоко — на вид подвох никак не заметить.

    Далее — мы вызываем статический метод довольно оригинально — приводим null к типу Main. И это не вызовет ошибки времени выполнения! Дело в том, что вызов статических методов разрешается на этапе компиляции и зависит только от типа объекта.

    В комментариях к данной статье пользователь Yurevich1 привёл пример из реального проекта:
    Как-то в проекте поставил в классе переменную «с» по-русски. Где-то час убил, чтобы понять, в чём ошибка и проект в другой части кода ругается на как бы ту же самую переменную c, которая уже на английском.


    6)Скомпилируется ли данный код и если да — то каким будет вывод?
    Byte[] Byte[] = {{0}};
    System.out.println(Byte);
    System.out.println(Byte.class);
    System.out.println(Byte.length);
    System.out.println(new Byte("8"));
    Ответ
    [[Ljava.lang.Byte;@6f171e30 (хэш может быть другим)
    class java.lang.Byte
    1
    8
    Пояснение
    Итак, вот вам ещё один пример кода, который на первый взгляд вводит в заблуждение. Для начала вас должно смутить казалось бы следующее два раза друг за другом объявление массива из оболочек для байтов. Однако если вы внимательно изучали язык, вы должны знать, что есть два способа объявления массива — с квадратными скобками до имени и после. Более того, никто не мешает нам использовать эти два способа одновременно — перед вами просто двумерный массив.

    Далее вас должно смутить имя массива, которое полностью совпадает с именем класса. Java позволяет называть локальные переменные классами стандартной библиотеки, при этом они будут перекрывать классы. Однако компилятор у Джавы умный. Очень умный. Он сообразит, что после оператора new может следовать только класс, да и перед .class — тоже. И в том контексте будет подразумеваться именно класс Byte, хотя имя экземпляра должно его перекрывать.


    Итоги

    Мне нравится Java за её жёсткую стандартизованность. Спецификация определяет практически все тонкости с очень большой точностью. А значит — изучив эти тонкости один раз — вы сможете работать с ними везде.

    Хочу добавить, что скрин кода над катом взят из IDEA. Схему подсветки я сам разработал и использую её преимущества по максимуму. Если кому понравилась — могу скинуть.

    Я готовился по нескольким разным системам тестирования. Для начала, хорошим сайтом будет Quizful. Тесты «Java-Основы» и «Java-средний уровень» содержат очень большое количество полезных задач. Далее — очень хороши тесты от ExamLab — гонял по ним SCJP 6. И наконец — для самого экзамена — Enthuware.

    После прохождения многочисленных тестов и решения задач «в уме» я стал приятно удивлён, каким комфортным и эффективным стало написание кода. Тесты очень хорошо систематизируют и организуют знания. Я стал предвидеть в уме многие ошибки, а также выбирать лучшие решения. И не пожалел, что выучил некоторую часть API, хотя сначала считал что не следует помнить названия методов и классов наизусть. Я считаю Java одним из лучших языков в мире и рекомендую тесты для его углублённого изучения. А Java SE 7 Programmer I был совсем не сложным — без труда набрал 96 из 100 баллов. Кто собирается сдавать — могу дать пару советов — напишите в личку.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 81

      +17
      > никогда не используйте
      > никогда так не делайте в реальных проектах


      Извините, может быть я чего не понимаю, но в чем тогда смысл таких задач? Проверить знание всевозможных извратов, возможных в языке?
        +1
        Да, экзамены не нацелены на проверку знаний чего-то удобного и крутого (отчасти), что можно использовать в проектах, а только если что нового разработчики скрыли в недрах Java и как не напороться на грабли по большей части.
          +4
          Чтобы знать все тонкости языка/компилятора и понимать, почему та или иная вещь сделана именно так.

          Лично я с удовольствием перетяну в свой c++ код правило обозначать тип большого целого числа только большой буквой L. Хотя, казалось бы, каким боком c++ к java.
            +8
            Я готовлюсь сейчас к этому экзамену и меня это тоже просто вымораживает. Несмотря на то что я могу программировать на яве вполне нормально, я не могу выбить больше 60% из тестовых заданий ну никак — потому что 50% задач которые приходится решать первым делом вызывают вопрос «какой идиот это писал?». И все чем я занимаюсь готовясь — учу в основном фокусы и тонкости которые никто никогда не будет использовать, и ловко отличать фишку которая скомпилируется явой от той которая не скомпилируется явой. Плюс составители обожают писать код для заданий наплевав на все правила программирования, например назвав вперемешку классы, интерфейсы и методы A/B/C и D и слепив из них жуткое месиво наследований, имплементаций и выводов и задва гениальный вопрос «что выведет данный код?» не забыв добавить вариант ответа «не скомпилируется».
            Короче это жуткий экзамен на фантастическую въедливость во все тонкости языка и внимательность.
              +2
              Смысл в том чтоб кто-то заплатил Ораклу за сертификацию, и даже если этот кто-то серьезно программирует ему должно быть трудно пройти тест, чтоб не было ощущения дешевки.
                0
                Мне в свое время было просто интерестно оценить уровень своих знания на всевозможных тестах. Поробовал симуляции тестов на exambraindumps.com/ просто ради удовольствия. Когда делать нечего, то мозги очень хорошо разминаются. Как бонус можно оценить сможешь ли здать реальный сертификационный экзамен.
                +2
                Некоторые вопросы предостерегают вас от ошибок, о которых я написал в пояснениях. И вообще в исходниках чужих всякое встречается. ИМХО — надо глубоко знать язык, особенно если у него есть жёсткая спецификация.
                  +11
                  На все эти вопросы IDE отвечает куда быстрее и точнее человека. К чему эти ненужные на практике знания? Вы пишете компилятор Java? Ни в одном вменяемом проекте не будет ни $_$()[] ни 0XD_EP2F.

                  PS сам знаю ответы почти на все вопросы и сдавал экзамен на тогда ещё SCJP. Тем скептичнее отношусь к сертификату. Благо я не практически не готовился к его сдаче, отвечал что знаю. Ненужная, ничего не показывающая бумажка. Возможно другие сертификаты ближе к жизни, этот меня разочаровал и желания сдавать дальше не вызвал.
                    +3
                    Разделяю ваше мнение по поводу сертификации. Они полезны только в тех компаниях, куда нормальные разработчики ни за какие деньги не сунутся, имхо :)

                    Есть у нас в универе один препод с over9000 сертификатами от Microsoft и т.д., но стоит его спросить о чем то реальном, так он так плавать начинает, что аж самому неловко становится от того что спросил это :)
                      +1
                      У меня достаточно знакомых, которые работают на хороших должностях в крупных компаниях и они все утверждают, что сертификаты дают значительный бонус при устройстве на работу. Хотя да, есть процент работодателей, которых не волнуют сертификаты, но он не велик. Возможно, вам просто не повезло =)
                        +3
                        Всё почти как с институтским дипломом блин.
                          0
                          Не подскажете, что за «значительный бонус» такой мифический?
                            +1
                            Например, в случае двух людей на одно место скорее берут того человека, у которого есть сертификат. Кроме того, в некоторых компаниях на более высокие должности берут только при получении соответствующего сертификата — и повышают зарплату также. Речь идёт о крупных компаниях.

                            «Без бумажки ты букашка, а с бумажкой — человек!» (с) советский поэт
                              +1
                              Это какой-то очень синтетический случай. Если на собеседование пришел человек, которого ты готов взять на работу (независимо от того что за сертификаты у него, есть ли во, служил, сидел и тд) это уже повод плясать джигу, но чтобы сразу двое — ну, так просто не бывает.
                                +1
                                Смотря в каких компаниях
                                  0
                                  Я вот, кстати, такого же мнения — нормальных специалистов днем с огнем не сыщешь, когда такой появляется — это праздник просто. И все это знают — и наниматели, и сами специалисты. И зачем этому специалисту тратить время и силы и деньги на прохождение сертификации, которая к его опыту ничего не добавит, и на которую никто все равно не смотрит? Вот и получается ситуация, что человек с сертификатами уже скорее подозрение вызывает :)
                              +3
                              Сертификаты волнуют работодателей из-за проведения тендеров (нужно N-сертифицированных специалистов). Да это нравится HR-ам, но сомневаюсь что сертификаты произведут впечатление на людей которые проводят техническое интервью.
                                0
                                Удивлен этим — за 11 лет карьеры не помню ни одного раза, чтобы сертификат по яве зачитывался хоть сколь-либо существенно сам по себе. Может, озвучите названия крупных компаний? Любопытно просто, что это за компания, которая, скажем, разработчику с опытом даст/не даст бонус только на основании сертификата.
                                  0
                                  Oracle
                                    0
                                    Странно, мне там про это не упоминали. Ну да ладно, главное, чтобы все были счастливы :)
                                      0
                                      Вот я теперь не знаю, кому верить =)

                                      Но я не пожалел что сдал его, потом планирую ещё и OCP сдать. Пускай для портфолио будут. Вообще это больше как личный мотиватор к качественному изучению курса по Java. Причём к широкому изучению. Например, я не пожалел что изучил Formatter и регулярные выражения (готовился-то к SCJP 6). Потом нашёл им применение, а раньше о них даже не знал.
                                      0
                                      ой, так ли? ;)
                                0
                                Великолепная описка в итогах:

                                Мне нравится Java за её жёсткую стандартизованность. Спецификация определяет практически все тонкости с очень большой тонкостью. А значит — изучив эти тонкости один раз — вы сможете работать с ними везде.


                                Хехе :)

                                А на самом деле, я даже рад, что не во всех вопросах правильно ответил
                                  0
                                  Исправил
                                    +2
                                    Ну если все тонкости спецификации всегда помнить, то и JavaScript недоумения не вызывает. Это можно про любой язык сказать.
                                    0
                                    Опять это дрочерство. Лучше JavaEE учите, полезнее будет.
                                      +12
                                      Да, должен же кто то джава бины клепать для говноформочек к базам данных.
                                        0
                                        можно подумать на JavaEE только джава бины к говнофомочкам делают… вы, судя по всему, совсем не знаете JavaEE
                                          0
                                          orly?
                                          я работал в дойче банке и других компаниях такого уровня и прекрасно представляю себе, какие проекты делаются на java SE и какие на java EE. EE используется для нетребовательных проектов как раз уровня говноформочек к БД, потому что это промышленный подход, не требующий особого знания кишок машины, системы и окружающей среды. И вот те самые клепатели этих CRM и прочего считают себя реальными хардкор прогерами и удивляются, зачем же надо знать про кишки JVM и особенности компиляции. Вам не надо, расслабьтесь.
                                            0
                                            Ну так зачем знать чо там как в JVM, если тебе что-то нужно, а для этого не существует аннотации — значит этого не существует в принципе.
                                              0
                                              Надеюсь сарказм?
                                                0
                                                Судя по некоторым, их тех, кого приходилось собеседовать или с кем пришлось поработать, сарказма тут маловато.
                                              0
                                              Это вам просто так везло. Мне приходилось делать красивые и удобные биллинговые системы под веб и заниматься оптимизацией крупных кластерных приложений. Всё на Java. Поэтому я не согласен с вашим обобщением. Хотя это может просто мне так повезло с работой.
                                              Не хочу теперь в дойче банк :)
                                        +1
                                        По поводу букв. F допускается в шестнадцатеричной форме: это 15.
                                          0
                                          Исправил
                                          +1
                                          Интересно, сколько пользователей, решивших этот тест, ответит больше чем на половину?

                                          Я неправильно ответил только на 3-й вопрос. Меня сбило с толку нижнее подчеркивание. Хотя, если бы меня попросили пояснить, то я бы пояснил не все. То есть, местами угадал просто. Спасибо, узнал кое-что новое.
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                              0
                                              а если убавить шрифт? :)
                                                0
                                                Наоборот, прибавлять нужно — тогда появится различие. Разумеется, на исходном тексте, а не на пиксельной картинке.
                                                Хотя убавить тоже можно, разница будет в нижней засечке.
                                                +1
                                                Для того и пишут заглавную l. Вроде бы, нетбинс и идея на такое даже ругаются.
                                                  –3
                                                  Я не очень понял насчёт заглавной L (пока что не прорешал задачи, надо сделать это обстоятельно, а не наспех), но если имеется в виду Long вместо long, то это совершенно не одно и то же, и так без нужды делать не стоит. Первое — объект, а второе — примитивный тип. В вычислениях объект придётся превращать в примитивный тип, и это вызовет ненужные проблемы с эффективностью кода. А если результат нужно будет записать обратно в переменную, то ещё и создастся новый объект в процессе автоупаковки.
                                                    +2
                                                    Речь об L в константе: 201L

                                                    BTW Следуя привычкам я бы определил константу в теле класса, убив интригу и неоднозначность восприятия:
                                                    public static final long YEAR_201 = 201L;
                                                    
                                                      +1
                                                      Значит, я даже с масштабом не там единичку разглядел. Ещё удивился насчёт типов.

                                                      Константа тут, мне кажется, не очень поможет. Если прописать в названии число, то тогда потом, когда оно поменяется, придётся её переименовывать, что не очень хорошо. А если не прописать, то тогда и разницы между константой и переменной особенно нет. Неоднозначность тут убирает именно заглавная L. Я сам обычно в литералах чисел строчные вообще не пишу, чтобы такая проблема не возникала.
                                                      0
                                                      Не зависимо от того, находится буква L в нижнем регистре или верхнем, в конце целочисленного литерала она всегда означает примитивный тип long.

                                                      Для случая Long year = 201L; автоупаковка будет также произведена.
                                                        +1
                                                        Да единицу я не там просто разглядел. Рано утром смотрел, показалось, что в начале long единица, а в конце литерала L, а там на самом деле наоброт.

                                                        Что касается автоупаковки, я имел в виду случай вроде этого (случай, разумеется, надуманный, чтобы было нагляднее):

                                                        Long year = 201L;
                                                        for (int offset = 0; offset < 100; offset++) {
                                                            year += offset;
                                                        }
                                                        

                                                        В первой строчке запакуется только один раз, что ни на что особенно не повлияет, но потом каждый раз будет распаковываться, когда нужно что-то сделать со значением.
                                                          +1
                                                          Пардон, хотел написать «а в конце литерала всё как надо», не успел отредактировать.
                                                    +1
                                                    хром на маке

                                                    eclipse

                                                    хром на андроиде

                                                    ЧЯДНТ?
                                                      +4
                                                      Перечень моноширинных шрифтов не заканчиваются на monaco и droid mono. И я бы сказал что шрифты и должны быть такими, в которых нельзя спутать 0/O, 1/l
                                                        0
                                                        Именно поэтому я предпочитаю anonymous pro на linux. Без нормального шрифта можно выстрелить в ногу. Особенно в языках с динамической типизацией.
                                                          +2
                                                          Anonymous Pro на маке:


                                                          Настоятельно рекомендую.
                                                          0
                                                          И я бы сказал что шрифты и должны быть такими, в которых нельзя спутать 0/O, 1/l

                                                          Угу, стандартная настроечная таблица шрифтов для программирования: O01Il|
                                                      +3
                                                      Спецификация определяет практически все тонкости с очень большой точностью. А значит — изучив эти тонкости один раз — вы сможете работать с ними везде.

                                                      Эх, если бы так просто было — «один раз», «одну спецификацию» и навсегда для всех проектов — не получится! :-)
                                                      В Java есть куча спецификаций, которые в совокупности определяют «хитрости» гораздо более высокого порядка.
                                                      Надо помнить, что Java это не только язык.

                                                      Попробую показать это на задачке из жизни:
                                                      Надо «на лету» создать класс с конструктором, который в своем теле на основании значения параметра вызывает конкретный конструктор суперкласса.
                                                      На языке Java конструктор такого класса выглядел бы как-нибудь вот так:

                                                          public A(int ctorNo, Object param) {
                                                              switch(ctorNo) {
                                                                  case 1:
                                                                      super(param);
                                                                  default:
                                                                      super();
                                                              }
                                                          }
                                                      
                                                      


                                                      Если только изучить The Java® Language Specification, то правильный ответ будет:
                                                      Это невозможно! — call to super must be first statement in constructor.

                                                      Но, The Java® Virtual Machine Specification (Second Edition) позволяет такое!
                                                      То есть задача решается в среде Java, если не использовать язык Java :-)

                                                      Да, задачи очень разные бывают. Эта задача была весьма специфическая. И для этой задачи хитрое до ненормальности решение (но не противоречащее нужным спецификациям!) было наиболее оптимальным.

                                                      Но, это факт, что большинство задач являются типовыми. И правильно для их решения использовать хорошо известные и проверенные шаблонные решения. Это так же относится и к стилю написания исходного кода. Если писать код следуя принятому «шаблонному» стилю, то его поддержка будет стоить намного дешевле.

                                                      IMHO большинство языковых «хитростей», которые содержит этот пост, я бы просто отнес к плохому стилю написания исходного кода. Изучать Java надо на положительных примерах и «набивать руку» согласно Code Conventions for the Java Programming Language.

                                                        0
                                                        число записано в шестнадцатеричной форме. Но ведь она допускает только A,B,C,D,E в качестве букв — кажете вы. Откуда тогда P и F?

                                                        Сижу вчитываюсь… С каких пор «F» — не часть 16тиричного числа? Я что-то не так понял?
                                                          0
                                                          Опечаточка, исправил
                                                            0
                                                            А как, кстати, записать DE * 22F? Если нужен тип float?
                                                          +3
                                                          Интересно конечно, только это к программированию не имеет никакого отношения, как собственно и к знанию JAVA.
                                                            +6
                                                            Приведу пример, сделанный на базе одного известного реального проекта:
                                                            class Base {
                                                              public static Base[] CHILDREN = { Child.NAME };
                                                            }
                                                            
                                                            class Child extends Base {
                                                              public static String NAME = "child";
                                                            }
                                                            


                                                            Что выведет такой вариант?
                                                            System.out.println(Base.CHILDREN[0]);
                                                            System.out.println(Child.NAME);
                                                            


                                                            А такой?
                                                            System.out.println(Child.NAME);
                                                            System.out.println(Base.CHILDREN[0]);
                                                            


                                                            результат
                                                            Первый:
                                                            child
                                                            child


                                                            Второй:
                                                            child
                                                            null


                                                            Всё дело в порядке инициализации. В JLS есть следующая строчка:
                                                            Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class are not initialized.
                                                            Если первым обращаются к Base.CHILDREN, то это требует загрузки, верификации, подготовки и инициализации Base, в процессе которой происходит обращение к Child.NAME (при выполнении статического инициализации поля CHILDREN).

                                                            Это приводит к загрузке, верификации, подготовке (при которой создаются static-поля и в них записываются значения по умолчанию) и инициализации класса Child.

                                                            Инициализация класса Child требует инициализации суперкласса (Base). Разрешение таких циклических зависимостей описано в JLS. Не касаясь синхронизации (для случая инициализации классов из разных потоков), произойдет следующее: JVM проверит состояние инициализации класса Base и, узнав что он инициализируется этим же потоком, продолжит процедуру инициализации класса Child. Это приведет к тому, что в static-поле NAME будет записана ссылка на соответствующую строку "child".

                                                            После этого инициализация класса Base продолжится и в массив CHILDREN будет записано значение инициализированного поля Child.NAME.

                                                            Напротив, при обратном порядке инициализации (сначала Child, потом Base), произойдет следующее: после загрузки, верификации и подготовки класса Child его статической поле NAME будет создано и заполнено значением по умолчанию (для ссылочных полей — null). После чего JVM начнет инициализацию суперкласса Base.

                                                            При инициализации суперкласса Base (загрузка, верификация и подготовка аналогичны) произойдет обращение к static-полю Child.NAME, что потребует инициализации Child, при попытке которой JVM выяснит, что класс находится в процессе инициализации этим же потоком и прекратит попытку. Из поля NAME будет считано текущее значение null.

                                                            Избежать этого можно проставив static-полю NAME модификатор final, тогда оно инициализируется раньше, чем будет предпринята попытка инициализировать суперкласс. Подробна эта процедура рассмотрена в 12 главе JLS. Правда, этот метод сработает только, если поле NAME инициализируется compile-time константой.

                                                            Вот такие пироги с котятами.

                                                            Кому интересно — issues.apache.org/jira/browse/SOLR-5526.
                                                              0
                                                              Хороший пример. Порядок инициализации классов нужно знать.
                                                              +8
                                                              Пожалуй добавлю Вам в копилку примеров «неправильного» кода на Java…
                                                              > никогда не используйте
                                                              > никогда так не делайте в реальных проектах несвязанных с Brainfuck

                                                              7) Скомпилируется ли данный код и если да — то каким будет вывод?

                                                              Файл Pure.java:
                                                              \u0070u\u0062lic\u0020\u0063la\u0073\u0073
                                                              Pure \u007B\u0070ubl\u0069c\u0020st\u0061tic
                                                              void \u006Da\u0069n(\u0053tr\u0069ng[]\u0020
                                                              \u0061rgs)\u007B\u0053ys\u0074e\u006D. out.
                                                              \u0070\u0072int\u006Cn(\u0022H\u0061p\160y new \u0022+
                                                              // Мне нравится Java за её жёсткую стандартизованность.
                                                              \u0022ye\141r with Java!\r\u0022\u0029;\u007D\u007D
                                                              


                                                              Ответ: Да
                                                              Пояснение: Исходный код файла Pure.java является 100% чистой Java.

                                                              Если Ваша IDE не выдерживает такого издевательства, то сделайте это без IDE:
                                                              1. Создайте файл Pure.java и скопируйте в него код.

                                                              2. Запустите команду компиляции исходного кода
                                                              javac Pure.java
                                                              

                                                              3. Запустите программу в виртуальной машине Java с помощью команды:
                                                              java Pure
                                                              
                                                                0
                                                                Человекочитаемо. Это вам не однострочник.
                                                                  +2
                                                                  Разумеется! Мы же не для компьютеров пишем :-)
                                                                  0
                                                                  Весьма интересно, но всё-таки как задача для решения в уме — не пойдёт.

                                                                  Но как демонстрация некоторых особенностей компилятора — вполне сойдёт.
                                                                    +1
                                                                    У всех разные способности. Если помнить латинский алфавит и знать, что 0x41 это заглавная «A» и 0x61 это прописная «a», то легко можно составить таблицу кодов букв. Это значит что все ключевые слова и имена могут быть дешифрованы без всяких инструментов. Небольшое знание синтаксиса языка позволит восстановить всякие скобочки и кавычки, даже если их коды не в памяти. Конечно, это бесчеловечно мучить коллегу такими упражнениями. Но, услышать подобное описанному выше это вполне реально от многих даже без доступа к компьютеру (я надеюсь).

                                                                    Правильнее сказать некоторых особенностей языка Java, а не компилятора. Так как это определено в JLS и все правильные реализации компиляторов обязаны воплощать эти особенности. Но, каждый компилятор может быть со своими тараканами, которые естественно желательно, чтобы по породе приближались бы к жукам эталонной реализации компилятора javac из JDK.
                                                                      0
                                                                      Хмм, довольно интересно. Узнал кое-что новое для себя. Спасибо.
                                                                  0
                                                                  дубликат почему-то :-(
                                                                    +2
                                                                    Что-то я не зная java на все вопросы ответил. Идти получать сертификат? :)
                                                                      0
                                                                      Минимум это запомнить, как делать не следует без осознанной необходимости.
                                                                      +2
                                                                      По поводу русских букв. Как-то в проекте поставил в классе переменную «с» по-русски. Где-то час убил, чтобы понять, в чём ошибка и проект в другой части кода ругается на как бы ту же самую переменную c, которая уже на английском. Добавьте в топик к русским буквам в качестве примера.
                                                                        +1
                                                                        Добавил, спасибо
                                                                        +2
                                                                        Знаете, вот вопросы насчет каких тонкостей языка я понимаю, но вопросы с опечатками, аля как с 201l — убивать готов. Это бред, а не тонкий вопрос, вопрос на остроту зрения. Я не первый раз встречаю этот вопрос, но каждый раз когда его встречаю, негодую и не понимаю зачем его несут в массы. В IDE это проблема решается подсветкой синтаксиса, но вы поймите, что есть впечатлительные люди, которые возьмут этот вопрос на собеседование и напечают на бумаге без подсветки и еще специально шрифт подберут, чтобы ну прям совсем… Вот если бы я оказался на собеседовании с таким вопрос, я бы от досады, что у меня спрашивают вопросы не столько по делу, сколько картинки «найди 10 отличий», начал бы ругаться, причем сильно.
                                                                          0
                                                                          Эти вопросы составлены не для проверки уровня знаний, а для предостережения от ошибок. Например, мораль вопроса про 201l такова, что всегда надо использовать заглавную L, иначе могут быть такие вот проблемы.

                                                                          Если нужно, я могу добавить в начале статьи предупреждение о том, что запрещаю использовать эти вопросы на собеседованиях.
                                                                          0
                                                                          А скинте, пожалуйста, схему подсветки все-таки… На первый взгляд кажется удобной =)
                                                                            0
                                                                            drive.google.com/file/d/0BwTdIuGuk1gxYUVTcy0yc1lkc2c/edit?usp=sharing
                                                                              0
                                                                              спасибо!
                                                                            +1
                                                                            Мне кажется, людей, которые убивают читаемость код посредством использования подобных финтифлюшек, нужно превентивно сжигать огнём.

                                                                            Бывает так, что раскладываешь всё на примитивные части, убираешь даже такие базовые вещи как тернарные операции и всё равно, код не очень хорошо воспринимается другим человеком (с которым нужно работать)…

                                                                            Тем не менее, достоинства материала это не умаляет. Спасибо автору, провёл 5 минут с интересом и удовольствием.
                                                                              +1
                                                                              Вот ведь интересное явление — статью на данный момент добавило в закладки 430 человек (!!!), и с каждым днём добавляет всё больше. Я пролистал 5 страниц хаба Java, и все статьи, которые были там — по количеству добавлений в закладки ниже этой статьи. Неужели статья получилась действительно удачной?
                                                                                +1
                                                                                да, статья получилась удачной
                                                                                спасибо
                                                                                0
                                                                                Не знал только про объявление методов в виде short() [] {… }
                                                                                Это во всех версиях Java работает? :-)

                                                                                А про русские буквы в идентификаторах — обычно ошибаются только в букве «c», т.к. на клавиатуре для обоих языков одна и та же клавиша. На остальные можно нарваться, IMHO, только в результате обфускации кода.
                                                                                  0
                                                                                  Должна во всех. Но эта форма хороша для переменных, а для методов лучше использовать другую
                                                                                  short[] func() {…}
                                                                                  +1
                                                                                  Все, кроме 3, ответил корректно.
                                                                                  Уже потом про P в HEX-формате вспомнил )
                                                                                    0
                                                                                    Молодцы) Мало кто настолько хорошо знает язык

                                                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                  Самое читаемое