![]() |
Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | |
|
JAVA
SE
При использовании методов класса String, изменяющих строку, создается новый измененный объект класса String. Сохранить изменения в объекте класса String можно только с применением оператора присваивания, т.е. установкой ссылки на этот новый объект. В следующем примере будет выведено последнее после присваивания значение str.
/* пример # 2: передача строки по ссылке: RefString.java */
package chapt07;
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 */
package chapt07;
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
package chapt07;
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
package chapt07;
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 */
package chapt07;
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 */
package chapt07;
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 */
package chapt07;
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 в файле.
Для создания объекта класса существует более десяти конструкторов. Ниже приведены наиболее употребляемые:
Дата публикования: 2015-01-23; Прочитано: 198 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!