Добавлен вопрос со свободным ответом

добавлен Drag&Drop

Добавлен вопрос на соответствие

При запуске приложения происходит объявление объекта unique c применением анонимного класса, в котором переопределяется метод addNewType(). Вызов данного метода на объектеunique приводит к вызову версии метода из анонимного класса, который компилируется в объектный модуль с именем
RunnerAnonym$1. Процесс создания второго объекта с анонимным типом применяется в программировании значительно чаще, особенно при реализации классов-адаптеров и реализации интерфейсов в блоках прослушивания. В этом же объявлении продемонстрирована возможность объявления в анонимном классе полей и методов, которые доступны объекту вне этого класса.

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

/* пример # 16 : анонимный класс в перечислении : EnumRunner.java */

package chapt06;

 

enum Shape {

RECTANGLE, SQUARE,

TRIANGLE {// анонимный класс

public double getSquare() {// версия для TRIANGLE

return a*b/2;

}

};

public double a, b;

 

public void setShape(double a, double b){

if ((a<=0 || b<=0) || a!=b && this==SQUARE)

throw new IllegalArgumentException();

Else

this.a = a;

this.b = b;

}

public double getSquare(){// версия для RECTANGLE и SQUARE return a * b;

}

public String getParameters() {

return "a=" + a + ", b=" + b;

}

}

public class EnumRunner {

public static void main(String[] args) {

int i = 4;

for (Shape f : Shape.values()) {

f.setShape(3, i--);

System.out.println(f.name()+"-> " + f.getParameters()

+ " площадь= " + f.getSquare());

}

}

}

В результате будет выведено:

RECTANGLE-> a=3.0, b=4.0 площадь= 12.0

SQUARE-> a=3.0, b=3.0 площадь= 9.0

TRIANGLE-> a=3.0, b=2.0 площадь= 3.0

Объектный модуль для такого анонимного класса будет скомпилирован
с именем Shape$1.

Задания к главе 6

Вариант А

1. Создать класс Notepad (записная книжка) с внутренним классом или классами, с помощью объектов которого могут храниться несколько записей на одну дату.

2. Создать класс Payment (покупка) с внутренним классом, с помощью объектов которого можно сформировать покупку из нескольких товаров.

3. Создать класс Account (счет) с внутренним классом, с помощью объектов которого можно хранить информацию обо всех операциях со счетом (снятие, платежи, поступления).

4. Создать класс Зачетная Книжка с внутренним классом, с помощью объектов которого можно хранить информацию о сессиях, зачетах, экзаменах.

5. Создать класс Department (отдел фирмы) с внутренним классом, с помощью объектов которого можно хранить информацию обо всех должностях отдела и обо всех сотрудниках, когда-либо занимавших конкретную должность.

6. Создать класс Catalog (каталог) с внутренним классом, с помощью объектов которого можно хранить информацию об истории выдач книги читателям.

7. Создать класс СССР с внутренним классом, с помощью объектов которого можно хранить информацию об истории изменения территориального деления на области и республики.

8. Создать класс City (город) с внутренним классом, с помощью объектов которого можно хранить информацию о проспектах, улицах, площадях.

9. Создать класс CD (mp3-диск) с внутренним классом, с помощью объек­тов которого можно хранить информацию о каталогах, подкаталогах
и записях.

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

11. Создать класс Художественная Выставка с внутренним классом,
с помощью объектов которого можно хранить информацию о картинах, авторах и времени проведения выставок.

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

13. Создать классShop(магазин) с внутренним классом, с помощью объектов которого можно хранить информацию об отделах, товарах и услуг.

14. Создать класс Cправочная Cлужба Oбщественного Tранспорта
с внутренним классом, с помощью объектов которого можно хранить информацию о времени, линиях маршрутов и стоимости проезда.

15. Создать класс Computer (компьютер)с внутренним классом, с помощью объектов которого можно хранить информацию об операционной системе, процессоре и оперативной памяти.

16. Создать класс Park (парк) с внутренним классом, с помощью объектов которого можно хранить информацию об аттракционах, времени их работы и стоимости.

17. Создать класс Cinema (кино) с внутренним классом, с помощью объектов которого можно хранить информацию об адресах кинотеатров, фильмах и времени сеансов.

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

19. Создать класс Фильмс внутренним классом, с помощью объектов которого можно хранить информацию о продолжительности, жанре и режиссерах фильма.

Вариант B

В заданиях варианта В главы 4 в одном из классов для сокрытия реализации использовать внутренний или вложенный класс. Для определения уникального поведения объекта одного из классов использовать анонимные классы.

Вариант C

Реализовать абстрактные классы или интерфейсы, а также наследование и полиморфизм для следующих классов:

1. Абстрактный класс Книга(Шифр, Автор, Название, Год, издательство). Подклассы Справочник и Энциклопедия.

2. interface Абитуриент ß abstract class Студент ß class Студент-Заочник.

3. interface Сотрудник ß class Инженер ß class Руководитель.

4. interface Здание ß abstract class Общественное Здание ß class Театр.

5. interface Mobile ß abstract class Siemens Mobile ß class Model.

6. interface Корабль ß abstract class Военный Корабль ß class Авианосец.

7. interface Врач ß class Хирург ß class Нейрохирург.

8. interface Корабль ß class Грузовой Корабль ß class Танкер.

9. interface Мебель ß abstract class Шкаф ß class Книжный Шкаф.

10. interface Фильм ß class Отечественный Фильм ß class Комедия.

11. interface Ткань ß abstract class Одежда ß class Костюм.

12. interface Техника ß abstract class Плеер ß class Видеоплеер.

13. interface Транспортное Средство ß abstract class Общественный Транспорт ß class Трамвай.

14. interface Устройство Печати ß class Принтер ß class Лазерный Принтер.

15. interface Бумага ß abstract class Тетрадь ß class Тетрадь Для Рисования.

16. interface Источник Света ß class Лампа ß class Настольная Лампа.

Тестовые задания к главе 6

Вопрос 6.1.

Какие из фрагментов кода скомпилируются без ошибки?

1)

import java.util.*;
package First;
class My{/* тело класса*/}

2)

package mypack;
import java.util.*;
public class First{/* тело класса*/}

3)

/*комментарий */
package first;
import java.util.*;
class First{/* тело класса*/}

Вопрос 6.2.

Какие определения интерфейса MyInterface являются корректными?

1) interface MyInterface{
public int result(int i){return(i++);}}

2) interface MyInterface{
intresult(int i);}

3) public interface MyInterface{
public static int result(int i);}

4) public interface MyInterface{

classMyClass{}}

5) public interface MyInterface{
public final static int i;

public abstract int result(int i);}

Вопрос 6.3.

Какие из объявлений корректны, если

class Owner{

class Inner{

} }

1) new Owner.Inner();

2) Owner.new Inner();

3) new Owner.new Inner();

4) new Owner().new Inner();

5) Owner.Inner();

6) Owner().Inner().

Вопрос 6.4.

Что будет выведено в результате компиляции и выполнения следующего кода?

abstract class Abstract {

abstract Abstract meth();

}

class Owner {

Abstract meth() {

class Inner extends Abstract {

Abstract meth() {

System.out.print("inner ");

return new Inner();

} }

return new Inner();

}

}

public abstract class Quest4 extends Abstract{

public static void main(String a[]) {

Owner ob = new Owner();

Abstract abs = ob.meth();

abs.meth();

}

}

1) inner;

2) inner inner;

3) inner inner inner;

4) ошибка компиляции;

5) ошибка времени выполнения.

Вопрос 6.5.

class Quest5 { char A; // 1 void A() {} // 2 class A {} // 3

}

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

1) 1;

2) 2;

3) 3;

4) компиляция без ошибок.

 


Часть 2.
ИСПОЛЬЗОВАНИЕ
КЛАССОВ И БИБЛИОТЕК

Во второй части книги рассмотрены вопросы использования классов Java при работе со строками и файлами, для хранения объектов, при создании пользовательских интерфейсов, многопоточное и сетевое программирование с использованием классов из пакетов java.util, java.text, java.net, java.io, java.awt, javax.swing и др.

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

Глава 7

ОБРАБОТКА СТРОК

Строка в языке Java – это основной носитель текстовой информации. Это не массив символов типа char, а объект соответствующего класса. Системная библиотека Java содержит классы String,StringBuilder и StringBuffer, поддерживающие работу со строками и определенные в пакете java.lang, подключаемом автоматически. Эти классы объявлены как final, что означает невозможность создания собственных порожденных классов со свойствами строки. Кроме того, для форматирования и обработки строк применяются классы Formatter, Pattern, Matcher и другие.

Класс String

Каждая строка, создаваемая с помощью оператора new или с помощью литерала (заключённая в двойные апострофы), является объектом класса String. Особенностью объекта класса String является то, что его значение не может быть изменено после создания объекта при помощи какого-либо метода класса, так как любое изменение строки приводит к созданию нового объекта. При этом ссылку на объект класса String можно изменить так, чтобы она указывала на другой объект и тем самым на другое значение.

Класс Stringподдерживает несколько конструкторов, например: String(),String(String str), String(byte asciichar[]), String(char[] unicodechar), String(StringBuffer sbuf), String(StringBuilder sbuild)и др. Эти конструкторы используются для создания объектов класса String на основе инициализации значениями из массива типа char, byte и др. Например, при вызове конструктора

new String(str.getChars(), "UTF-8"),

где str – строка в формате Unicode, можно установить необходимый алфавит с помощью региональной кодировки в качестве второго параметра конструктора, в данном случае кириллицу. Когда Java встречает литерал, заключенный в двойные кавычки, автоматически создается объект типа String, на который можно установить ссылку. Таким образом, объект класса String можно создать, присвоив ссылке на класс значение существующего литерала, или с помощью оператора new и конструктора, например:

String s1 = "sun.com";

String s2 = new String("sun.com");

Класс String содержит следующие методы для работы со строками:

String concat(String s) или “+” – слияние строк;

boolean equals(Object ob)и equalsIgnoreCase(String s) –сравнение строк с учетом и без учета регистра соответственно;

int compareTo(String s) и compareToIgnoreCase(String s) –лексикографическое сравнение строк с учетом и без учета регистра. Метод осуществляет вычитание кодов символов вызывающей и передаваемой в метод строк и возвращает целое значение. Метод возвращает значение нуль в случае, когда equals() возвращает значение true;

boolean contentEquals(StringBuffer ob) –сравнение строки
и содержимого объекта типа StringBuffer;

String substring(int n, int m) –извлечение из строки подстроки длины m-n, начиная с позиции n. Нумерация символов в строке начинается с нуля;

String substring(int n) –извлечение из строки подстроки, начиная с позиции n;

int length()– определение длины строки;

int indexOf(char ch)– определение позиции символа в строке;

static String valueOf(значение) – преобразование переменной базового типа к строке;

String toUpperCase()/toLowerCase()– преобразование всех символов вызывающей строки в верхний/нижний регистр;

String replace(char с1, char с2) – замена в строке всех вхождений первого символа вторым символом;

String intern() – заносит строку в “пул” литералов и возвращает ее объектную ссылку;

String trim() – удаление всех пробелов в начале и конце строки;

char charAt(int position) – возвращение символа из указанной позиции (нумерация с нуля);

boolean isEmpty() – возвращает true, если длина строки равна 0;

byte[] getBytes(), getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) – извлечение символов строки в массив байт или символов;

static String format(String format, Object... args), format(Locale l, String format, Object... args)– генерирует форматированную строку, полученную с использованием формата, интернационализации и др.;

String[] split(String regex), split(String regex, int limit) – поиск вхождения в строку заданного регулярного выражения (разделителя) и деление исходной строки в соответствии с этим на массив строк.

Во всех случаях вызова методов, изменяющих строку, создается новый объект типа String.

В следующем примере массив символов и целое число преобразуются в объекты типа Stringс использованием методов этого класса.

/* пример # 1 : использование методов: DemoString.java */

packagechapt07;

public class DemoString {

static int i;

 

public static void main(String[] args) {

char s[] = { 'J', 'a', 'v', 'a' }; // массив

// комментарий содержит результат выполнения кода

String str = new String(s); // str="Java"

if (!str.isEmpty()) {

i = str.length(); // i=4

str = str.toUpperCase(); // str="JAVA"

String num = String.valueOf(6); // num="6"

num = str.concat("-" + num); // num="JAVA-6"

char ch = str.charAt(2); // ch='V'

i = str.lastIndexOf('A'); // i=3 (-1 если нет)

num = num.replace("6", "SE"); // num="JAVA-SE"

str.substring(0, 4).toLowerCase(); // java

str = num + "-6";// str=”JAVA-SE-6”

String[] arr = str.split("-");

for (String ss : arr)

System.out.println(ss);

} else{ System.out.println("String is empty!");

}

}

}

В результате будет выведен массив строк:

JAVA

SE

При использовании методов класса String, изменяющих строку, создается новый измененный объект класса String. Сохранить изменения в объекте класса String можно только с применением оператора присваивания, т.е. установкой ссылки на этот новый объект. В следующем примере будет выведено последнее после присваивания значение str.

/* пример # 2 : передача строки по ссылке: RefString.java */

packagechapt07;

public class RefString {

public static void changeStr(String s) {

s.concat(" Microsystems");// создается новая строка

}

public static void main(String[] args) {

String str = new String("Sun");

changeStr(str);

System.out.println(str);

}

}

В результате будет выведена строка:

Sun

Так как объект был передан по ссылке, то любое изменение объекта в методе должно сохраняться и для исходного объекта, так как обе ссылки равноправны. Этого не происходит по той причине, что вызов метода concat(String s) приводит к созданию нового объекта.

В следующем примере рассмотрены особенности хранения и идентификации объектов на примере вызова метода equals(), сравнивающего строку String с указанным объектом и метода hashCode(), который вычисляет хэш-код объекта.

/* пример # 3 : сравнение ссылок и объектов: EqualStrings.java */

packagechapt07;

public class EqualStrings {

public static void main(String[] args) {

String s1 = "Java";

String s2 = "Java";

String s3 = new String("Java");

System.out.println(s1 + "==" + s2 +

" : " + (s1 == s2)); // true

System.out.println(s1 + "==" + s3 +

" : " + (s1 == s3)); // false

System.out.println(s1 + " equals " + s2 + " : "

+ s1.equals(s2)); // true

System.out.println(s1 + " equals " + s3 + " : "

+ s1.equals(s3)); // true

System.out.println(s1.hashCode());

System.out.println(s2.hashCode());

System.out.println(s3.hashCode());

}

}

В результате, например, будет выведено:

Java==Java : true

Java==Java : false

Java equals Java : true

Java equals Java : true

Несмотря на то, что одинаковые по значению строковые объекты расположены в различных участках памяти, значения их хэш-кодов совпадают.

Т.к. в Java все ссылки хранятся в стеке, а объекты – в куче, то при создании объекта s2 сначала создается ссылка, а затем этой ссылке устанавливается в соответствие объект. В данной ситуации s2 ассоциируется с уже существующим литералом, так как объект s1 уже сделал ссылку на этот литерал. При создании s3 происходит вызов конструктора, то есть выделение памяти происходит раньше инициализации, и в этом случае в куче создается новый объект.

Существует возможность сэкономить память и переопределить ссылку с объекта на литерал при помощи вызова метода intern().

// пример # 4 : применение intern() : DemoIntern.java

packagechapt07;

public class DemoIntern {

public static void main(String[] args) {

String s1 = "Java"; // литерал и ссылка на него

String s2 = new String("Java");

System.out.println(s1 == s2); // false

s2 = s2.intern();

System.out.println(s1 == s2); // true

}

}

В данной ситуации ссылка s1 инициализируется литералом, обладающим всеми свойствами объекта вплоть до вызова методов. Вызов метода intern() организует поиск соответствующего значению объекта s2литерала и при положительном результате возвращает ссылку на найденный литерал, а при отрицательном – заносит значение в пул и возвращает ссылку на него.

Ниже рассмотрена сортировка массива строк методом выбора.

// пример # 5 : сортировка: SortArray.java

packagechapt07;

public class SortArray {

public static void main(String[] args) {

String a[] = {" Alena", "Alice ", " alina",

" albina", " Anastasya", " ALLA ", "AnnA "};

for(int j = 0; j < a.length; j++)

a[j] = a[j].trim().toLowerCase();

for(int j = 0; j < a.length - 1; j++)

for(int i = j + 1; i < a.length; i++)

if(a[i].compareTo(a[j]) < 0) {

String temp = a[j];

a[j] = a[i];

a[i] = temp;

}

int i = -1;

while(++i < a.length)

System.out.print(a[i] + " ");

}

}

Вызов метода trim() обеспечивает удаление всех начальных и конечных символов пробелов. Метод compareTo() выполняет лексикографическое сравнение строк между собой по правилам Unicode.

Классы StringBuilder и StringBuffer

Классы StringBuilder и StringBuffer являются “близнецами”
и по своему предназначению близки к классу String, но, в отличие от последнего, содержимое и размеры объектов классовStringBuilder
и StringBuffer можно изменять.

Основным и единственным отличием StringBuilder от StringBuffer является потокобезопасность последнего. В версии 1.5.0 был добавлен непотокобезопасный (следовательно, более быстрый в обработке) класс StringBuilder, который следует применять, если не существует вероятности использования объекта в конкурирующих потоках.

С помощью соответствующих методов и конструкторов объекты классов StringBuffer,StringBuilder и String можно преобразовывать друг в друга. Конструктор класса StringBuffer (также как и StringBuilder) может принимать в качестве параметра объект String или неотрицательный размер буфера. Объекты этого класса можно преобразовать в объект класса String методом toString()или с помощью конструктора класса String.

Следует обратить внимание на следующие методы:

void setLength(int n)– установка размера буфера;

void ensureCapacity(int minimum) – установка гарантированного минимального размера буфера;

int capacity() – возвращение текущего размера буфера;

StringBuffer append(параметры)– добавление к содержимому объекта строкового представления аргумента, который может быть символом, значением базового типа, массивом и строкой;

StringBuffer insert(параметры) – вставка символа, объекта или строки в указанную позицию;

StringBuffer deleteCharAt(int index) – удаление символа;

StringBuffer delete(int start, int end) – удаление подстроки;

StringBuffer reverse() – обращение содержимого объекта.

В классе присутствуют также методы, аналогичные методам класса String, такие как replace(), substring(), charAt(), length(), getChars(), indexOf()и др.

/* пример # 6 : свойства объекта StringBuffer: DemoStringBuffer.java */

packagechapt07;

public class DemoStringBuffer {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer();

System.out.println("длина ->" + sb.length());

System.out.println("размер ->" + sb.capacity());

// sb = "Java"; // ошибка, только для класса String

sb.append("Java");

System.out.println("строка ->" + sb);

System.out.println("длина ->" + sb.length());

System.out.println("размер ->" + sb.capacity());

System.out.println("реверс ->" + sb.reverse());

}

}

Результатом выполнения данного кода будет:

длина ->0

размер ->16

строка ->Java

длина ->4

размер ->16

реверс ->avaJ

При создании объекта StringBuffer конструктор по умолчанию автоматически резервирует некоторый объем памяти (16 символов), что в дальней­шем позволяет быстро менять содержимое объекта, оставаясь в границах участка памяти, выделенного под объект. Размер резервируемой памяти при необходимости можно указывать в конструкторе. Если длина строки StringBufferпосле изменения превышает его размер, то ёмкость объекта автоматически увеличивается, оставляя при этом резерв для дальнейших изменений. С помощью метода reverse() можно быстро изменить порядок символов в объекте.

Если метод, вызываемый объектом StringBuffer, производит измене­ния в его содержимом, то это не приводит к созданию нового объекта, как
в случае объекта String, а изменяет текущий объект StringBuffer.

/* пример # 7 : изменение объекта StringBuffer: RefStringBuffer.java */

packagechapt07;

public class RefStringBuffer {

public static void changeStr(StringBuffer s) {

s.append(" Microsystems");

}

public static void main(String[] args) {

StringBuffer str = new StringBuffer("Sun");

changeStr(str);

System.out.println(str);

}

}

В результате выполнения этого кода будет выведена строка:

Sun Microsystems

ОбъектStringBuffer передан в метод changeStr() по ссылке, поэтому все изменения объекта сохраняются и для вызывающего метода.

Для класса StringBuffer не переопределены методы equals() и
hashCode(), т.е. сравнить содержимое двух объектов невозможно, к тому же хэш-коды всех объектов этого типа вычисляются так же, как и для класса
Object.

/*пример # 8 : сравнение объектов StringBuffer и их хэш-кодов:

EqualsStringBuffer.java */

packagechapt07;

public class EqualsStringBuffer {

public static void main(String[] args) {

StringBuffer sb1 = new StringBuffer("Sun");

StringBuffer sb2 = new StringBuffer("Sun");

System.out.print(sb1.equals(sb2));

System.out.print(sb1.hashCode() ==

sb2.hashCode());

}

}

Результатом выполнения данной программы будет дважды выведенное значение false.

Форматирование строк

Для создания форматированного текстового вывода предназначен класс java.util.Formatter. Этот класс обеспечивает преобразование формата, позволяющее выводить числа, строки, время и даты в любом необходимом разработчику виде.

В классе Formatter объявлен метод format(), который преобразует переданные в него параметры в строку заданного формата и сохраняет в объекте типа Formatter. Аналогичный метод объявлен у классов PrintStream и PrintWriter. Кроме того, у этих классов объявлен метод printf() с парамет­рами идентичными параметрам метода format(), который осуществ­ляет форматированный вывод в поток, тогда как метод format() сохраняет изменения в объекте типа Formatter. Таким образом, метод printf() автоматически ис­пользует возможности класса Fomatter и подобен функции printf() языка С.

Класс Formatter преобразует двоичную форму представления данных
в форматированный текст. Он сохраняет форматированный текст в буфере, содержимое которого можно получить в любой момент. Можно предоставить классу Formatter автоматическую поддержку этого буфера либо задать его явно при создании объекта. Существует возможность сохранения буфера класса Formatter в файле.

Для создания объекта класса существует более десяти конструкторов. Ниже приведены наиболее употребляемые:

Formatter()

Formatter(Appendable buf)