Quantcast
Channel: Найцікавіше на DOU
Viewing all articles
Browse latest Browse all 8115

Почему Java все еще не торт. Yet

$
0
0

Всем привет. Месяц назад вышла Java 11. Все круто. 6-месячныйрелиз работает. Платформа действительно начала быстро развиваться и обрастать новыми фичами. Вот, например, полный списокиз 90 фич, которые появились в одинадцатке. В основном это изменения на уровне JVM, но, по сути, это фундамент для будущих плюшек.

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

Pattern matching

Пожалуй, единственная конструкция из всего списка, которую я использую почти каждый день:

if (obj instanceof Device) {
    Device device = (Device) obj;
    ...
}

Для нас, как разработчиков, вполне очевидно, что если мы сделали проверку на тип переменной и она прошла, то мы вполне можем оперировать переменной как объектом этого типа. Сейчас же мы постоянно должны приводить переменную к нужному типу явно. Уже даже появился JEP305для этой задачи, который предлагает следующий выход:

if (x matches Device device) {
    // can use device here
}

Но, судя по всему, в ближайший год это не попадет в джаву. Остается только надеяться, что фичу не придется ждать 10 лет.

switch for class

Синтаксис не очень частый, но иногда просто бесит, что нельзя сделать простой:

switch (obj.getClass()) {
    case Integer.class:…
    case Long.class:
       ...
}

Лично мне не понятно, почему такая простая, казалось бы, операция все еще не поддерживается джавой нативно. Конечно, эту проблему всегда можно обойти полиморфизмом или пачкой if elseили сделать class.getSimpleName()и свитч по строке, но это не так удобно. Да и по производительности явно не лучший вариант.

List<Integer> to int[]

Каждому разработчику известно чувство, когда он фокусируется, входит в поток и начинает эффективно колбасить. И вот все идет классно, пока не нужно сделать преобразование List<Integer> в int[]или наоборот. Нельзя просто так взять и преобразовать лист целых чисел в массив примитивов. Сейчас, чтобы это сделать, нужно или писать цикл преобразования:

int[] integerListToInt(List<Integer> integers) {
        int[] result = new int[integers.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = integers.get(i);
        }
        return result;
    }

Ну или через стримы:

int[] array = list.stream().mapToInt(i->i).toArray();

Оба варианта, очевидно, не самые оптимальные и удобные. Да и вопрос на СО, которому уже 10 лет с сотнями голосов и сотнями тысяч просмотров как бы намекает нам про актуальность. С преобразованием в обратную сторону — такая же ситуация.

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

list.toArray(new Integer[0])

new ArrayList(array)

Если отсутствие преобразования List<Integer> -> int[]еще как-то можно объяснить разными сущностями intи Integer, то отсутствие конструктора с массивом для ArrayListвообще не укладывается в голове. И почему за 20 лет существования языка нужно использовать:

new ArrayList<>(Arrays.asList(array))

вместо:

new ArrayList<>(array)

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

ConcurrentSet

Да, его до сих пор нету в джаве, и судя по всему никогда и не будет. К счастью, начиная с 8-йджавы, есть статический метод для его создания:

ConcurrentHashMap.newKeySet()

Но, во-первых, про этот метод нужно знать, во-вторых, опять же вопрос удобства, ну и в-третьих, это не ConcurrentSet, а просто Set. А сам класс — некий KeySetView. Почти в любом большом опенсорс-проекте, который я видел, был свой ConcurrentSet.

Path API

Как только появилось новое Path API, я сразу на него перешел. И вот, 7 лет спустя, до сих пор каждый раз, когда мне нужно использовать это API — страдаю от этого. Вы не можете сделать new Path(), так как это интерфейс. А статических фабричных методов в классе Pathsцелых 2. И поэтому часто код с Path выглядит так:

Paths.get(dataDir.toString(),  folder);

вместо:

Paths.get(dataDir,  folder);

Это, конечно, не так критично, так как у Pathесть метод resolve(), но в виду его специфики он не всегда подходит.

Вывод

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

А что вам не нравится в сегодняшней Java?


Viewing all articles
Browse latest Browse all 8115

Trending Articles