Читаем Философия Java3 полностью

Преобразование типа или instanceof с параметром типа не приводит ни к какому эффекту. В следующем контейнере данные хранятся во внутреннем представлении в форме Object и преобразуются к Т при выборке:

//. generics/GenericCast.java

class FixedSizeStack { private int index = 0; private Object[] storage; public FixedSizeStackOnt size) {

storage = new Object[size];

}

public void push(T item) { storage[index++] = item; }

@SuppressWarni ngs("unchecked")

public T popО { return (T)storage[--index], }

}

public class GenericCast {

public static final int SIZE = 10; public static void main(String[] args) { FixedSizeStack strings =

new FixedSizeStack(SIZE); for (String s • "А В С D E F G H I J".splitC' "))

strings.push(s), for(int i = 0. i < SIZE; i++) {

String s = strings pop(); System.out.print(s + " ");

} /* Output:

JIHGFEDCBA

*///:-

Без директивы @SuppressWarnings компилятор выдает для рор() предупреждение о «непроверенном преобразовании». Вследствие стирания он не знает, безопасно преобразование или нет, поэтому метод рор() никакого преобразования не выполняет. Т стирается до первого ограничения, которым по умолчанию является Object, так что рор() на самом деле преобразует Object в Object.

Перегрузка

Следующий пример не компилируется, хотя на первый взгляд выглядит вполне разумно:

// generics/UseList java

// {CompileTimeError} (He компилируется)

import java.util.*;

public class UseList { void f(List v) {}

void f(List v) {}

} III ~

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

II. generics/UseList2 java

import java util.*;

public class UseList2 { void fl(List v) {} void f2(List v) {}

} III.-

К счастью, проблемы такого рода обнаруживаются компилятором.

Резюме

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

Аргумент такой: одним из самых логичных мест для использования механизма параметризации являются контейнерные классы: List, Set, Map и т. д. До выхода Java SE5 объект, помещаемый в контейнер, преобразовывался в Object, и информация типа терялась. Если же вы хотели снова извлечь объект из контейнера, его приходилось преобразовывать к нужному типу. Я пояснял происходящее на примере List с элементами Cat (разновидность этого примера с Apple и Orange приведена в начале главы 11). Без параметризованной версии контейнера из Java SE5 вы помещаете и извлекаете из контейнера Object, поэтому в List с элементами Cat легко поместить объект Dog.

Однако версии Java, существовавшие до появления параметризации, не допускали злоупотреблений объектами, помещаемыми в контейнер. Если вы помещали Dog в контейнер Cat, а затем пытались интерпретировать все элементы контейнера как Cat, то при извлечении ссылки на Dog и ее преобразовании к Cat происходило преобразование RuntimeException. Проблема обнаруживалась, пусть и на стадии выполнения, а не во время компиляции.

В предыдущих изданиях книги я писал:

«Это не просто мелкая неприятность, а потенциальный источник трудноуловимых ошибок. Если одна часть (или несколько частей) программы вставляет объекты в контейнер, а в другой части программы обнаруживается, что в контейнер был йомещен недопустимый объект, вам придется искать, где именно была выполнена неверная операция вставки».

Но позже я задумался над этим аргументом, и у меня появились сомнения. Во-первых, насколько часто это происходит? Не помню, чтобы такая ошибка встретилась в моей программе. Когда я спрашивал людей на конференциях, мне тоже не удалось найти никого, с кем бы это случилось. В другой книге использовался пример списка с именем files, содержащего объекты String, — в этом примере казалось абсолютно логичным добавить в список объект типа File, так что объекту, вероятно, стоило присвоить имя fileNames. Какую бы проверку типов ни обеспечивал язык Java, программист все равно может написать малопонятную программу — а плохо написанная программа, даже если она компилируется, все равно остается плохо написанной. Вероятно, нормальный разработчик присвоит контейнеру понятное имя вроде cats, которое послужит предупреждением для программиста, пытающегося занести в контейнер другой объект, отличный от Cat. Но, даже если это и произойдет, как долго такая ошибка останется скрытой? Здравый смысл подсказывает, что исключение произойдет вскоре после начала тестирования с реальными данными.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных