Java

Все разработчики имеют дело со словами и фразами в некоторых частях кода. String — это тип данных, используемый в программировании для представления текста.

В Java есть три класса с именами String, StringBuilder и StringBuffer, где содержатся методы, написанные для операций над строками. Эти классы включены в пакет lang и импортируются в Java-код автоматически.

Здесь я расскажу подробнее об этих классах, а также о том, как и когда их использовать, чтобы облегчить себе работу со строками.

String

Строки в Java иммутабельны (не могут быть изменены). При изменении объекта String в Java каждый раз создается совершенно новый объект. В Java существует два способа объявить объект String, как это показано в примере ниже:

class StrEx1 {
  public static void main(String[] args) {
  String s1 = "This is a String"; // Объявлено с использованием строкового литерала
  String s2 = new String("This is another String"); // Объявлено с использованием оператора new
  }
}

Разница между этими двумя способами в том, что при использовании оператора new в памяти кучи каждый раз будет создаваться новый объект String. При использовании литерала объекта, если такой объект уже существует в куче, новый объект не появится, а ссылочная переменная будет указывать на существующий объект. При использовании строкового литерала объект String в Java сохраняется в так называемом пуле строк (String Pool). Он расположен внутри памяти кучи, что помогает Java Runtime сэкономить много места, даже если для создания объекта String при этом требуется больше времени. Так что, если вы хотите каждый раз создавать новый объект String, вам следует воспользоваться оператором new, а если вы хотите сберечь память кучи, тогда используйте строковый литерал.

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

Класс String также предоставляет доступ ко многим полезным методам для различных операций над строками. Вот некоторые из этих методов: substring(), charat(), length(), equals(), concat(), replace(), trim(), split(), toUpperCase() и toLowerCase(). Эти методы можно применять как по отдельности, так и в сочетании с другими методами класса String, чтобы манипулировать строками так, как нам того захочется.

class StrEx2 {
  public static void main(String args[]) {
        String s1 = "Hello World";
        String s2 = s1.substring(0,5).concat(" r2d2").toUpperCase();
        System.out.println(s2); // Результат: HELLO R2D2
    }
}

Здесь значение переменной s1 не изменяется.

StringBuilder

Класс StringBuilder представляет собой альтернативу классу String, поскольку создает мутабельный (изменяемый) набор символов. Класс StringBuilder, как и класс String, содержит набор методов для управления строковыми объектами.

class SbdEx1 {
 public static void main(String args[]) {
        StringBuilder sbd = new StringBuilder("Hello World");
        String s = sbd.replace(5,11,"").append(" r2d2").toString();
        System.out.println(sbd); // Результат: Hello r2d2
        System.out.println(s.toUpperCase()); //Результат: HELLO R2D2
    }
}

Классы StringBuilder и StringBuffer предоставляют важные методы, которых не предоставляет класс String, такие как insert(), delete() и reverse(). Если вы много раз совершаете какие-либо действия над строками в коде, вам следует использовать StringBuilder или StringBuffer, потому что они намного быстрее и потребляют меньше памяти, чем String. Например, если вы используете конкатенацию строк в цикле, то лучше применять StringBuilder.

class SbdEx2 {
 public static void main(String args[]){
        StringBuilder sbd = new StringBuilder("0");
        for (int i = 1; i < 100; i++) {
            sbd.append(", "+i);
        }
    }
}

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

StringBuffer

Как и класс StringBuilder, класс StringBuffer также создает изменяемый строковый объект. И StringBuffer содержит те же методы, что и StringBuilder. Таким образом, разница между ними в том, что класс StringBuffer —  потокобезопасный и синхронизированный: экземпляры класса StringBuffer могут совместно использоваться несколькими потоками. Для операций со строками в многопоточных средах стоит использовать StringBuffer.

class Test extends Thread  {  
  StringBuffer sbr;

    public Test() {
        sbr = new StringBuffer();
    }

    public String hello() {
        sbr.append("Hello World");
        return(sbr.toString());
    }
}

 public class SbrEx {  
    public static void main(String args[]) {
      Test thread1 = new Test(); 
      thread1.start(); 
      Test thread2 = new Test(); 
      thread2.start(); 
      System.out.println(thread1.hello());
      System.out.println(thread2.hello());
    }
}

Здесь несколько потоков обращаются к методу hello(), поэтому для обеспечения потокобезопасности необходимо применить StringBuffer.

Надеюсь, что вы все теперь разобрались со String, StringBuilder и StringBuffer. Спасибо, что прочитали!

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи: Manusha Chethiyawardhana, “String, StringBuilder, and StringBuffer Do You Know the Difference?”

Предыдущая статьяПочему нельзя разрешать поля GraphQL как конечные точки REST
Следующая статьяНавигация по настраиваемой доставке