Java тестируем метод toString
Сегодня поговорим о методе toString(). Этот метод служит для представления объекта в виде строки. Это требуется например если мы хотим вывести объект на экран.
Самое главное знать, что метод toString() есть у всех объектов и все объекты используют этот метод при работе со строками. По-умолчанию он состоит из двух составляющих разделенных собачкой. Эти составляющие: имя_класса_объекта и хэш_кода. Пример: java.lang.Integer;@24d200d8. Теперь посмотрим как это работает.
Для начала, давайте поиграемся с обычными переменными объектного типа и с массивами на их основе.
Вот тестовая программа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import java.util.Arrays; public class Main { public static void main(String[] args) { // Test 1 Integer a = 1; // Test 2, Test 3, Test 4 Integer [] b = new Integer [3]; b[0] = 1; b[1] = 1; b[2] = 1; // Test 5, Test 6 Integer [][] c = new Integer [2][3]; c[0][0] = 1; c[0][1] = 2; c[0][2] = 3; c[1][0] = 4; c[1][1] = 5; c[1][2] = 6; // Test 7 String [][] d = new String [2][3]; d[0][0] = "1"; d[0][1] = "2"; d[0][2] = "3"; d[1][0] = "4"; d[1][1] = "5"; d[1][2] = "6"; // Test 8 String[][] e = { {"X", "O", "O"}, {"O", "X", "X"}, {"X", "O", "X"}}; System.out.println("Test 1 | a"); System.out.println(a); System.out.println("\nTest 2 | b[]"); System.out.println(b); System.out.println("\nTest 3 | b[].toString"); System.out.println(b.toString()); System.out.println("\nTest 4 | Arrays.deepToString(b[])"); System.out.println(Arrays.deepToString(b)); System.out.println("\nTest 5 | c[][]"); System.out.println(c); System.out.println("\nTest 6 | Arrays.deepTostring(c[][])"); System.out.println(Arrays.deepToString(c)); System.out.println("\nTest 7 | Arrays.deepTostring(d[][])"); System.out.println(Arrays.deepToString(d)); System.out.println("\nTest 8 | Arrays.deepTostring(e[][])"); System.out.println(Arrays.deepToString(e)); } } |
Вот такой она дает результат:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Test 1 | a 1 Test 2 | b[] [Ljava.lang.Integer;@24d200d8 Test 3 | b[].toString [Ljava.lang.Integer;@24d200d8 Test 4 | Arrays.deepToString(b[]) [1, 1, 1] Test 5 | c[][] [[Ljava.lang.Integer;@573577ca Test 6 | Arrays.deepTostring(c[][]) [[1, 2, 3], [4, 5, 6]] Test 7 | Arrays.deepTostring(d[][]) [[1, 2, 3], [4, 5, 6]] Test 8 | Arrays.deepTostring(e[][]) [[X, O, O], [O, X, X], [X, O, X]] |
Давайте теперь разберем, что же тут происходит.
- Тест 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() в наших объектах его можно переопределять, для получения желаемого результата. Рассмотрим такой пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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 birthYear; User(String name, String surname, int birthYear) { this.name = name; this.surname = surname; this.birthYear = birthYear; } } |
Результат работы такой программы будет:
1 2 3 |
User@4d24bd93 |
Разумеется, нам это не подходит. А мы бы хотели получить что-то вроде:
1 2 3 |
Эдуард Пупырышкин, 22 года |
Добиться подобного результата не сложно, достаточно переопределить метод toString() в нашем классе User. Раз это не сложно, давайте сделаем это
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
import java.util.Calendar; import java.util.TimeZone; import java.util.Locale; import java.util.Date; 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 birthYear; User(String name, String surname, int birthYear) { this.name = name; this.surname = surname; this.birthYear = birthYear; } @Override public String toString() { return this.name+" "+this.surname+", "+getAge()+" года"; } private int getAge() { Calendar calendar = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()); calendar.setTime(new Date()); int currentYear = calendar.get(Calendar.YEAR); return currentYear - birthYear; } } |
И мы получаем именно то, что и хотели:
1 2 3 |
Эдуард Пупырышкин, 22 года |
Как видите для того чтобы переопределить toString, необходимо просто его объявить в нашем классе и вернуть значение типа String, вот и вся магия. Директива @Override перед методом, необходима для того, чтобы по ошибке (если мы допустим ошибку) не перегрузить метод (overloading), а именно переопределить его (override). Она говорит компилятору: "Дорогой друг, наш программер не очень внимательный, поэтому проследи плиз, чтобы он нигде не протупил, и сделал именно переопределение метода"
В нашем примере, работу с календарем нужно было вынести в отдельный класс, но для сокращения кода я не стал этого делать и оставил все в методе getAge().
Вопросы для собеседования:
- Что будет выведено на экран:
1234Integer d = 1;System.out.println(d); - Что будет выведено на экран:
1234Integer[] c = {1};System.out.println(c); - Что будет выведено на экран:
1234String[] b = {"H","e","l","l","o"};System.out.println(b); - Что будет выведено на экран:
1234Integer[] a = {'H'+'e','l'+'l','o'+' ','w'+'o','r'+'l'+'d'};System.out.println(Arrays.deepToString(a)); - Каким методом можно получить значения массива из вопроса 3, в виде String
- Есть такой класс:
123456class ArrayOfInteger{private Integer[][] arrayOfInt= {{1,2},{3,4}};}
необходимо выводить значения arrayOfInt на печать через System.out.println, как вы это реализуете?
Ответы:
- Будет выведено:
1231 - Будет выведено:
123java.lang.Integer;@2260e277
а именно: класс-объекта@хэш-код-объекта - Будет выведено:
123java.lang.String;@5502abdb
а именно: класс-объекта@хэш-код-объекта - Будет выведено:
123[173, 216, 143, 230, 322]
Неожиданно? А как по мне вполне ожидаемо, char автоматически преобразовался в int, а потом в Integer, на этапе инициализации массива. - Можно использовать метод deepToString(Array) класса Arrays
- Я переопределю в классе, метод toString(), внутри метода напишу return Arrays.deepToString(arrayOfInt);Вот такой получится класс:
12345678910class ArrayOfInteger{private Integer[][] arrayOfInt= {{1,2},{3,4}};@Overridepublic String toString() {return Arrays.deepToString(arrayOfInt);}}
В таком случае мы сможем распечатать значения таким способом:
1234ArrayOfInteger arrayOfInt = new ArrayOfInteger();System.out.println(arrayOfInt);
и получим такой результат:
123[[1, 2], [3, 4]]
Author: | Tags: /
| Rating:
15 comments.
Write a comment