Вход/Регистрация
Java: руководство для начинающих
вернуться

Шилдт Герберт

Шрифт:

// Эта строка кода верна, так как Т и V относятся типу Integer. Paircinteger, Integer> х = new Pair(l, 2);

//И эта строка кода верна, так как Integer является подклассом Number. Pair у = new Pair(10.4, 12); А следующий фрагмент кода содержит ошибку:

// Эта строка кода недопустима, так как String не является подклассом Number. Pair z = new Pair(10.4, "12"); В данном случае класс String не является производным от класса Number, что нарушает граничное условие, указанное в объявлении класса Pair. ## Использование метасимвольных аргументов Несмотря на всю полезность типовой безопасности в обобщениях, иногда она может помешать использованию идеально подходящих языковых конструкций. Допустим, требуется реализовать метод absEqual , возвращающий логическое значение true в том случае, если два объекта рассмотренного выше класса NumericFns содержат одинаковые абсолютные значения. Допустим также, что этот метод должен оперировать любыми типами числовых данных, которые могут храниться в сравниваемых объектах. Так, если один объект содержит значение 1,25 типа Double, а другой — значение -1,25 типа Float, метод absEqual должен возвращать логическое значение true. Один из способов реализации метода absEqual состоит в том, чтобы передавать этому методу параметр типа NumericFns, а затем сравнивать его абсолютное значение с абсолютным значением текущего объекта и возвращать логическое значение true, если эти значения совпадают. Например, вызов метода absEqual может выглядеть следующим образом:

NumericFns dOb = new NumericFns(1.25) ; NumericFns fOb = new NumericFns(-1.25) ;

if(dOb.absEqual(fOb)) System.out.println("Absolute values are the same."); else System.out.println("Absolute values differ."); На первый взгляд может показаться, что при выполнении метода absEqual не должно возникнуть никаких затруднений, но это совсем не так. Затруднения начнутся при первой же попытке объявить параметр типа NumericFns. Каким он должен быть? Казалось бы, подходящим должно быть следующее решение, где т указывается в качестве параметра типа:

//Не пройдет!

// определить равенство абсолютных значений в двух объектах boolean absEqual(NumericFns ob) { if(Math.abs(num.doubleValue) == Math.abs(ob.num.doubleValue) return true; return false; } В данном случае для определения абсолютного значения каждого числа используется стандартный метод Math. abs . Полученные значения сравниваются. Но дело в том, что рассматриваемое здесь решение окажется пригодным лишь в том случае, если объект класса NumericFns, передаваемый в качестве параметра, имеет тот же тип, что и текущий объект. Так, если текущий объект относится к типу NumericFns<Integer>, параметр ob также должен быть типа NumericFns<Integer>, а следовательно, сравнить текущий объект с объектом типа NumericFns<Double> не удастся. Таким образом, выбранное решение не является обобщенным. Для того чтобы создать обобщенный метод absEqual , придется воспользоваться еще одним свойством обобщений в Java, называемым метасимвольным аргументом. Для указания такого аргумента служит знак ?, обозначающий неизвестный тип данных. Используя метасимвольный аргумент, можно переписать метод absEqual следующим образом:

// определить равенство абсолютных значений в двух объектах boolean absEqual(NumericFns<?> ob) { // обратите внимание на метасимвол if(Math.abs(num.doubleValue) == Math.abs(ob.num.doubleValue) return true; return false; } В данном случае выражение NumericFns<?> соответствует любому типу объекта из класса NumericFns и позволяет сравнивать абсолютные значения в двух произвольных объектах класса NumericFns. Ниже приведен пример программы, демонстрирующий применение метасимвольного аргумента.

// Применение метасимвольного аргумента, class NumericFns { T num; // передать конструктору ссылку на числовой объект NumericFns(Т п) { num = п; } // возвратить обратную величину double reciprocal { return 1 / num.doubleValue; } // возвратить дробную часть double fraction { return num.doubleValue - num.intValue; } // определить равенство абсолютных значений в двух объектах boolean absEqual(NumericFns<?> ob) { if(Math.abs(num.doubleValue) == Math.abs(ob.num.doubleValue)) return true; return false; } // ...

} // продемонстрировать применение метасимвольного аргумента class WildcardDemo { public static void main(String args[]) { NumericFns iOb = new NumericFns(6) ; NumericFns dOb = new NumericFns(-6.0) ; NumericFns 10b = new NumericFns(5L); System.out.println("Testing iOb and dOb."); // В этом вызове метода тип метасимвольного // аргумента совпадает с типом Double. if(iOb.absEqual(dOb)) System.out.println("Absolute values are equal."); else System.out.println("Absolute values differ."); System.out.println; System.out.println("Testing iOb and 10b."); // А в этом вызове метода тип метасимвольного // аргумента совпадает с типом Long. if(iOb.absEqual(10b)) System.out.println("Absolute values are equal."); else System.out.println("Absolute values differ."); }

} Выполнение этой программы дает следующий результат:

Testing iOb and dOb. Absolute values are equal.

Testing iOb and 10b. Absolute values differ. Обратите внимание на два следующих вызова метода absEqual :

if(iOb.absEqual(dOb))

if(iOb.absEqual(10b)) В первом вызове переменная iOb указывает на объект типа NumericFns<Integer>, а переменная dOb — на объект типа NumericFns<Double>. Благодаря применению ме- тасимвольного аргумента по ссылке на объект iOb удается передать объект dOb методу absEqual . Подобным образом формируется и другой вызов, в котором методу передается объект типа NumericFns<Long>. И последнее замечание: не следует забывать, что метасимвольные аргументы не оказывают влияния на тип создаваемого объекта в классе NumericFns. Для этой цели служит оператор extends, указываемый в объявлении класса NumericFns. Метасимвольный аргумент лишь указывает на соответствие любому допустимому объекту класса NumericFns. ## Ограниченные метасимвольные аргументы Метасимвольные аргументы можно ограничивать таким же образом, как и любой параметр типа. Ограниченные метасимвольные аргументы приобретают особое значение при написании методов, которые должны оперировать только объектами подклассов отдельного суперкласса. Для того чтобы стало понятнее назначение метасимвольных аргументов, обратимся к простому примеру. Допустим, имеется следующий ряд классов:

class А { // ... }

class В extends А { // ... }

class С extends А { // ... }

// Обратите внимание на то, что D не является подклассом А. class D { // ... } Здесь класс А является суперклассом для классов В и С, но не для класса D. Теперь рассмотрим очень простой обобщенный класс.

// Простой обобщенный класс. class Gen { ^ Т ob; Gen(Т о) { ob = о; }

} В классе Gen предусмотрен один параметр типа, который определяет тип объекта, хранящегося в переменной ob. Как видите, на тип Т не накладывается никаких ограничения. Следовательно, параметр типа Т может обозначать любой класс. А теперь допустим, что требуется создать метод, принимающий аргумент любого типа, соответствующего объекту класса Gen, при условии, что в качестве параметра типа этого объекта указывается класс А или его подклассы. Иными словами, требуется создать метод, который оперирует только объектами типа Gen<тип>, где тип — это класс А или его подклассы. Для этой цели нужно воспользоваться ограниченным метасимволь- ным аргументом. Ниже для примера приведено объявление метода test , которому в качестве аргумента может быть передан только объект класса Gen, на параметр типа которого накладываются следующие ограничения: соответствие классу А или его подклассам.

  • Читать дальше
  • 1
  • ...
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: