Main > Java | Java labs > Java тестируем метод toString

Java тестируем метод toString

27.03.2012 15 comments » Views: 59,832

Сегодня поговорим о методе toString(). Этот метод служит для представления объекта в виде строки. Это требуется например если мы хотим вывести объект на экран.

Самое главное знать, что метод toString() есть у всех объектов и все объекты используют этот метод при работе со строками. По-умолчанию он состоит из двух составляющих разделенных собачкой. Эти составляющие: имя_класса_объекта и хэш_кода. Пример: java.lang.Integer;@24d200d8. Теперь посмотрим как это работает.

Для начала, давайте поиграемся с обычными переменными объектного типа и с массивами на их основе.

Вот тестовая программа:

Вот такой она дает результат:

Давайте теперь разберем, что же тут происходит.

  • Тест 1: Видим что все объектные типы прекрасно сами конвертируются в строку.
  • Тест 2: Пробуем вывести массив. Видим что выводится тип-объекта и его хеш-код.
  • Тест 3: Пробуем вызвать toString() самостоятельно. Видим что получаем тот же результат, что в тесте 2. А как же распечатать массив?
  • Тест 4: Пробуем использовать метод deepToString(Object[] a) класса Arrays.  Массив печатается.
  • Тест 5: Пробуем воспользоваться методом toString для двумерного массива. Результат тот же - тип-объекта и хеш-код.
  • Тест 6: Пробуем использовать метод deepToString(Object[] a) класса Arrays.  Двумерный массив печатается.
  • Тест 7: Пробуем использовать метод deepToString(Object[] a) класса Arrays для двумерного массива строк.  Массив печатается.
  • Тест 8: Пробуем использовать метод deepToString(Object[] a) класса Arrays для массива объявленого и сразу проинициализированного.  Массив печатается.

Делаем выводы: чтобы распечатать массив, нужно использовать метод класса Arrays.deepToString.

Прочитать про этот метод можно здесь Arrays.deepToString(). Так же в этом же руководстве советую обратить внимание на метод: deepEquals,  который позволяет сравнить два массива сравнивая так же их "внутренности".

Вернемся к методу toString() в наших объектах его можно переопределять, для получения желаемого результата. Рассмотрим такой пример:

Результат работы такой программы будет:

Разумеется, нам это не подходит. А мы бы хотели получить что-то вроде:

Добиться подобного результата не сложно, достаточно переопределить метод toString() в нашем классе User. Раз это не сложно, давайте сделаем это

И мы получаем именно то, что и хотели:

Как видите для того чтобы переопределить toString, необходимо просто его объявить в нашем классе и вернуть значение типа String, вот и вся магия. Директива @Override перед методом, необходима для того, чтобы по ошибке (если мы допустим ошибку) не перегрузить метод (overloading), а именно переопределить его (override). Она говорит компилятору: "Дорогой друг, наш программер не очень внимательный, поэтому проследи плиз, чтобы он нигде не протупил, и сделал именно переопределение метода"

В нашем примере, работу с календарем нужно было вынести в отдельный класс, но для сокращения кода я не стал этого делать и оставил все в методе getAge().

Вопросы для собеседования:

  1. Что будет выведено на экран:
  2. Что будет выведено на экран:
  3. Что будет выведено на экран:
  4. Что будет выведено на экран:
  5. Каким методом можно получить значения массива из вопроса 3, в виде String
  6. Есть такой класс:

    необходимо выводить значения arrayOfInt на печать через System.out.println, как вы это реализуете?

Ответы:

  1. Будет выведено:
  2. Будет выведено:

    а именно: класс-объекта@хэш-код-объекта
  3. Будет выведено:

    а именно: класс-объекта@хэш-код-объекта
  4. Будет выведено:

    Неожиданно? А как по мне вполне ожидаемо, char автоматически преобразовался в int, а потом в Integer, на этапе инициализации массива.
  5. Можно использовать метод deepToString(Array) класса Arrays
  6. Я переопределю  в классе, метод toString(), внутри метода напишу return Arrays.deepToString(arrayOfInt);Вот такой получится класс:

    В таком случае мы сможем распечатать значения таким способом:

    и получим такой результат:

Author: | Rating: 5/5 | Tags: , ,

15 comments.

Write a comment
  1. Oleg Reply
    08.12.2013 в 7:30 pm
    там int age а в User birhtYear
    • Vitaliy Orlov Reply
      09.12.2013 в 7:47 am
      Oleg, спасибо! Нашел наконец-то свою ошибку. Исправлено.
  2. alex Reply
    07.12.2013 в 4:31 pm
    небольшая неточность во фразе : "@Override перед методом, необходима для того, чтобы по ошибке (если мы допустим ошибку) не перегрузить метод (overloading), а именно переопределить его (override)" . Если допустить ошибку и не поставить директиву, то перегрузить не получится, ибо для перегрузки необходимо, что бы сигнатуры методов различались.Поправьте, если я не прав.
    • Vitaliy Orlov Reply
      09.12.2013 в 7:54 am
      Тут я, по всей видимости, имел ввиду, что можно ошибиться с параметрами метода и таким образом его перезагрузить (т.е. будет другая сигнатура). А если поставить @Override, то такое не прокатит. К сожалению сейчас не могу проверить. Если ошибаюсь, прошу меня исправить.
  3. Юрий Reply
    02.10.2013 в 8:01 pm
    "Вернемся к методу toString() в наших объектах его можно переопределять, для получения желаемого результата. Рассмотрим такой пример:"

    public class Main {
    public static void main(String[] args) {
    User user = new User("Эдуард", "Пупырышкин", 1990);
    System.out.println(user);
    }
    }

    class User {
    private String name;
    private String surname;
    private int age;
    User(String name, String surname, int birthYear)
    {
    this.name = name;
    this.surname = surname;
    this.birthYear = birthYear;
    }
    }
    ошибка в 11-й строке должно быть -
    private int birthYear;
    • Vitaliy Orlov Reply
      09.10.2013 в 7:31 am
      Вроде, так и есть, или я не смог найти проблему :)
      • Vitaliy Orlov Reply
        09.12.2013 в 7:55 am
        Нашел, исправлено! Юрий, спасибо за внимательность!
  4. Илья Reply
    30.01.2013 в 5:02 pm
    По поводу 4 вопроса.
    А как у вас такой код может компилироваться: Integer[] a = {'H','e','l','l','o'} ?? Никак не пойму, тут ведь нужно приведение типов..
    • Vitaliy Orlov Reply
      30.01.2013 в 8:53 pm
      Все верно, это не будет работать. Исправлено на:
      Integer[] a = {'H'+'e','l'+'l','o'+' ','w'+'o','r'+'l'+'d'};
  5. Vitaliy Orlov Reply
    10.01.2013 в 2:37 am
    Я тоже в свое время сталкивался с такой проблемой. Решение - вынести создание объекта Random за пределы цикла.
    --------------------
    import java.util.Date;
    import java.util.Random;


    public class Main {

    public static void main(String[] args) {

    Random generator = new Random( (new Date()).getTime());

    for (int i=1; i
  6. Stanton Reply
    09.01.2013 в 10:41 pm
    Спасибо. А с генератором случайных чисел не поможете? Нужно создать двухмерный массив из случайных чисел конкретного диапазона (например 1-9, важно чтобы 0 не генерировал). Нашёл где-то в сети генератор. Сам по себе он работает вроде нормально, но если при создании массива вызываю его внутри цикла, то он выдаёт почти всегда одно и тоже число.
    Вот такой генератор:
    public static void main(String[] args) {
    for (int i=1; i<= 20; i++){
    Random generator = new Random(newDate().getTime());
    System.out.println(generator.nextInt(8));
    }
    }
    Заранее спасибо.
  7. Vitaliy Orlov Reply
    06.01.2013 в 6:13 pm
    Здравствуйте, Stanton!

    Тут все довольно просто:

    1) метод toString(), есть у всех классов (а соответственно и объектов в Java), т.к. все классы наследуются от родительского класса Object, где этот метод и определен.

    2) при кастинге (преобразовании) любого объекта к типу String, метод toString() автоматически вызывается у всех объектов.

    Т.е. вот такой вызов:

    User u = new User();
    System.out.println( u );

    это эквивалент вызова:

    User u = new User();
    System.out.println( u.toString() );

    это преобразование за нас делает компилятор. Я так думаю, это сделано таким образом, только из соображений лаконичности. Т.е. грубо говоря, все программисты знают, о таком способе вызова и просто его используют, при необходимости вывести какую-то информацию об объекте в дружелюбном к пользователю формате.
  8. Stanton Reply
    06.01.2013 в 4:14 pm
    Здравствуйте, Виталий.
    Честно говоря я не совсем понял как этот toString() работает. В частности, тот пример с классом User, где Вы показываете как переопределять этот метод. Класс User, за исключением метода getAge(), состоит только лишь из конструктора и метода toString(). Далее в классе Main создаётся один объект класса User и посредством System.out.println() выводится на экран. Так вот я не пойму почему это всё работает, если сам метод toString() вообще не вызывается в классе Main? Не могли бы Вы это как-то подробнее разъяснить? Я новичок.
  9. Алексей Reply
    09.10.2012 в 7:47 am
    Не дурите голову :)) полчаса не верил 4-му пункту примера. И оказался прав, пока не проверил сам.

    Что будет выведено на экран:
    Integer[] a = {'H','e','l','l','o'};
    System.out.println(a);

    Будет выведено:
    [72, 101, 108, 108, 111]

    нет - совсем не это.
    Упрямый рантайм возвращает что то типа:
    [Ljava.lang.Integer;@45a877


    Как понимать? Верю тому что выдает бинарник а не символы сайта.
    • Vitaliy Orlov Reply
      09.10.2012 в 8:07 am
      Алексей, это опечатка в вопросе, я наверно пропустил Arrays.deepToString, т.е. должно было быть так:
       
      Integer[] a = {'H','e','l','l','o'};
      System.out.println(Arrays.deepToString(a));
       

      Уже поправил, спасибо! :D

Leave a Reply

Your email address will not be published. Required fields are marked *

Allowed HTML-tags: <a>, <code>, <i>, <em>, <strong>, <b>, <u>, <strike>