Иллюстрированный самоучитель по Java

         

Числовые классы


В каждом из шести числовых классов-оболочек есть статические методы преобразования строки символов типа

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.


Класс Big Decimal


Класс

BigDecimal

расположен В пакете

java.math

.

Каждый объект этого класса хранит два целочисленных значения: мантиссу вещественного числа в виде объекта класса

Biglnteger

, и неотрицательный десятичный порядок числа типа

int

.

Например, для числа 76.34862 будет храниться мантисса 7 634 862 в объекте класса

Biglnteger

, и порядок 5 как целое число типа

int

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

integer.MAX_VALUE

. Результат операции над объектами класса

BigDecimal

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

ROUND_CEILING

— округление в сторону большего целого;

ROUND_DOWN

— округление к нулю, к меньшему по модулю целому значению;

ROUND_FLOOR

— округление к меньшему целому;

ROUND_HALF_DOWN

— округление к ближайшему целому, среднее значение округляется к меньшему целому;

ROUND_HALF_EVEN

— округление к ближайшему целому, среднее значение округляется к четному числу;

ROOND_HALF_UP

— округление к ближайшему целому, среднее значение округляется к большему целому;

ROUND_UNNECESSARY

— предполагается, что результат будет целым, и округление не понадобится; 

ROUND_UP

— округление от нуля, к большему по модулю целому значению.

В классе

BigDecimal

четыре конструктора:

BigDecimal (Biglnteger bi) —

объект будет хранить большое целое

bi,

порядок равен нулю;

BigDecimal (Biglnteger mantissa, int scale)

— задается мантиса

mantissa

и неотрицательный порядок

scale

объекта; если порядок

scale

отрицателен, возникает исключительная ситуация;

BigDecimal (double d)

— объект будет содержать вещественное число удвоенной точности

d

; если значение

d

бесконечно или

NaN

, то возникает исключительная ситуация;

BigDecimal (String val)

число задается строкой символов

val

, которая должна содержать запись числа по правилам языка Java.

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


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 то, что надо.


Класс Biglnteger


Все примитивные целые типы имеют ограниченный диапазон значений. В целочисленной арифметике Java нет переполнения, целые числа приводятся по модулю, равному диапазону значений.

Для того чтобы было можно производить целочисленные вычисления с любой разрядностью, в состав Java API введен класс

Biglnteger

, хранящийся в пакете

java.math

. Этот класс расширяет класс

Number

, следовательно, в нем переопределены методы

doubleValue(), floatValue(), intValue(), longValue()

. Методы

byteVaiue()

и

shortvalue()

не переопределены, а прямо наследуются от класса

Number

.

Действия с объектами класса

Biglnteger

не приводят ни к переполнению, ни к приведению по модулю. Если результат операции велик, то число разрядов просто увеличивается. Числа хранятся в двоичной форме с дополнительным кодом.

Перед выполнением операции числа выравниваются по длине распространением знакового разряда.

Шесть конструкторов класса создают объект класса

BigDecimai

из строки символов (знака числа и цифр) или из массива байтов.

Две константы —

ZERO

и

ONE

— моделируют нуль и единицу в операциях с объектами класса

Biglnteger

.

Метод

toByteArray()

преобразует объект в массив байтов.

Большинство методов класса

Biglnteger

моделируют целочисленные операции и функции, возвращая объект класса

Biglnteger

:

abs()

— возвращает объект, содержащий абсолютное значение числа, хранящегося в данном объекте

this

;

add(x)

— операция

this + х

and(x)

— операция

this & х

;

andNot(x)

— операция

this & (~х)

;

divide (x)

— операция

this / х

divideAndRemainder(х)

— возвращает массив из двух объектов класса

Biglnteger

, содержащих частное и остаток от деления

this

на

х

;

gcd(x)

— наибольший общий делитель, абсолютных, значений объекта

this

и аргумента

х

;

mах(х)

— наибольшее из значений объекта

this

и аргумента

х

;

min(x)

— наименьшее из значений объекта

this

и аргумента

х

;

mod(x)

— остаток от деления объекта


this

на аргумент метода

х

;

modinverse(x)

— остаток от деления числа, обратного объекту

this

, на аргумент

х

;

modPow(n, m)

— остаток от деления объекта

this

, возведенного в степень

n

, на

m

;

multiply (х)

—операция

this * х

;

negate()

— перемена знака числа, хранящегося в объекте;

not()

— операция

~this

;

оr(х)

— операция

this | х

;

pow(n)

— операция возведения числа, хранящегося в объекте, в степень

n

;

remainder(х)

—операция

this % х

;

shiftLeft (n)



операция

this « n

;

shiftRight (n)

— операция this » n;

signum()

— функция

sign (x)

;

subtract (x)

— операция

this - x

;

xor(x)

— операция

this ^ x

.

В листинге 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

.


Класс 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, не выражающихся одним символом.

Множество статических логических методов проверяют различные характеристики символа, переданного в качестве аргумента метода:

isDef ined()

— выясняет, определен ли символ в кодировке Unicode; 

isDigit()

— проверяет, является ли символ цифрой Unicode;

isidentifierignorable()

— выясняет, нельзя ли использовать символ в идентификаторах;

isisocontroi()

— определяет, является ли символ управляющим;

isJavaidentifierPart()

— выясняет, можно ли использовать символ в идентификаторах;

isjavaidentifierstart()

— определяет, может ли символ начинать идентификатор;

isLetter()

— проверяет, является ли символ буквой Java;

IsLetterOrDigit()

— Проверяет, является ли символ буквой или цифрой Unicode;

isLowerCase()

— определяет, записан ли символ в нижнем регистре; 

isSpaceChar()

— выясняет, является ли символ пробелом в смысле Unicode; 

isTitieCase()

— проверяет, является ли символ титульным;

isUnicodeldentifierPart()

— выясняет, можно ли использовать символ в именах Unicode;

isunicodeidentifierstart()

— проверяет, является ли символ буквой Unicode; 


isUpperCase()

— проверяет, записан ли символ в верхнем регистре; 

isWhitespace()

— выясняет, является ли символ пробельным.

Точные диапазоны управляющих символов, понятия верхнего и нижнего регистра, титульного символа, пробельных символов, лучше всего посмотреть по документации 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

Вместе с классами-оболочками удобно рассмотреть два класса для работы со сколь угодно большими числами.


Класс 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