1. Java / Говнокод #12286

    +83

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    try{
        name.toLowerCase();
      }catch (NullPointerException e) {
       report().error("java.lang.NullPointerException", e);
       name = "";
      }

    Перспективная проверка на null

    Запостил: nafania217518, 13 Декабря 2012

    Комментарии (92) RSS

    • Н-да… Лучше перехватить NullPointerException, чем проверить (name != null) перед операцией… А присваивать чему-нибудь имя, преобразованное к нижнему регистру, видимо, незачем…
      %)
      Ответить
      • if (name != null) {
            name.toLowerCase();
        } else {
            report().error("java.lang.NullPointerException", new NullPointerException());
            name = "";
        }

        Ну некрасиво смотрится ведь!
        Ответить
        • В переписанном коде есть лишний фрагмент:
          name.toLowerCase();
          ни к чему не приводит, ведь значение name останется таким же, как и до вызова toLowerCase.
          Ответить
          • > В переписанном коде есть лишний фрагмент...
            ... подумал программист и, не долго думая, удалил строку 2.
            Ответить
            • Ну, если писать серьёзное решение, то Captain Obvious предлагает такой вариант:
              if (name != null) {
                  name = name.toLowerCase();
              } else {
                  name = "";
              }

              А от записывания (и тем более от бросания) NullPointerException тут вообще надо бы отказаться. Мы ведь уже предусмотрели, что делать в случае (name == null).
              Ответить
              • А мне кажется, что автор именно ради проверки на null дернул первый попавшийся под руку метод (toLowerCase()), поэтому:
                if (name == null) name = "";
                Ответить
                • nullToEmpty(name).toLowerCase()
                  Ответить
                • Тоже вполне возможный мотив для такого стиля программирования!
                  %)
                  В этом случае, за исключением репорта, тут полностью сохраняется семантика фрагмента.
                  Ответить
              • [SherlockHolmes]
                Кажется я понял мотив того, кто писал данный код.

                У автора кода возникла проблема - код крашился в непонятном месте с NPE, но логирования еще не было. Клиенты уже злые, и доводить дело до крешлога в следующий раз нельзя...

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

                Затем, через некоторое время, он прочтет лог, поймет где же возникает NPE, и выпилит эти заглушки.
                [/SherlockHolmes]
                Ответить
        • Я думаю, нужно дать возможность методу типа toString() возвращать "null", если применён к null-значению, а дальше всё просто.
          Ответить
          • А дальше ... Ищи ошибки в коде :)
            Ответить
          • Не нужно. Это сломает всю концепцию языка.

            Настоящие жависты toString() безопасный от NPE, делают так: ""+obj.
            Ответить
          • Objective Java :P

            Тут как раз в соседнем треде обсуждали, что в Objective C на null'ах можно вызывать что угодно, и оно промолчит и не крашнется.
            Ответить
            • Ну правильно, .method(params) по сути сахар над Class::method(this,params).
              Зачем NPE? Идиотия.
              Кстати мне нравится в C# extension methods, то что они так и сделаны.
              Ответить
              • > Зачем NPE?
                Ну как зачем. При вызове через null жаба тупо не знает, метод какого класса ей вызывать.
                Object o = null; // new Foo() or new Bar()?
                o.toString(); // what we can do here?
                Здесь я вижу только три варианта:
                1) Ничего не вызывать, и вернуть 0.0, 0, null или false, в зависимости от типа результата.
                2) Вызывать метод согласно типу переменной (в данном случае Object), подсунув ему null в this.
                3) Сделать нуллы типизированными (null перестанет быть пустой ссылкой, а будет ссылкой на null-объект соотвествующего класса) - запретить использовать просто null, а писать что-то в духе Foo.null или Bar.null.

                И все они мне нравятся еще меньше чем экцепшн, или необходимость ручной проверки на null...
                Ответить
                • А ну да. Виртуальные методы ведь. Ради полиморфизма - убогой пародии на мультиметоды.

                  >И все они мне нравятся еще меньше чем экцепшн, или необходимость ручной проверки на null...
                  Тоже щитаю, что NPE - меньшее из зол.

                  Могли хотя бы обращения к полям null ового объекта выдавать как null.
                  Хотя с повальными getter/setter и отсутсвием сахара в виде свойств это никого бы не спасло.

                  Короче NPE-говно в крестах, жабе и решетке у самого основания.
                  Ответить
                  • > Короче NPE-говно в крестах, жабе и решетке у самого основания.
                    Необходимое зло ;(

                    > Ради полиморфизма - убогой пародии на мультиметоды.
                    Да кстати, полноценный мультиметод не смог бы быть членом класса (и даже статиком), поэтому они бы разнесли уютненький мир жабы и шарпика к хуям.
                    Ответить
                    • плюсую за эмоциональность в конце предложения :)
                      Ответить
                    • >Да кстати, полноценный мультиметод не смог бы быть членом класса
                      Лолчто? Существуют не симетричные мультиметоды. Они они даже по сильнее симетричных:
                      class TJva
                      {
                        void multimethodAssSimetric(virtual TShrap rhs);
                        static void multimethodSemiSimetric(virtual TJva lhs, virtual TShrap rhs);
                      }
                      Ответить
                      • 1) С каких пор полноценный мультиметод ограничен джвумя аргументами?

                        2) Ну висит он себе в статике. Как я его вызывать то буду? Допустим есть такой код:
                        class Foo {
                            static void multi(virtual Bar foo, virtual Test test) { ... }
                        }
                        class Foo {
                            static void multi(virtual Foo foo, virtual Test test) { ... }
                        }
                        
                        Object obj = ...; // new Foo() or new Bar()
                        multi(foo, test); // how?
                        Если эта конструкция не работает - то как мне вызвать этот "мультиметод"? Через Foo.multi() ? Ну и нахуй он тогда сдался? А если работает - то метод уже нихуя не член класса, т.к. вывалился из положенной ему области видимости...
                        Ответить
                        • >1) С каких пор полноценный мультиметод ограничен джвумя аргументами?
                          Лолшто?
                          class Foo {
                              static void multi(virtual Bar foo, virtual Test test, virtual Ko kO) { ... }
                          }


                          AHAH А у тебя стасик не подсвечивает
                          Ответить
                        • >Как я его вызывать то буду?
                          class Foo {
                              static void multi(virtual Bar foo, virtual Test test) { ... }
                          }
                          class Foo {
                              static void multi(virtual Foo foo, virtual Test test) { ... }
                          ...
                          void f(){
                            ...
                            Bar.multi(foo, bar);//Bar.multi
                            Foo.multi(foo, bar);//Foo.multi
                            multi(foo, bar);//Foo.multi
                          
                          }
                          static void sf(){
                            ...
                            Bar.multi(foo, bar);//Bar.multi
                            Foo.multi(foo, bar);//Foo.multi
                            multi(foo, bar);//Foo.multi
                          }
                          }
                          Чё, какие проблемы?
                          Ответить
                          • Нууу, если принять ограничение, что все варианты мультиметода должны лежать в одном классе, а для модульности использовать Partial классы... то, наверное, это сойдет за полноценный мультиметод.
                            Ответить
                            • По секрету скажу: В сишарпе почти так и реализовано :)
                              Ответить
                              • Как же так? Неужели никому не хочется назвать меня троллем и сказать, что в сишарпе нет мультиметодов?
                                Ответить
                                • всемнасрать.жпг
                                  Ответить
                                  • И все-таки мультиметоды в сишарпе есть!

                                    ps:Чё это меня разлогинило?
                                    Ответить
                                    • pps:Не сжигайте.
                                      Ответить
                                    • Они даже в жабе есть
                                      http://www.lshift.net/blog/2006/06/23/multimethods-for-java
                                      Ответить
                                      • Не, ты перепутал. Это частный случай мультиметода на один элемент - визитор. Он конечно расширяем до мультиметодов второго и более порядка, но не без говна, копипасты и комбинаторного взрыва.
                                        Ответить
                                        • В шарпе же мультиметод встроенный на уровне языка.
                                          Ответить
                                  • LispGovno уже не торт
                                    Ответить
                                  • >насрать.жпг
                                    PPPS: Знаю что вас много. Но меня как истинного борща за свободу это не волнует.
                                    Ответить
                                • >что в сишарпе нет мультиметодов?
                                  Они там есть.
                                  А еще чудесное слово dynamic. Определяет какой метод вызввать в рантайме.
                                  Проблема в том что если оно не может разрулить какой метод вызвать - есть альтернативы, или вообще без вариантов, то оно в том же рантайме и падает.
                                  Ответить
                                  • > чудесное слово dynamic
                                    Это не мультиметоды, это утиная типизация.
                                    Ответить
                                    • А еще чудесное слово dynamic.
                                      Ну с этой фичей можно забыть о полиморфизме.
                                      Ответить
                  • Что-за NPE?
                    Ответить
                    • http://docs.oracle.com/javase/6/docs/api/java/lang/NullPointerException.html
                      Ответить
                • >Здесь я вижу только три варианта:
                  4)Метод вернет Maybe.Nothing вместо результата.
                  5)Объект Null примет сообщение toString и решит как его обработать. Может исключение, а может ещё что-то. Хотя потомок все объектов Object.Null мне больше нравится. Так можно больше вариантов для обработки и изменения поведения сделать.
                  Ответить
              • И кстати не упадут на null объекте. Если внутри не будет явного использования членов.
                Ответить
                • Шарп выбирает подходящий экстеншн метод на этапе компиляции, поэтому в этом случае никакой проблемы с null'ом нет.

                  Вызов же обычного метода будет разруливаться в рантайме - ведь вместо объекта могут подсунуть его потомка. И вот там null уже довольно фатален, т.к. рантайм не знает, что ему вызвать.
                  Ответить
                  • >подходящий экстеншн метод на этапе компиляции
                    Только статика, только хардкор!
                    А полиморфизм мы заменим ссылками на функцию, делегатами или фп!
                    Ответить
                    • и получим языг, который хочет Тарас
                      Ответить
                      • Блджад, но я ведь тоже такой джва года жду.
                        И с тарасоформатированием, обязательно!!!
                        Хотя "тарасоформатирование" и устоявшийся тут термин, но эксклюзивных прав Тарасу форматировать так код никто не давал, поскольку я, например задолго до всех обсуждений на гк юзаю подобный подход.
                        Ответить
                        • это уже суд решит, имеешь ли ты право форматировать тарасоформатированием, глядя в монитор подозрительно прямоугольной формы
                          Ответить
                    • Вот кстати в хаскеле можно делать лифтинг метода в монаду Maybe:
                      -- было
                      a :: Int -> Int
                      -- стало после поднятия
                      liftM a :: Maybe Int -> Maybe Int
                      При Nothing на входе будет возвращать Nothing на выходе, при Just x на входе вернет Just (a x).

                      Попробуем применить эту идею к яве. Разобъем типы на 2 категории - допускающие нулл (обозначим как nullable в шарпике через Object?) и недопускающие (обозначим Object). Object можно невозбранно кастовать в Object?, но не наоборот. При вызове метода на Object? метод автоматически лифтится, и если он возвращал T, то полученный метод будет возвращать T?.

                      Пример:
                      // У Object есть метод toString()
                      Object? a;
                      String s = a.toString(); // нельзя, String? не кастуется в String
                      String? s = a.toString(); // все ок, если a == null, то и s == null
                      Вот такая вот концепция пришла в мою сонную голову. При такой схеме NPE невозможно. Любая возможность его появления жестко пресекается компилятором.
                      Ответить
                      • Ах да, забыл еще каст из Object? в Object. Его запишем вот так (название нового оператора - первое что в голову пришло):
                        Object? test;
                        ifnotnull (Object test2 : test) {
                            // юзаем test2
                        } else {
                            // а тут юзать нечего, т.е. test это null
                        }
                        Итог - кастануть Object? в Object забыв проверить его на null попросту невозможно.
                        Ответить
                      • Вот цены бы хаскелу не было, будь он более обобщенным. А то смотрим и видим liftM/liftM_; liftM2/liftM2_; ...liftM100500/...
                        Ответить
                        • Если очень хочется прям обобщённости, можно взять Template Haskell, и сделать макро-lift. Но вообще тут лучше аппликативные функторы:
                          (+) <$> Just 3 <*> Just 1 --эквивалентно (liftA2 (+) (Just 3) (Just 1)), для монад liftM == liftA
                          func <$> a1 <*> a2 ... <*> an --эквивалентно (liftAn func a1 .. an)
                          Ответить
                          • Честно, отвратительная хрень. Читается как говно и с приоритетами легко запутаться.
                            Ответить
                      • В шарпе это реализуется через несколько экстеншен методов и лямбды. По поведению будет похоже на монады.
                        Псевдокод:
                        Object? a;
                        a.callIfNotNull(a=>a.toString()).ResultTo(print);
                        Таким вот нехитрым образом через икстеншен методы добавлять можно недомонады. toString вызовется только если 'a' не null, а затем если 'a' не нуоль и результат toString не null вызывается print.

                        http://ic.pics.livejournal.com/staffi/6805635/91492/91492_original.jpg
                        Ответить
                        • Да. Я хотел об этом сказать. Что видел шарпоизвраты с лямбдами чтобы сделать монады.
                          Проблема "умного" подхода ровно в одном: кода получается больше, читается он хуже и работает чуть медленей, чем "тупые" ifы.

                          ЗЫ. А. Теперь вижу хорошую, олдскульную картинку. Плюс.
                          Где-то у меня была сцылка на редкость упоротого поциента, который монадил в шарпе.
                          Ответить
                          • Не хватает как в хаскеле do синтаксического сахара над этим.
                            Ответить
                  • >Вызов же обычного метода будет разруливаться в рантайме
                    виртуального
                    Ответить
                    • А ну да, в шарпике же есть невиртуальные. Но в яве выбора нет, там только виртуальные.
                      Ответить
              • >.method(params) по сути сахар над Class::method(this,params).

                лолчто?
                this.method(params) по сути сахар над
                this->vtbl[Class::method_number](this,params)
                Ответить
                • Лолчто? Это только для виртуальных методов так.
                  Ответить
                  • Да. При этом не для виртуальных во время компиляции будет выбран вариант от пи. А для статических вариант без передачи this. Но в шарпе не виртуальных почти нет.
                    Ответить
                    • > Но в шарпе не виртуальных почти нет.
                      А в яве вообще нет.

                      P.S. Ну собственно ява сама по себе совсем простой язык. На порядки проще решеток и крестов, где-то в районе питона. Все сложности начинаются в ее стандартной либе...
                      Ответить
                      • >А в яве вообще нет.
                        Я бы упомянул про final - раз. Про static - два. Ну ладно - нет, так нет.

                        >Ну собственно ява сама по себе совсем простой язык.
                        Да, одна из немногих положительных её сторон, что они вдохновлялись минимализмом Вирта.

                        >Все сложности начинаются в ее стандартной либе...
                        Не будем о плохом...
                        Ответить
                        • final методы? а как final отражаются на поведении байткода при вызове метода? Мне кажется это просто ограничение для компилятора и особого, отличного от прочих, механизма вызова этих методов нет. (Джваву не знаю, так что это вопрос).
                          Ответить
                          • Хз. Может оно JVM как-то оптимизирует те методы, которые сразу обозначены как final, без шансов на всякое наследование и потому логично не создать для них таблиц.

                            final на переменных тоже вроде как ограничение для компилятора, а внутри HotSpota - это флаг который влияет на то когда можно публиковать объект.
                            Ответить
                        • С одной стороны компилятор должен догадаться, что финальный метод в некоторых случаях можно вызвать напрямую. С другой стороны - если его дернуть через базовый класс - он ведет себя вполне как виртуальный метод... Обязан ли рантайм вызывать final метод через объект класса, в котором он описан, невиртуально? Имхо нет, и это просто неплохая, но необязательная оптимизация.

                          static - ну статики да, не виртуальные, само собой, но у них и this нет, поэтому хрен с ними.
                          Ответить
                          • Я кстати на 99% уверен что умная JVM будет не просто вызывать напрямую, а инлайнить методы типа String.isEmpty().

                            Ибо метод не из интерфейса, а сам класс String - финальный.

                            Более того даже если у тебя самый обычный нефинальный класс без родителей и наследников, то вм может догадаться и заинлайнить его методы.
                            В HotSpote они даже оптимизируют полиморфизм для джвух наследников, а такие простые случаи и подавно.

                            То есть теоретически bormand - прав, по дефолту всё виртуальное, но внутри jvm оно может быть как просто вызовом, так и вообще инлайнится в код.

                            Возможно поэтому Блох в книжке рекомендует писать побольше finalов и запрещать наследование, там где не предполагается расширять в дальнейшем.
                            Ответить
                            • >оптимизируют полиморфизм для джвух наследников,
                              virtual void say(){
                              if(this is TDogB) print "gav gav gav"
                              else /*if(this is TCockB)*/ print "ko ko ko";
                              Как-то так?
                              Ответить
                              • Ну когда обсуждали полиморфизм в твоем же треде #12038 я давал сцылку:
                                http://www.javaspecialists.eu/archive/Issue158.html
                                We run this six times, one for each test case. Here are the test cases:

                                A1: No-morphic: Single subclass, pointed to directly
                                A2: Mono-Morphic: Single subclass, via interface
                                A3: Bi-Morphic: Two subclasses, via interface
                                A4: Poly-Morphic: Three subclasses, via interface
                                A5: Poly-Morphic: Four subclasses, via interface
                                A6: Poly-Morphic: Eight subclasses, via interface
                                  
                                On my server, the average results are:
                                
                                    A1     A2     A3       A4         A5         A6
                                    0 (0)  0 (0)  495 (9)  2855 (31)  2838 (18)  2837 (10)

                                When you run it with Java 6 -server, A1 and A2 come back with an average of 0 (0). The standard deviation is in brackets. In the case of a simple pointer to B or where there is a single subclass of B, the method call is inlined.

                                A3 is the bi-morphic case, where we have two subclasses of B. In this case, the results come back as 495 (9).
                                Ответить
                              • А вот и про инлайны
                                according to Cliff Click, deals with bi-morphism as a special case of poly-morphism: "Where the server compiler can prove only two classes reach a call site, it will insert a type-check and then statically call both targets (which may then further inline, etc)."

                                "HotSpot uses an inline-cache for calls where the compiler cannot prove only a single target can be called. An inline-cache turns a virtual (or interface) call into a static call plus a few cycles of work. It's is a 1-entry cache inlined in the code; the Key is the expected class of the 'this' pointer, the Value is the static target method matching the Key, directly encoded as a call instruction. As soon as you need 2+ targets for the same call site, you revert to the much more expensive dynamic lookup (load/load/load/jump-register). Both compilers use the same runtime infrastructure, but the server compiler is more aggressive about proving a single target."

                                Ответить
                              • >TDogB
                                >TCockB
                                Лол, только сейчас обратил внимание на нейминг.
                                Тип того. Он не лезет в таблицу, а прописывает адреса для calla явно.
                                Как видим, ускорение, от меньшего кол-ва обращений к памяти, около 5-6 раз.
                                Ответить
                          • >Имхо нет, и это просто неплохая, но необязательная оптимизация.

                            Ява раньше была очень тормозной, а из-за реализации таких вот вещей она стала просто тормозной.
                            И всё-таки быстрее, чем тот же js, хацкиль или питон. А если на каждый чих лезть в таблицу виртуальных методов это катастрофически понизит скорость.
                            Ответить
                            • > быстрее, чем тот же js, хацкиль или питон
                              Вот насчёт хацкила, кстати, неуверен.
                              Он хоть худо-бедно, но изначально компилился в натив. А в жабе 1.1 только интерпретация байт-кода, только хардкор. Да и потребление памяти у него всегда было значительно меньше (при рациональном коде, разумеется)
                              Ответить
                              • Иммутабельность.
                                Всё что выигрывается на assParallel, то и тратится на иммутабельность.
                                Но зато простор для оптимизации и роста - огромный.
                                Ответить
                                • Там, где иммутабельность не нужна, хацкиль может превратиться оптимизатором в тупые циклы, сильно зависит от кода. Хацкил даже от современной жабы не всегда отстаёт:
                                  http://shootout.alioth.debian.org/u32/haskell.php
                                  Ответить
                                  • Меня удивило другое - почему в хацкиле кода в 2-3 раза больше чем в js?
                                    А еще scala иногда быстрее чем "оптимальный" код на жабе.
                                    Плюс scala быстрее и короче хацкиля.

                                    Знаю я как бенчи делают. Очень трудно сделать объективно.
                                    Ответить
                                    • > Знаю я как бенчи делают. Очень трудно сделать объективно.
                                      Идеальный бенч должен делать человек, которому похуй на обе системы. Но т.к. ему похуй, он его делать не будет. Поэтому честных бенчей нет :(
                                      Ответить
                                      • Мало того - нужны еще негумнистые познания во всех языках.
                                        А то скала получается быстрее чем жаба в которую она транслируется.
                                        Это как сишка получилась бы быстрей ассемблера.
                                        Ответить
                                        • > Это как сишка получилась бы быстрей ассемблера.
                                          В общем то если взять матёрого сишника, и нуба-ассемблерщика, то так оно и будет. Что-то мне подсказывает, что и со скалой был точно такой же бенч.
                                          Ответить
                                        • Нужны по каждому языку реализация от нескольких кандидатов и притом каждый язык защищает свой кандидат, который хорошо знает его и любит. (Что-бы не было, вот этот язык мне не нравится и напишу гумно, а этот нравится и напишу быстрый код). (Хоть кресты и знаю, но защищать их я не стану).
                                          Ответить
                                          • > каждый язык защищает свой кандидат
                                            Проблема в том, что задание для бенчмарка должен составлять нейтральный человек. Иначе он придумает такую задачу, которая легче реализуется на том языке, который ему больше нравится...
                                            Ответить
                                            • Это правда. Поэтому нужно по задаче от каждого кандидата.
                                              Ещё вариант - попросить какого-нибудь математика задачу составить, который кроме матпакета ничего и не видел.
                                              Ответить
                                              • >попросить какого-нибудь математика задачу составить

                                                Нужны задачи приближенные к практике. С этим никто спорить не будет?
                                                Ответить
                                              • Я бы предпочел шифрование (простые числа, остатки), архивацию (поиск в массиве), dct, motion search (операции на матрицах - sad,satd), нейронные сети, fft, map-reduce,
                                                а не что-то а-ля projecteuler.
                                                Но это область нативной сишки и асмовставками.
                                                Ответить
                                                • кстати, для порядка асмовставки нужно запретить или хотябы соревнования проводить в разных весовых категориях.

                                                  Хаскель не может в асмовставки
                                                  Ответить
                                                  • А если в сам язык зашиты например быстрые нативные регулярки (как в js) или годная математеческая либа написанная на асме.
                                                    Ответить
                                                    • Тогда пользовать можно, тк это высокоуровневые инструменты самого языка. А вот низкоуровневыми аппаратнозависимыми хаками - запретить.
                                                      Ответить
                                                      • Извините, но варианта на хацкиле я понял - наверное он труЪ, ибо divmod и прочие чудеса.
                                                        import System.Environment
                                                        
                                                        pidgits n = 0 % (0 # (1,0,1)) where
                                                         i%ds
                                                          | i >= n = []
                                                          | True = (concat h ++ "\t:" ++ show j ++ "\n") ++ j%t
                                                          where k = i+10; j = min n k
                                                                (h,t) | k > n = (take (n`mod`10) ds ++ replicate (k-n) " ",[])
                                                                      | True = splitAt 10 ds
                                                         j # s | n>a || r+n>=d = k # t
                                                             | True = show q : k # (n*10,(a-(q*d))*10,d)
                                                          where k = j+1; t@(n,a,d)=k&s; (q,r)=(n*3+a)`divMod`d
                                                         j&(n,a,d) = (n*j,(a+n*2)*y,d*y) where y=(j*2+1)
                                                        
                                                        main = putStr.pidgits.read.head =<< getArgs
                                                        Ответить
                                          • >>>Нужны по каждому языку реализация от нескольких кандидатов и притом каждый язык защищает свой кандидат, который хорошо знает его и любит.

                                            Ну на том сайте вроде так и делают.
                                            А хацкиль делает жабу в среднем зачете, только потому что джва последних теста: Bad Output и No program.

                                            Так вот жаба сливает скале и хацки в бенче с интересным неймом pinumbers.

                                            Ну во-первых в глаза бросилось читерство:
                                            static {System.loadLibrary("jgmplib");  }

                                            http://shootout.alioth.debian.org/u32/program.php?test=pidigits&lang=java&id=2

                                            И шо это за гумно? Наверное вывод в буферизованный поток еще не проходили.
                                            private boolean prdigit(int y)
                                               {
                                                  strBuf.append(y);
                                                  if (++i % 10 == 0 || i == n) {
                                                     if (i%10!=0) for (int j=10-(i%10);j>0;j--) { strBuf.append(" "); }
                                                     strBuf.append("\t:");
                                                     strBuf.append(i);
                                                     System.out.println(strBuf);
                                                     strBuf = new StringBuffer(20);
                                                  }
                                                  return i == n;
                                               }

                                            Скала кстати тоже так написана.
                                            Наверное сравнивают скорость буферизации при выводе и либы, а не языки.
                                            Ответить
    • Вообще, вышеуказаный пример сводится к:
      if (name == null) {
          report().error("java.lang.NullPointerException", new NullPointerException());
          name = ""; 
      }
      Ответить
    • report().error("java.lang.NullPointerExc eption", new NullPointerException());
      а зачем вот эта строчка ?

      Я бы ее тоже грохнул, особого смысла в ней не вижу
      Ответить
      • > особого смысла в ней не вижу

        Более того, я в ней вижу зло, потому что, во-первых, занимает ресурсы на генерацию исключения, а во-вторых, засоряет лог, ведь полезной информации не даёт.
        Ответить
    • Оправившись от лёгкого потрясения и услышав голос, врач спросил:
      Ответить

    Добавить комментарий