Pull to refresh

Comments 52

Поменял. Надеюсь, так лучше.
да, действительно лучше!
Теперь мне интересно какая там была раньше картинка
Опережая вопрос — а заголовок был: «Java, ну зачем?»
;)
Моя первая мысль после просмотра статьи.
«I was programming in ML in the 1990s. Imagine my dismay when Java came out in 1995, one of the biggest step backwards in history» (автор)
Да, Java позволяет отстрелить себе ногу (это вы еще git не видели :))
С дженериками лучше, чем без них, удобнее: часть труда берет на себя компилятор. Конечно, его можно обмануть или ввести в заблуждение, только зачем?
Вообще, пост напоминает историю, как израильтяне хаммер перевернули.
Почему не видел?=)

А я и не говорю, что с дженериками плохо. Мне просто совсем непонятно, почему нельзя было хранить ссылку на класс-параметр в объекте дженерика. В этом случае дженерики оставались бы дженериками и в рантайме.
Обратная совместимость, не?
Повторюсь, почему нельзя было сразу так сделать? Очевидное же решение. Подозреваю, что это связано со старыми коллекциями, но не владею точной информацией.
Вначале джененриков даже в мыслях не было. А потом пришлось делать костылями ради обратной совместимости.
Так именно в этом и вопрос — ради какой совместимости? Коллекции? Это-то и интересно…
За этот костыль сейчас благодарят авторы Scala. Её продвинутую систему типов удалось реализовать лишь благодаря type erasure. А вот с .NET-овской версией Scala всё загнулось, как раз из-за type reification.
Я не разработчик языка. И потому судить о причинах и рассуждать «почему бы не хранить ссылку» — не могу. Авторам таки виднее, чем мне. Думаю, Выступления двух наших известных соотечественников, которые «пилят» производительность лямбды, показывают сколько «стекла» может крыться за с виду простым шагом. Поэтому… есть особенность, о ней надо знать. Можно свои идеи изложить в виде багрепорта. Можно просто смириться.
alhimik45 уже ответил — обратная совместимость. Это и хлеб и бич Java. Хлеб, потому что Java используют многие enterprise-приложения, которые не любят изменений внутри своего кода. А следовательно «write once run everywhere»-принцип должен соблюдаться и в части старого наследия.
На моей памяти эта обратная совместимость именно в энтерпрайз приложениях и чудила: проект с WebService, собранный JDK7, не запускается на JDK6. Что-то ему не ладно показалось в javax.ws.* Обратная совместимость — это не только формат классов. Это дохрена библиотек. Которые совершенствуются и включаются в JDK.
В общем, не верю я в сферическую совместимость в вакууме. Для какого-то конкретного приложения — может быть. Если авторы приложат руки и специально проверят.
проект с WebService, собранный JDK7, не запускается на JDK6

Не наоборот?
С последними версиями вполне может быть (натыкался, например, на баги типа 1.6_22 — работает, 1.6_25 работает, в 1.6_24 — сломалось).
Не, именно так. В разработке я на 7 перешел. А на боевой площадке еще 6я стояла. В процессе багфикса поймал :)
Так это не обратная совместимость. Если вы собрали под 7, то как оно под 6 запустится? Это forward-совместимость, а не backward.
Тогда я не прав. Тут, тогда, про обратную совместимость.
Так ведь обратная совместимость языка, а не библиотек!
Смотрите, дженерики были введены в версии 1.5, до неё все делали все преобразования вручную. Проблема в том, что часть кода работала отличным от дженериков образом и внесение их в ВМ привело бы к краху многие приложения. А ведь до сих пор есть код, написанный под 1.4 (а крутится порой и на 1.7).
В моем случае были не библиотеки а классы из состава самого JDK, в чем вся прелесть. Кроме того, после смены собственника старый софт часто намекает на левую java-машину и отказывается работать. OpenProj к примеру.
Ещё раз: совместимость языка. Классы JDK теоретически можно невозбранно заменять, как там с практикой — не знаю. Но даже в этом случае JDK стараются наращивать, а не менять (добавить nio, а не заменять io, добавить Collections, ...) Но есть случаи, когда меняют и JDK, обычно об этом заранее предупреждает свойство
@deprecated
Можно еще сделать простой импорт Y класса:

import ru.open.haven.client.gui.Test.X.Y;

public class Test {
    public static class X {
        public static class Y {
            public static String Z = "life is good";
        }

        public static C Y;
    }

    public static class C {
        public static String Z = "life is pain";
    }

    public static void main(final String[] args) {
        System.out.println(Y.Z);
    }
}


Выведет «life is good»
Действительно, намудрил со статическим. Поправил в посте, спасибо
Дженерики в Java тот ещё выкидыш. И пока они обратную совместимость не поломают, ничего в лучшую сторону не изменится.
> Каст к типу дженерика — это костыль
Единственный ценный месседж: каст к типу дженерика пропадает в рантайме.
Кстати, это действительно так? Я не проверял, но что-то есть сомнения.

Забавно, но информация о дженериках полностью не стирается в рантайме.
См. docs.oracle.com/javase/6/docs/api/java/lang/reflect/Type.html и все что с ним связано, вроде:
docs.oracle.com/javase/6/docs/api/java/lang/reflect/Method.html#getGenericReturnType()
Или:

short a = 1;
short b = 2;
short z = a + b;
System.out.println(z);

Что выведет?
Пишите ещё через неделю )
> Реализуйте метод, бросающий произвольный Throwable

Unsafe.getUnsafe().throwException(new IOException());
Или так:

Thread.currentThread().stop(new IOException());
Да, все верно, хоть и использовать deprecated методы и не комильфо;)
Все-таки подход к управлению потоками кардинально поменялся и это как раз тот случай, когда deprecated == нельзя, имхо.

Я не писал этот способ, потому что задание, все-таки, было «дополнительным» к дженерикам. Грубо говоря, на «усвоенный материал». На мой взгляд весьма забавное (как и каст нулла)

В любом случае, добавлю в пост, спасибо.
Ну, на то он и Unsafe. Так не интересно;) Просто так не напишете. В любом случае, добавлю, спасибо
UFO just landed and posted this here
UFO just landed and posted this here
Груви — это велосипед, от которого отказался автор языка. О чем тут еще можно говорить?
UFO just landed and posted this here
Ну, этот отказался, другие подобрали. Что это доказывает? Как из этого можно ввести, что это плохой язык?
Он не плохой, он просто не нужен. Ну скажем, есть в Groovy хотя бы pattern matching? А персистентные коллекции? Какую задачу вообще Groovy решает кроме того, что Java-код можно переписать чуть короче?
Автор) Я тебе подкину тоже веселый пример.

public class GenericTest
{
	public static void main(String[] args)
	{
		Map<Integer, Long> v = new HashMap<Integer, Long>();
		v.put(1, 0L);

		Long val = v.isEmpty() ? 0 : v.get(2);

		System.out.println(val);
	}
}


Могу сказать код скомпилится на все JDK, и не выполнится на любой(тестил 6-7-8, мб и где то пофиксили но я не видел)
Конечно, у вас вот тут:

Long val = v.isEmpty()? 0: v.get(2);

NPE, надо вот так:

Long val = v.isEmpty()? 0: v.get(1);
Нет, v.get(2) возвращает null, который легко печатается System.out.println(). Если пример выше переписать через if:
import java.util.*;

public class GenericTest {
    public static void main(String[] args) {
        Map<Integer, Long> v = new HashMap<Integer, Long>();
        v.put(1, 0L);
        if(v.isEmpty()) {
            System.out.println(0);
        } else {
            System.out.println(v.get(2));
        }   
    }   
}

То тоже будет работать. Как и другой код, что я уже написал. Так что вся хитрочть в операторе "?"
Это особенность не дженерика, а оператора "?". В Java он не умеет выводить тип. Вот так работает:

import java.util.*;

public class GenericTest {
    public static void main(String[] args) {
        Map<Integer, Long> v = new HashMap<Integer, Long>();
        v.put(1, 0L);
        Long val = v.isEmpty() ? Long.valueOf(0) : v.get(2);
        System.out.println(val);
    }   
}

Вопрос на засыпку — придумать пример из жизни, когда использование таких конструкций реально _необходимо_ ;-)
Мне кажется, в программировании отсутствует понятие «необходимости» как таковое. Всегда есть какое-то альтернативное решение. Всегда есть «архитектура лучше/выше/быстрее», «код понятнее/короче/круче». Потому-то оно и искусством считается=)

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

Эти задачки — это не паттерны, это синтетические примеры, в которых неочевидное поведение языка (например) приводит к неожиданным результатам. И если встретить подобный пример в живом проекте вряд ли удастся (и слава богу) — понимание этой неочевидности краевых случаев _необходимо_ (противоречу сам себе с необходимостью;)).

Разумеется, так нельзя писать, но понимать, как устроены дженерики (что не нужно полагаться на тип и удивляться пришедшим багам), как разруливаются конфликты имен — никогда не повредит.
Sign up to leave a comment.

Articles