| « Поставить закладку » « Сделать стартовой » | |||
|
|||
| Статьи:: Интернет технологии :: Технология JAVA :: ГЛАВА 4. Классы-оболочки
ГЛАВА 4. Классы-оболочкиJava — полностью объектно-ориентированный язык. Это означает, что все, что только можно, в Java представлено объектами. Восемь примитивных типов нарушают это правило. Они оставлены в Java из-за многолетней привычки к числам и символам. Да и арифметические действия удобнее и быстрее производить с обычными числами, а не с объектами классов. Но и для этих типов в языке Java есть соответствующие классы — классы-оболочки (wrapper) примитивных типов. Конечно, они предназначены не для вычислений, а для действий, типичных при работе с классами — создания объектов, преобразования объектов, получения численных значений объектов в разных формах и передачи объектов в методы по ссылке. На рис. 4.1 показана одна из ветвей иерархии классов Java. Для каждого примитивного типа есть соответствующий класс. Числовые классы имеют общего предка — абстрактный класс Number, в котором описаны шесть методов, возвращающих числовое значение, содержащееся в классе, приведенное к соответствующему примитивному типу: bytevalue (), doubievalue (), floatValue (), intValue(), longValue (), shortValue (). Эти методы переопределены в каждом из шести числовых классов-оболочек.
Рис. 4.1. Классы примитивных типов Помимо метода сравнения объектов equals о, переопределенного из класса object, все описанные в этой главе классы, кроме Boolean и class, имеют метод compareTo (), сравнивающий числовое значение, содержащееся в данном объекте, с числовым значением объекта — аргумента метода compareTo(). В результате работы метода получается целое значение:
Что полезного в классах-оболочках? Числовые классы В каждом из шести числовых классов-оболочек есть статические методы преобразования строки символов типа string лредставляющей число, в соответствующий примитивный тип: Byte.parseByte(), Double.parseDouble(), Float.parseFloat(), Integer.parselnt(), Long.parseLong(), Short.parseShort(). Исходная строка типа string, как всегда в статических методах, задается как аргумент метода. Эти методы полезны при вводе данных в поля ввода, обработке параметров командной строки, т. е. всюду, где числа представляются строками цифр со знаками плюс или минус и десятичной точкой. В каждом из этих классов есть статические константы MAX_VALUE и MIN_VALUE, показывающие диапазон числовых значений соответствующих примитивных типов. В классах Double и Float есть еще константы POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN, о которых шла речь в главе 1, и логические методы проверки isNan(), isInfinite(). Если вы хорошо знаете двоичное представление вещественных чисел, то можете воспользоваться статическими методами floatTointBits() и doubieToLongBits(), преобразующими вещественное значение в целое. Вещественное число задается как аргумент метода. Затем вы можете изменить отдельные биты побитными операциями и преобразовать измененное целое число обратно в вещественное значение методами intsitsToFioat() и longBitsToDouble(). Статическими методами toBinaryString(), toHexString() и toOctalString() классов integer и Long можно преобразовать целые значения типов int и long, заданные как аргумент метода, в строку символов, показывающую двоичное, шестнадцатеричное или восьмеричное представление числа. В листинге 4.1 показано применение этих методов, а рис. 4.2 демонстрирует вывод результатов.
Рис. 4.2. Методы числовых классов ; Листинг 4.1. Методы числовых классов class NumberTest{ public static void main(String[] args){ int i = 0; short sh = 0; double d = 0; Integer kl = new Integer(55); Integer k2 = new Integer(100); Double dl = new Double(3.14); try{ i = Integer.parselnt(args[0]); sh = Short.parseShort(args[0]); d = Double.parseDouble(args[1]); dl = new Double(args[1]); kl = new Integer(args[0]); }catch(Exception e){} double x = 1.0/0.0; System.out.println("i = " + i) ; System.outjprintln("sh - " + sh) ; System.out.println("d. = " + d) ; System.out.println("kl.intValue() = " + kl.intValue()); System.out.println("dl.intValue() '= "'+ dl.intValuei)); System.out.println("kl > k2? " + kl.compareTo(k2)); System.out.println ("x = " + x); System.out.println("x isNaN? " + Double.isNaN(x)); System.out.println("x islnfinite? " + Double.islnfinite(x)); System.out.println("x == Infinity? " + (x == Double.POSITIVE_INFINITY) ); System.out.println("d = " + Double.doubleToLongBits(d)); System.out.println("i = " + Integer.toBinaryString(i)); System.out.println("i = " + Integer.toHexString(i)); System.out.println("i = " + Integer.toOctalString(i)); } } Методы parseint() и конструкторы классов требуют обработки исключений, поэтому в листинг 4.1 вставлен блок try{} catch(){}. Обработку исключительных ситуаций мы разберем в главе 16. Класс Boolean Это очень небольшой класс, предназначенный главным образом для того, чтобы передавать логические значения в методы по ссылке. Конструктор Boolean (String s) создает объект, содержащий значение true, если строка s равна "true" в любом сочетании регистров букв, и значение false — для любой другой строки. Логический метод booieanvalue() возвращает логическое значение, хранящееся в объекте. Класс Character В этом классе собраны статические константы и методы для работы с отдельными символами. Статический метод digit(char ch, in radix) переводит цифру ch системы счисления с основанием radix в ее числовое значение типа int. Статический метод forDigit(int digit, int radix) производит обратное преобразование целого числа digit в соответствующую цифру (тип char) в системе счисления с основанием radix. Основание системы счисления должно находиться в диапазоне от Character.MIN_RADIX до Character.MAX_RADIX. Метод tostring() переводит символ, содержащийся в классе, в строку с тем же символом. Статические методы toLowerCase(), touppercase(), toTitieCase() возвращают символ, содержащийся в классе, в указанном регистре. Последний из этих методов предназначен для правильного перевода в верхний регистр четырех кодов Unicode, не выражающихся одним символом. Множество статических логических методов проверяют различные характеристики символа, переданного в качестве аргумента метода:
Точные диапазоны управляющих символов, понятия верхнего и нижнего регистра, титульного символа, пробельных символов, лучше всего посмотреть по документации Java API. Листинг 4.2 демонстрирует использование этих методов, а на рис. 4.3 показан вывод этой программы. Листинг 4.2. Методы класса Character в программе CharacterTest class CharacterTest{ public static void main(String[] args){ char ch = '9'; Character cl = new Character(ch); System.out.println("ch = " + ch); System.out.println("cl.charValue() = " + c1.charValue()); System.out.println("number of 'A' = " + Character.digit('A', 16}}; System.out.println("digit for 12 = " + Character.forDigit(12, 16}}; System.out.printlnC'cl = " + cl.toString() ); System.out.println("ch isDefined? " + Character.isDefined(ch)); System.out.println("ch isDigit? " + Character.isDigit(ch)); System.out.println("ch isldentifierlgnorable? " + Character.isldentifierlgnorable(ch)); System.out.println("ch isISOControl? " + Character.isISOControl(ch)); System.out.println("ch isJavaldentifierPart? " + Character.isJavaldentifierPart(ch)); System.out.println("ch isJavaldentifierStart? " + Character.isJavaldentifierStart(ch)); System.out.println("ch isLetter? " + Character.isLetter(ch)); System.out.println("ch isLetterOrDigit? " + Character.isLetterOrDigit(ch)); System.out.println("ch isLowerCase? " + Character.isLowerCase(ch)); System.out.println("ch isSpaceChar? " + Character.isSpaceChar(ch)); System.out.println("ch isTitleCase? " + Character.isTitleCase(ch)); System.out.println("ch isUnicodeldentifierPart? " + Character.isUnicodeldentifierPart(ch)); System.out.println("ch isUnicodeldentifierStart? " + Character.isUnicodeldentifierStart(ch)); System.out.println("ch isUpperCase? " + Character.isUpperCase(ch)); System.out.println("ch isWhitespace? " + Character.isWhitespace(ch)); } } В класс Character вложены классы Subset и UnicodeBlock, причем класс Unicode и еще один класс, inputSubset, являются расширениями класса Subset, как это видно на рис. 4.1. Объекты этого класса содержат подмножества Unicode.
Рис. 4.3. Методы класса Character в программе CharacterTest Вместе с классами-оболочками удобно рассмотреть два класса для работы со сколь угодно большими числами. Класс Biglnteger Все примитивные целые типы имеют ограниченный диапазон значений. В целочисленной арифметике Java нет переполнения, целые числа приводятся по модулю, равному диапазону значений. Для того чтобы было можно производить целочисленные вычисления с любой разрядностью, в состав Java API введен класс Biglnteger, хранящийся в пакете java.math. Этот класс расширяет класс Number, следовательно, в нем переопределены методы doubleValue(), floatValue(), intValue(), longValue(). Методы byteVaiue() и shortvalue() не переопределены, а прямо наследуются от класса Number. Действия с объектами класса Biglnteger не приводят ни к переполнению, ни к приведению по модулю. Если результат операции велик, то число разрядов просто увеличивается. Числа хранятся в двоичной форме с дополнительным кодом. Перед выполнением операции числа выравниваются по длине распространением знакового разряда. Шесть конструкторов класса создают объект класса BigDecimai из строки символов (знака числа и цифр) или из массива байтов. Две константы — ZERO и ONE — моделируют нуль и единицу в операциях с объектами класса Biglnteger. Метод toByteArray() преобразует объект в массив байтов. Большинство методов класса Biglnteger моделируют целочисленные операции и функции, возвращая объект класса Biglnteger:
В листинге 4.3 приведены примеры использования данных методов, а рис. 4.4 показывает результаты выполнения этого листинга.
Рис. 4.4. Методы класса Biglnteger в программе BiglntegerTest Листинг 4.3. Методы класса Biglnteger в программе BiglntegerTest import Java.math.Biglnteger; class BiglntegerTest{ public static void main(String[] args){ Biglnteger a = new Biglnteger("99999999999999999") ; Biglnteger b = new Biglnteger("88888888888888888888"); System.out.println("bits in a = " + a.bitLength()); System.out.println("bits in b = " + b.bitLengthO); System.out.println("a + b = " + a.add(b)); System.out.println("a & b = " + a.and(b)); System.out.println("a & ~b = " + a.andNot(b)); System.out.println("a / b = " + a.divide(b)); Biglnteger[] r = a.divideAndRemainder(b); System.out.println("a / b: q = " + r[0] + ", r = " + r[l]); System.out.println("gcd(a, b) = " + a.gcd(b)); System.out.println("max(a, b) = " + a.max(b)); System.out.printin("min(a, b) = " + a.min(b)); System.out.println("a mod b = " + a.mod(b)); System.out.println("I/a mod b = " + a.modlnverse(b)); System.out.println("алп mod b = " + a.modPow(a, b)); System.out.println("a * b = " + a.multiply(b)); System.out.println("-a = " + a.negate()); System, out. println ("~a = " + a.not()); System.out.println("a | b = " + a.or(b)); System.out.println("а л 3 = " + a.pow(3)); System.out.println("a % b = " + a.remainder(b)); System.out.println("a « 3 = " + a.shiftLeft(3)}; System.out.println("a » 3 = " + a.shiftRight(3)); System.out.println("sign(a) = " + a.signum()); System.out.println("a - b = " + a.subtract(b)); System.out.println("а л b = " + a.xor(b)); } } Обратите внимание на то, что в программу листинга 4.3 надо импортировать пакет Java.math. Класс Big Decimal Класс BigDecimal расположен В пакете java.math. Каждый объект этого класса хранит два целочисленных значения: мантиссу вещественного числа в виде объекта класса Biglnteger, и неотрицательный десятичный порядок числа типа int. Например, для числа 76.34862 будет храниться мантисса 7 634 862 в объекте класса Biglnteger, и порядок 5 как целое число типа int. Таким образом, мантисса может содержать любое количество цифр, а порядок ограничен значением константы integer.MAX_VALUE. Результат операции над объектами класса BigDecimal округляется по одному из восьми правил, определяемых следующими статическими целыми константами:
В классе BigDecimal четыре конструктора:
При использовании третьего из перечисленных конструкторов возникает неприятная особенность, отмеченная в документации. Поскольку вещественное число при переводе в двоичную форму представляется, как правило, бесконечной двоичной дробью, то при создании объекта, например, BigDecimal(0.1), мантисса, хранящаяся в объекте, окажется очень большой. Она показана на рис. 4.5. Но при создании такого же объекта четвертым конструктором, BigDecimal ("0.1"), мантисса будет равна просто 1. В Классе переопределены методы doubleValue(), floatValue(), intValue(), longValue(). Большинство методов этого класса моделируют операции с вещественными числами. Они возвращают объект класса BigDecimal. Здесь буква х обозначает объект класса BigDecimal, буква n — целое значение типа int, буква r — способ округления, одну из восьми перечисленных выше констант: abs() — абсолютное значение объекта this; add(x) — операция this + х; divide(х, r) — операция this / х с округлением по способу r; divide(х, n, r) — операция this / х с изменением порядка и округлением по способу r; mах(х) — наибольшее из this и х; min(x) — наименьшее из this и х; movePointLeft(n) — сдвиг влево на n разрядов; movePointRight(n) — сдвиг вправо на n разрядов; multiply(х) — операция this * х; negate() — возврзщает объект с обратным знаком; scale() — возвращает порядок числз; setscaie(n) — устзнавливает новый порядок n ; setscaie(n, r) — устанавливает новый порядок п и округляет число при необходимости по способу r; signumo — знак числа, хранящегося в объекте; subtract(х) — операция this - х; toBiginteger() — округление числа, хранящегося в объекте; unscaiedvalue()—возвращает мантиссу числа. Листинг 4.4 показывает примеры использования этих методов, а рис. 4.5 — вывод результатов.
Рис. 4.5. Методы класса BigDecimal в программе BigDecimalTest Листинг 4.4. Методы класса BigDecimal В программе BigDecimalTest import java.math.*; class BigDecimalTest{ public static void main,( String [] args) { BigDecimal x = new BigDecimal("-12345.67890123456789"); BigDecimal у = new BigDecimal("345.7896e-4"); BigDecimal z = new BigDecimal(new Biglnteger("123456789"),8); System.out.println("|x| = " + x.abs()); System.out.println("x + у = " + x.add(y)); System.out.println("x / у = " + x.divide(y, BigDecimal.ROUND__DOWN)); System.out.println("х / у = " + x.divide(y, 6, BigDecimal.ROUND_HALF_EVEN)); System.out.println("max(x, y) = " + x.max(y)); System.out.println("min(x, y) = " + x.min(y)); System.out.println("x « 3 = " * x.movePointLeft(3)); System.out.println("x » 3 = " + x.mpvePQintRight(3)); System.out.println("x * у = " + x.multiply(y)); System.out.println("-x = " + x.negate()); System.out.println("scale of x = " + x.scale()); System.out.println("increase scale of x to 20 = " + x.setScale(20)); System.out.println("decrease scale of x to 10 = " + x.setScale (10, BigDecimal.ROUND_HALF__UP)) ; System.out.println("sign(x) = " + x.signum()); System.out.println("x - у = " + x.subtract(y)}; System.out.println("round x = " + x.toBiglnteger()); System.out.println("mantissa of x = " + x.unscaledValue()); System.out.println("mantissa of 0.1 =n= " + new BigDecimal(0.1).unscaledValue()); } } Приведем еще один пример. Напишем простенький калькулятор, выполняющий четыре арифметических действий с числами любой величины. Он работает из командной строки. Программа представлена в листинге 4.5, а примеры использования калькулятора — на рис. 4.6. Листинг 4.5. Простейший калькулятор import Java.math.*; class Calc{ public static void main(String[] args){ if (args.length < 3){ System.err.println("Usage: Java Calc operand operator operand"); return; } BigDecimal a = new BigDecimal(args[0]); BigDecimal b = new BigDecimal(args[2]); switch (args[l].charAt(0)){ case '+': System.out.println(a.add(b)); break; case '-': System.out.println(a.subtract(b)); break; case '*': System.out.println(a.multiply(b)); break; case '/': System.out.println(a.divide(b, BigDecimal.ROUND_HALF_EVEN)); break; default : System.out.println("Invalid operator"); } } } Почему символ умножения — звездочка — заключен на рис. 4.6 в кавычки? "Юниксоидам" это понятно, а для других дадим краткое пояснение.
Рис. 4.6. Результаты работы калькулятора Это особенность операционной системы, а не языка Java. Введенную с клавиатуры строку вначале просматривает командная оболочка (shell) операционной системы, а звездочка для нее — указание подставить на это место все имена файлов из текущего каталога. Оболочка сделает это, и интерпретатор Java получит от нее длинную строку, в которой вместо звездочки стоят имена файлов через пробел. Звездочка в кавычках понимается командной оболочкой как обычный символ. Командная оболочка снимает кавычки и передает интерпретатору Java то, что надо. Класс Class Класс Object, стоящий во главе иерархии классов Java, представляет все объекты, действующие в системе, является их общей оболочкой. Всякий объект можно считать экземпляром класса Object. Класс с именем class представляет характеристики класса, экземпляром которого является объект. Он хранит информацию о том, не является ли объект на самом деле интерфейсом, массивом или примитивным типом, каков суперкласс объекта, каково имя класса, какие в нем конструкторы, поля, методы и вложенные классы. В классе class нет конструкторов, экземпляр этого класса создается исполняющей системой Java во время загрузки класса и предоставляется методом getciass() класса object, например: String s = "Это строка"; Class с = s.getClass(); Статический метод forName(string class) возвращает объект класса class для класса, указанного в аргументе, например: Class cl = Class.forName("Java,lang.String"); Но этот способ создания объекта класса class считается устаревшим (deprecated). В новых версиях JDK для этой цели используется специальная конструкция — к имени класса через точку добавляется слово class: Class c2 = Java.lang.String.class; Логические методы isArray(), isIntetface(), isPrimitive() позволяют уточнить, не является ли объект массивом, интерфейсом или примитивным типом. Если объект ссылочного типа, то можно извлечь сведения о вложенных классах, конструкторах, методах и полях методами getoeciaredciasses(), getdeclaredConstructors(), getDeclaredMethods(), getDeclaredFields(), в виде массива классов, соответствейно, Class, Constructor, Method, Field. Последние три класса расположены в пакете java.lang.reflect и содержат сведения о конструкторах, полях и методах аналогично тому, как класс class хранит сведения о классах. Методы getClasses(), getConstructors(), getlnterfaces(), getMethods(), getFieids() возвращают такие же массивы, но не всех, а только открытых членов класса. Метод getsuperciass() возвращает суперкласс объекта ссылочного типа, getPackage() — пакет, getModifiers() — модификаторы класса В битовой форме. Модификаторы можно затем расшифровать методами класса Modifier из пакета Java.lang.reflect. Листинг 4.6 показывает применение этих методов, а рис. 4.7 — вывод результатов Листийс 4.6 tМетоды класса Class в программе ClassTest import java.lang.reflect.*; class ClassTest{ public static void main(String[] args)( Class с = null, c1 = null, c2 = null; Field[] fld = null; String s = "Some string"; с = s.getClass(); try{ cl = Class.forName("Java.lang.String"); // Старый стиль c2 = Java.lang.String.class; // Новый стиль if (!c1.isPrimitive()) fid = cl.getDeclaredFields(); // Все поля класса String }catch(Exception e){} System.out.println("Class c: " + c); System.out.println("Class cl: " + cl); System,out.println("Class c2: " + c2); System.out.printlnt"Superclass c: " + c.getSuperclass()); System.out.println("Package c: " + c.getPackageO); System.out.printlnf"Modifiers c: " + c.getModifiers()); for(int i = 0; i < fid.length; i++) System.out.println(fld[i]); } } Методы, возвращающие свойства классов, вызывают исключительные ситуации, требующие обработки. Поэтому в программу введен блок try{} catch() {}. Рассмотрение обработки исключительных ситуаций мы откладываем до главы 16.
Рис. 4.7. Методы класса Class в программе ClassTest Рубрика: Технология JAVA
О том как разработчики пьют кофе.
Сегодня ночью вернулся из Москвы, где я посетил сразу три конференции — SQA, PM Days и PHPconf. На конференции прозвучала масса интересных докладов, о которых наверняка еще не раз напишут, я же хочу поделиться некоторыми забавными наблюдениями. В перерывах между докладами все присутствующие могли выйти в холл, где их ожидали вкусные плюшки, молоко, чай и кофе. Для последнего на столах установили пять термосов. Разумеется для более чем двухсот участников конференции их было явно недостаточно и на каждой конференции эту проблему решали по своему, как умели.
Подробнее... |
Рубрика: Юмор
| Добавлено: 24.06.2008
Работаем с LINQ to XML.
Что же, попробуем раскрыть принципы работы этой новой технологии от Microsoft.
Подробнее... |
Рубрика: LINQ
| Добавлено: 24.06.2008
XmlSerializer - Assembly Leak без спроса.
В некоторых частях .NET Framework, таких как XmlSerializer, используется внутреннее динамическое создание кода.XmlSerializer создает временные файлы C#, компилирует результирующие файлы во временную сборку и затем загружает эту сборку в процесс. Такое создание кода тоже стоит сравнительно дорого, поэтому XmlSerializer размещает временные сборки в кэш, по одной на каждый тип. Это значит, что в следующий раз при создании кода XmlSerializer для класса Х не будет создаваться новая сборка, а будет использована сборка из кэша. Однако, не все так просто.
Подробнее... |
Рубрика: Сборки и развертывание
| Добавлено: 24.06.2008
Остальные статьи:
Реализация MVC в WPF. Александр Шер
ADO.NET Sync Services. Марат Бакиров
Рефакторинг JavaScript с применением Microsoft ASP.NET AJAX. Александр Шер
Архитектура приложений: интерфейс пользователя. Дмитрий Мартынов
Введение в Windows Workflow Foundation. Марат Бакиров
Создание расширяемых и удобных библиотек на платформе .NET. Особенности реализац...
Почему Ruby и Python не могут занять место стареющей Java
Использование пространств имен для организации JavaScript-кода
Создание сложных приложений в ExtJS
Google добавил интерфейс для AJAX-библиотек
Стивен Синофски о Windows 7
Несколько вещей об Ajax, которые должен знать веб-мастер
Model-View-Controller для JavaScript
Remix 2008: интернет меняет Microsoft
Планировщик задач на JavaScript
Построение систем автоматического протоколирования Си/Си++ кода |
Цитата дня (все,добавить): |
Realcoding.NET
© 2003-2008 |
Контакты |
Реклама на сайте
|