Как стать автором
Обновить

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

Для улучшения читаемости программ в Java добавлена интересная возможность разделять разряды длинных чисел символом подчеркивания:

int value1 =  1_500_000;
long value2 = 0xAA_BB_CC_DD;


В C++ также разделяются разряды:
int value1 = 1'500'000;


Перечисления в С++ также существуют строготипизированные. Вообще вам не стоило в статью втягивать С++
Как и range-based for, библиотека коллекций, std::string, тип ссылок, по части управления ресурсами — такая важная вещь, как RAII.
еще добавляем семантику перемещения, возможности метапрограммирования, constexpr и прочие плюшки…
НЛО прилетело и опубликовало эту надпись здесь
в С++, кстати, даже используя возврат bool/int, в качестве флага ошибки, вместо исключений, можно делать это изящно без передачи «выходного» аргумента, с возвратом флага и значения, через структурированные привязки:
auto [result, data] = obj.CalculateSomething();

Также есть std::optional…
И в С++ препроцессор — это зло, особенно огорчает его наплевательское отношение к namespace. Для условной компиляции, есть if constexpr (compile-time) и шаблоны. Для макро-функций, есть constexpr выражения, которые не подставляют тупо строку, а вычисляют выражения, плюс делают это с учётом типов.
только для выхода из вложенных циклов

Не только циклов, но и произвольных блоков кода.

один способ передачи объекта в метод – по ссылке.

Нет. В Java все аргументы метода передаются по значению. Просто для объектных типов значением является ссылка.

сигнатура (имя метода, возвращаемое значение, аргументы) с точностью совпадали

Нет. Возвращаемое значение не входит в сигнатуру метода.
Код, демонстрирующий утверждение
class A {
    A method() {
        throw new UnsupportedOperationException("not implemented");
    }
}
class B extends A {
    @Override B method() {
        return this;
    }
}



возможность корректно использовать строки в switch-case

Этой возможностью лучше не пользоваться, т.к. это сахар, на деле, switch делается по хешкоду, который может иметь коллизии.

Этой возможностью лучше не пользоваться, т.к. это сахар, на деле, switch делается по хешкоду, который может иметь коллизии.

Не совсем. Сравнение делается вызовом String.equals, а этот метод сравнивает строки посимвольно. Допускается, что в байт-коде может быть все по другому, но поведение должно быть именно таким.

В поисках правды я обратился к Oracle документации по Java: docs.oracle.com/javase/specs/index.html

Спецификация языка Java согласна с Вами и утверждает, что строки в switch сравниваются через equals: docs.oracle.com/javase/specs/jls/se10/html/jls-14.html#jls-14.11.

If one of the case constants is equal to the value of the expression, then we say that the case label matches. Equality is defined in terms of the == operator (§15.21) unless the value of the expression is a String, in which case equality is defined in terms of the equals method of class String.


Но в JVM спецификации написано следующее — docs.oracle.com/javase/specs/jvms/se10/html/jvms-3.html#jvms-3.10:

The Java Virtual Machine's tableswitch and lookupswitch instructions operate only on int data. Because operations on byte, char, or short values are internally promoted to int, a switch whose expression evaluates to one of those types is compiled as though it evaluated to type int.


Строки прямо не упомянуты. Но все остальные типы приводятся к int. Что делает версию с проверкой строки по хэшкоду весьма правдоподобной.

Не получив четкого ответа из доков, начал компилить и декомпилить. У меня HotSpot JVM 1.8. При декомпиляции switch по String видно, что используется и hashcode и equals:

switch(name.hashCode()) {
        case 3556498:
            if (name.equals("test")) {
                // здесь код
            }
Возвращаемое значение входит в сигнатуру метода, но переопределить метод можно лишь в том случае, если новое возвращаемое значение совместимо с возвращаемым значением родителя.

docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2
Java — очень старый язык. Сейчас доступны языки значительно более высокого уровня. При этом некоторые (Rust, ATS) по производительности и возможности работы с аппаратурой не уступают C/C++. Интересно было бы сравнить с ними.
НЛО прилетело и опубликовало эту надпись здесь
В Rust значительно больше условий проверяется на этапе компиляции. Есть классы типов — очень высокоуровневый мезанизм. Есть алгебраические типы и pattern matching. Различаются беззнаковые и знаковые числа. Есть синтаксические макросы.
Все это означает более высокий уровень абстракции, на котором может работать программист.
А а Java есть reflection. Ну и тот же паттерн-матчинг через какое-то время, я думаю, появится (как появился в c#). Rust просто другой язык. Не выше и не ниже уровнем: просто другой и для других целей сделанный.
Reflection — скорее низкоуровревая конструкция, перекладывающая на программиста работу компилятора. По этому поводу я всегда вспоминаю главу «Правильное и неправильное использование RTTI» в книге Страуструппа, в которой приведено несколько примеров неправильного использования и ни одного правильного. В Java reflection нужен для инструментальных средств (но разработчики языка вполне могли бы предложить специализированные решения дли того же позднего связавания), реализации динамических языков (очень специфическая область, что бы под нее затачивать язык) и для компенсации недоработок в дизайне (отсутствие pattern matching).
В завершение, порядок байт в многобайтных примитивах в Java фиксированный (младший байт по младшему адресу, Little-endian, обратный порядок).


А разве не BigEndian?
    public static void main(String[] args) {
        long value = 1;
        System.out.println(Longs.toByteArray(value)[0]); // выводит "0"
    }
Сперва задайтесь вопросом, что за класс Longs, откуда вы его взяли и как он работает.
Если же требуются выполнять операции вставки/удаления элементов, или создавать более сложные структуры данных, то необходимо использовать коллекции, такие как множество (Set), список (List), карта (Map).

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


Память, занимаемую объектом, не нужно освобождать, эту работу выполняет сборщик мусора. Невозможно забыть удалить объект после использования – меньше вероятность появления эффекта «утечки памяти».

утечки в java точно такой же бич, как и в других языках. При всём при том, что вы правы насчёт конкретной реализации утечек, в java существует другой способ достичь такого же поведения. Например создать переменную класса (см. ключевоей слово static) — она не подвержена сборке мусора. А если это коллекция и туда постоянно идёт вставка? Но это простейший вариант, возможны и куда как более сложные случаи.


В основе идеологии языка Java лежит утверждение «все есть объект».

а потом вы пишите про примитивы… В общем уже на заре создания языка авторы конкретную такую бомбу заложили под идеологию...


abstract class Base {
abstract public void method();
}

такие вещи чаще всего выражаются через интерфейс.


interface Base {
    void method();//он автоматически public, и до java 8 интерфейс не может содержать реализации метода
}

Для управления «видимостью» предназначены 3 модификатора доступа: private, protected, public.

4 модификатора. Ведь пишете же дальше о всех, почему здесь неправильно? 4ый называется модификатор доступа по умолчанию или же package-private. И да он состоит в отсутствии иного модификатора доступа.


Все коллекции делятся на 3 больших класса: списки, множества и карты.

И здесь пусто про очереди :(


Программируя на Java, не приходится постоянно «бояться» допустить ошибку – зачастую среда разработки подскажет, что надо исправить, а иногда сделает это за вас.

для сей/плюсов так же есть инструменты статического анализа кода. Правда, действительно, IDE для java совсем без таких интсрументов выглядит странно (да и комплиятор кое-что умеет), а вот для c/c++ они часто не входят в IDE...


Если же возникла ошибка времени выполнения, то в логе всегда указан тип ошибки и место ее возникновения в исходном коде – борьба с такими ошибками становится тривиальным делом.

Не панацея. Совсем. Вполне можно обработать реальную ошибку в одном месте и создать в другом месте новую. Инструмент действительно хороший и мощный, но всё же не так уж и редко приходится искать реальную причину...


PS и да, чтобы было понимае — я люблю java как удобный инструмент, я с ней уже ~8 лет работаю… просто хочется предостеречь от подводных камней, которые ну очень близко :-)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории