LINUX.ORG.RU
ФорумTalks

[java][г]Маразматические глюки.

 


0

0

Есть простенький код:

import java.util.Arrays;
import java.util.List;
public class Main {
    public static void main(String[] args) {
      Container cont0 = new Container();
      for(String s : cont0.getStrings()){
        System.out.println(s);
      }
    }
}
class Container<T> {
  public T getType(){
    return null;
  }
  public List<String> getStrings(){
    return Arrays.asList("1", "2", "str");
  }
}

Компилируем.... и получаем

Main.java:6: incompatible types
found   : java.lang.Object
required: java.lang.String
      for(String s : cont0.getStrings()){
                                     ^
1 error

Это не бага, а фишка, только как эти **** которые такие фишки придумали объяснят свои затейства (в багтреккере наверняка это есть но непонятно как найти)?

ps. Пойти что ли в церковь микрософта и поставить черную свечку за тех кто реализовал генерики в яве?

★★☆

Последнее исправление: wfrr (всего исправлений: 1)
Ответ на: комментарий от wfrr

Странно, мне почему-то кажется все наоборот. bbk123 объясняет, что параметризация в конкретном объекте или есть (во всех случах), или нет (во всех случаях).

svu ★★★★★
()
Ответ на: комментарий от svu

Только вот вы не заметили что по этому факту с ним никто не спорит 8). Ему просто говорят, что это жутко нелогичное поведение.

wfrr ★★☆
() автор топика
Ответ на: комментарий от wfrr

Логика имеет много измерений. Одно из них - ЛОГИЧНО сохранять бинарную совместимость со старым кодом. Эту потрясающую мысль, кажется, он тоже озвучивал.

svu ★★★★★
()
Ответ на: комментарий от wfrr

> Только вот вы не заметили что по этому факту с ним никто не спорит 8). Ему просто говорят, что это жутко нелогичное поведение.

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

bbk123 ★★★★★
()
Ответ на: комментарий от svu

Вы не заметили что эту потрясающую мысль озвучили все?, а не так давно его в очередной раз ткнули носом что эта совместимость сохраняется 8) при любом раскладе.

wfrr ★★☆
() автор топика
Ответ на: комментарий от qnikst

про несоберётся я немножно ошибся cont0 не соберётся и куча ворнингов вылезет про приведения. так что совместимостью это назвать тяжко ;)

qnikst ★★★★★
()
Ответ на: комментарий от bbk123

Многоуважаемейший, на это вам неоднократно отвечали 8) и даже демонстрировали примеры, но вы наитупейшим образом это игнорируете, а на те посты просто не ответили, может вы тролль?

wfrr ★★☆
() автор топика
Ответ на: комментарий от wfrr

гхм. Перечитал этот камент еще раз, в обе стороны:)

Есть у меня подозрения, что это штука, зависящая от компилятора. Прогнать бы это через какой-нибудь другой компилятор...

svu ★★★★★
()
Ответ на: комментарий от qnikst

Соббсно на этом месте я сильнее всего удивился - по поводу cont0.

svu ★★★★★
()
Ответ на: комментарий от svu

> Прогнать бы это через какой-нибудь другой компилятор...

В Eclipse есть свой компилятор.

bbk123 ★★★★★
()
Ответ на: комментарий от wfrr

> > > Только вот вы не заметили что по этому факту с ним никто не спорит 8). Ему просто говорят, что это жутко нелогичное поведение.

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


Многоуважаемейший, на это вам неоднократно отвечали 8) и даже демонстрировали примеры, но вы наитупейшим образом это игнорируете, а на те посты просто не ответили, может вы тролль?


Что именно мне отвечали и что демонстрировали? Расскажите, каким образом вы можете гарантировать безопасность приведения типов в случае если значение cont0 получено из библиотеки написанной на Java 1.4.2?

bbk123 ★★★★★
()
Ответ на: комментарий от qnikst

> Теперь вопрос о том, что подрузамевается под совместимостью с Java 1.4. Если то под какую версию java написаны исходные файлы и соотв как компилировать, то проект с generic не скомпилируется в принципе. Если имеется ввиду совместимость уже байткода, то как мы заметили разницы нет, и будут работать все написанные коды. и почему нельзя автоматизировать каст в 1м случае неясно (это примерно про это писал выфер). Вариант давайте ребята учитесь писать как надо, а старый варинат мы скоро отключим, не рассматривается, т.к. на мой взгляд он единственный логичный.

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

http://www.linux.org.ru/jump-message.jsp?msgid=4835741&cid=4836130
http://www.linux.org.ru/jump-message.jsp?msgid=4835741&cid=4839972
http://www.linux.org.ru/jump-message.jsp?msgid=4835741&cid=4842818
http://www.linux.org.ru/jump-message.jsp?msgid=4835741&cid=4844663

bbk123 ★★★★★
()
Ответ на: комментарий от bbk123

> Что именно мне отвечали и что демонстрировали? Расскажите, каким образом вы можете гарантировать безопасность приведения типов в случае если значение cont0 получено из библиотеки написанной на Java 1.4.2?

т.е. есть код написанный с generic Type (например Container<?>) и вы собираетесь взять и использовать его в классе написанном под Java 1.4?

можно демонстрацию работающего примера?

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

> Что именно мне отвечали и что демонстрировали? Расскажите, каким образом вы можете гарантировать безопасность приведения типов в случае если значение cont0 получено из библиотеки написанной на Java 1.4.2?

т.е. есть код написанный с generic Type (например Container<?>) и вы собираетесь взять и использовать его в классе написанном под Java 1.4?

можно демонстрацию работающего примера?

Предположим вы и я написали следующие классы для Java 1.4.2.

Я написал:

import java.util.*;

public class B {

	private List list = new ArrayList();

	public List getList() {
		return list;
	}
}

Вы получили от меня файл B.class и написали:

import java.util.*;

public class A {

	private B b = new B();

	public A() {
		List list = b.getList();
		list.add(0, new Integer(3));
		list.add(1, new Double(5.7));
	}

	public B getB() {
		return b;
	}
}

При этом исходного кода вашего класса у меня нет. Есть лишь файл A.class, котрый вы для меня скомпилировали.

Затем я перешёл на Java 5.0 и решил, что класс B должен быть параметризированным:

import java.util.*;

public class B<T> {

	private List<String> list = new ArrayList<String>();

	public List<String> getList() {
		return list;
	}
}

В дальнейшем я пытаюсь использовать ваш класс следующим образом:

		A a = new A();
		B b = a.getB();
И хотя класс B у меня уже параметризирован, я получаю ссылку на его экземпляр из вашего класса A, который ничего о параметризации не знает и гарантировать, что getList() вернёт List, содержащий только String-и, не может.

bbk123 ★★★★★
()
Ответ на: комментарий от bbk123

по поводу кода, разве так будет легче?

        A a = new A();
        B<String> b = a.getB();

и в том и в другом случае у нас параметризация не гарантирутеся и к тому же добавятся одинаковые проверки /для for (String s: b.getStrings())/ в байткоде.

К тому же вы не заметили, что случай 1 в посте отличается от этого.

Расширю ваш пример по аналогии

public class B< T> {

    public final String[] str = {"1","2"};
    //old code

    public final List<String> getStr(){
        List<String> lst = new ArrayList<String>();
        for (String s: str){
            lst.add(s);
        }
        return lst;
    }

Вы поверите, что это вернёт всегда List<String>, чтобы я не делал? но код

    public static void main(String[] args) {
        A a = new A();
        B b = a.getB();
        for (String s: b.getStr()) {
            //code
        }
    }

компилироваться не будет. Хотя наверное такие случаи сложно отследить.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

> по поводу кода, разве так будет легче?

B<String> b = a.getB();


Тут вы приводите raw type от B<T> к B<String> на свой страх и риск.

и в том и в другом случае у нас параметризация не гарантирутеся и к тому же добавятся одинаковые проверки /для for (String s: b.getStrings())/ в байткоде.


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

Если вы приводите непараметризированный тип к параметризированному нужно тоже понимать что вы делаете.

К тому же вы не заметили, что случай 1 в посте отличается от этого. Расширю ваш пример по аналогии.


Разнца в коде вашего getStr() и моего getList() значения не имеет. Код не является частью интерфейса.

Вы поверите, что это вернёт всегда List<String>, чтобы я не делал?

public final List<String> getStr()



С точки зрения интерфейса ваш List<String> getStr() отличается от моего List<String> getList() только названием. В моём старом B.class может быть непараметризированная версия getStr(), точно так же как и getList(). При этом новая, параметризированная верстя B.class прекрасно слинкуется с вашим непараметризированным A.class. Поэтому если B b = a.getB();, то b.getStr() должно возвращать List. Так же, как это делает b.getList().

компилироваться не будет. Хотя наверное такие случаи сложно отследить.


Welcome back to Java 1.4.2

bbk123 ★★★★★
()
Ответ на: комментарий от bbk123

блин было бы круто, если бы вы обращали внимание по каким пунктам с вами спорят, а по каким нет :) 90% очередного поста утверждения которые все участники дискуссии понимают и никто не спорит с их правильностью

Разнца в коде вашего getStr() и моего getList() значения не имеет. Код не является частью интерфейса.

ну как-бы если есть желение вразумлять меня далее, то смотрим код внимательнее.

С точки зрения интерфейса ваш List<String> getStr() отличается от моего List<String> getList() только названием.

а так же модификаторами и тому, к чему он обращается ^_^. Хочешь замени final на static может тогда мысль поймёшь.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

> блин было бы круто, если бы вы обращали внимание по каким пунктам с вами спорят, а по каким нет :) 90% очередного поста утверждения которые все участники дискуссии понимают и никто не спорит с их правильностью

Я пытаюсь объяснить почему авторы генериков добавили raw types и реализовали их таким образом. Вся эта тема об этом. Вы хотите поговорить о чём-то другом?

> Разнца в коде вашего getStr() и моего getList() значения не имеет. Код не является частью интерфейса.


ну как-бы если есть желение вразумлять меня далее, то смотрим код внимательнее.


Смотрите ниже.

> С точки зрения интерфейса ваш List<String> getStr() отличается от моего List<String> getList() только названием.


а так же модификаторами и тому, к чему он обращается ^_^. Хочешь замени final на static может тогда мысль поймёшь.


С каких пор модификатор final у getStr() препятсятвует существованию нескольких версий B.class? С каких пор реализация этого метода (то, что он обращается к final полю или играет на гармошке) стала частью интерфеса?

bbk123 ★★★★★
()
Ответ на: комментарий от bbk123

Вся эта тема об этом.

Я вас разочарую 8) не об этом.

wfrr ★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.