Добавлен вопрос со свободным ответом
добавлен 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)