Авторские права

Брюс Эккель - Философия Java3

Здесь можно скачать бесплатно "Брюс Эккель - Философия Java3" в формате fb2, epub, txt, doc, pdf. Жанр: Прочая старинная литература. Так же Вы можете читать книгу онлайн без регистрации и SMS на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Брюс Эккель - Философия Java3
Рейтинг:
Название:
Философия Java3
Автор:
Издательство:
неизвестно
Год:
неизвестен
ISBN:
нет данных
Скачать:

99Пожалуйста дождитесь своей очереди, идёт подготовка вашей ссылки для скачивания...

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.

Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

Описание книги "Философия Java3"

Описание и краткое содержание "Философия Java3" читать бесплатно онлайн.








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

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

Проблемы стирания

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

Однако за стирание приходится расплачиваться. Параметризованные типы не могут использоваться в операциях, в которых явно задействованы типы времени выполнения — преобразования типов, instanceof и выражения new. Вся информация о типах параметров теряется, и при написании параметризованного кода вам придется постоянно напоминать себе об этом. Допустим, вы пишете фрагмент кода

class Foo<T> { Т var;

}

Может показаться, что при создании экземпляра Foo:

Foo<Cat> f = new Foo<Cat>(),

код class Foo должен знать, что он работает с Cat. Синтаксис создает впечатление, что тип Т подставляется повсюду внутри класса. Но на самом деле это не так, и при написании кода для класса вы должны постоянно напоминать себе: «Нет, это всего лишь Object».

Кроме того, стирание и миграционная совместимость означают, что контроль за использованием параметризации не настолько жесткий, как хотелось бы:

//: generics/ErasureAndlnheritance.java

class GenericBase<T> { private T element;

public void set(T arg) { arg = element; } public T get О { return element. }

}

class Derivedl<T> extends GenericBase<T> {}

class Derived2 extends GenericBase {} // Без предупреждений

// class Derived3 extends GenericBase<?> {}

// Странная ошибка.

// Обнаружен непредвиденный тип : ?

// требуется- класс или интерфейс без ограничений

public class ErasureAndlnheritance { @SuppressWarni ngs("unchecked") public static void main(String[] args) { Derived2 d2 = new Derived2(); Object obj = d2.get(); d2.set(obj); // Предупреждение!

}

} ///

Derived2 наследует от GenericBase без параметризации, и компилятор не выдает при этом никаких предупреждений. Предупреждение выводится позже, при вызове set().

Для подавления этого предупреждения в Java существует директива, приведенная в листинге (до выхода Java SE5 она не поддерживалась):

@SuppressWarnings("unchecked")

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

Ошибка, выдаваемая в Derived3, означает, что компилятор рассчитывает увидеть «обычный» базовый класс.

Добавьте к этому дополнительные усилия на управление ограничениями, если вы не желаете интерпретировать параметр типа как простой Object, — и что мы получаем в остатке? Гораздо больше хлопот при гораздо меньше, пользе по сравнению с параметризованными типами в языках вроде С++, Ada или Eiffel. Конечно, это вовсе не означает, что эти языки в целом эффективнее Java в большинстве задач программирования, а говорит лишь о том, что их механизмы параметризации типов отличаются большей гибкостью и мощью, чем в Java.

Проблемы на границах

Пожалуй, самый странный аспект параметризации, обусловленный стиранием, заключается в возможности представления заведомо бессмысленных вещей. Пример:

//: generics/ArrayMaker.java

import java.lang.reflect.*;

import java.util.*;

public class ArrayMaker<T> { private Class<T> kind;

public ArrayMaker(Class<T> kind) { this.kind = kind; } @SuppressWarni ngs("unchecked") T[] create(int size) {

return (T[])Array.newInstance(kind, size);

}

public static void main(String[] args) { ArrayMaker<String> stringMaker =

new ArrayMaker<String>(String.class); String[] stringArray = stringMaker.create(9); System.out.pri ntin(Arrays.toStri ng(stri ngArray));

}

} /* Output;

[null, null, null. null. null. null. null. null, null]

*///:-

Несмотря на то что объект kind хранится в виде Class<T>, стирание означает, что фактически он хранится в виде Class без параметра. Следовательно, при выполнении с ним каких-либо операций (например, при создании массива) Array. newlnstance() не обладает информацией о типе, подразумеваемой kind. Метод не сможет выдать нужный результат, не требующий преобразования типа, а это приводит к выдаче предупреждения, с которым вам не удастся справиться.

Обратите внимание: для создания массивов в параметризованном коде рекомендуется использовать Array.newlnstance().

Если вместо массива создается другой контейнер, ситуация меняется:

//: generics/ListMaker.java

import java util.*;

public class ListMaker<T> {

List<T> create О { return new ArrayList<T>(); } public static void main(String[] args) {

ListMaker<String> stringMaker= new ListMaker<String>(); List<String> stringList = stringMaker.createO;

}

} ///:-

Компилятор не выдает предупреждений, хотя мы знаем, что <Т> в new ArrayList<T>() внутри create() удаляется — во время выполнения <Т> внутри класса нет, поэтому здесь его присутствие выглядит бессмысленным. Однако если вы попробуете применить эту идею на практике и преобразуете выражение в new ArrayList(), компилятор выдаст предупреждение.

Но действительно ли этот элемент не имеет смысла? Что произойдет, если мы поместим в список несколько объектов, прежде чем возватим его?

II: generics/Fi1ledListMaker java

import java.util.*;

public class FilledListMaker<T> { List<T> create(T t, int n) {

List<T> result = new ArrayList<T>(); for(int i = 0: i < n; i++)

result.add(t); return result:

}

public static void main(String[] args) {

FilledListMaker<String> stringMaker =

new Fi11edListMaker<String>(); List<String> list = stringMaker.createC'Hello", 4): System.out.pri ntln(1i st);

}

} /* Output:

[Hello, Hello. Hello. Hello]

*lll:~

Хотя компилятор ничего не может знать о Т в create(), он все равно способен проверить — на стадии компиляции — что заносимые в result объекты имеют тип Т и согласуются с ArrayList<T>. Таким образом, несмотря на то что стирание удаляет информацию о фактическом типе внутри метода или класса, компилятор все равно может проверить корректность использования типа в методе или классе.

Так как стирание удаляет информацию о типе внутри тела метода, на стадии выполнения особую роль приобретают границы — точки, в которых объект входит и выходит из метода. Именно в этих точках компилятор выполняет проверку типов и вставляет код преобразования. Рассмотрим следующий ^параметризованный пример:

// generics/SimpleHolder.java

public class SimpleHolder { private Object obj;

public void set(Object obj) { this.obj = obj; } public Object get О { return obj; } public static void main(String[] args) {

SimpleHolder holder = new SimpleHolder().

holder set("Item"),

String s = (String)holder getO:

}

} ///-

Декомпилировав результат командой javap -с SimpleHolder, мы получим (после редактирования):

public

void set(java lang Object);

0

aload_0

1:

aload 1

2:

putfield #2; II Поле obj.Object;

5.

return

public

java lang.Object getO.

0;

aload 0

1-

getfield #2; II Поле obj-Object,

4

areturn

public

static void main(java 1ang.String[]);

0:

new #3, // Класс SimpleHolder

3-

dup

4:

invokespecial #4; // Метод "<init>".()V

7.

astore_l

8-

aload 1

9.

ldc #5; II String Item

11

invokevirtual #6; // Метод set (Object;)V

14:

aload_l

15.

invokevirtual #7, // Метод get:()Object:

18;

checkcast #8, //'Класс java/lang/String

21:

astore_2

22.

return

Методы set() и get() просто записывают и читают значение, а преобразование проверяется в точке вызова get().

Теперь включим параметризацию в приведенный фрагмент:

II: generics/GenericHolder.java

public class GenericHolder<T> { private T obj,

public void set(T obj) { this.obj = obj; } public T get О { return obj; } public static void main(String[] args) { GenericHolder<String> holder =

new GenericHolder<String>(); holder.set("Item"); String s = holder.get О;

}

Необходимость преобразования выходного значения get() отпала, но мы также знаем, что тип значения, передаваемого set(), проверяется во время компиляции. Соответствующий байт-код:

public void set(java.lang.Object);

0:

aload_0

1:

aload_l

2:

putfield #2; // Поле obj:0bject;

5:

return

public java.lang.Object getO;

0:

aload_0

1:

getfield #2; // Поле obj:0bject;

4:

areturn

public static void main(java.lang.String[]);

0.

new #3; // Класс GenericHolder

3:

dup

4:

invokespecial #4; // Метод "<init>"-()V

7:

astore_l

8:

aload_l

9:

ldc #5; // String Item

11


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "Философия Java3"

Книги похожие на "Философия Java3" читать онлайн или скачать бесплатно полные версии.


Понравилась книга? Оставьте Ваш комментарий, поделитесь впечатлениями или расскажите друзьям

Все книги автора Брюс Эккель

Брюс Эккель - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Брюс Эккель - Философия Java3"

Отзывы читателей о книге "Философия Java3", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.