новая строка (); в Яве - PullRequest
       2

новая строка (); в Яве

1 голос
/ 29 января 2012

У меня есть утверждение assert для проверки метода равных в классе.ниже 2 утверждения

Assert.assertTrue(a.equals(new VideoObj(title, year, director)));
Assert.assertTrue(a.equals(new VideoObj(new String(title), year, director)));

в чем разница между двумя утверждениями?и почему у 2-го утверждения assert есть new String(title), может кто-нибудь сказать мне, в чем разница в этом?

А также не могли бы вы предоставить мне учебник для изучения написания тестового класса для Java?*

спасибо

Ответы [ 7 ]

1 голос
/ 29 января 2012

Новый оператор String () создает новый объект String с содержимым исходной строки. Это дает вам два объекта String (исходный и тот, который был недавно создан с новым оператором String (originalString)), которые имеют одинаковое содержимое, но являются двумя различными объектами Java. Если вы сравните эти два объекта с оператором ==, это сравнение вернет false, потому что это два разных объекта. Принимая во внимание, что сравнение с методом equals () в String все равно вернет true, потому что внутри этих двух строк хранится один и тот же текст.

Итак, я предполагаю, что цель этого утверждения в тесте состоит в том, чтобы убедиться, что метод equals () элемента «a» действительно использует метод equals () строки заголовка для проверки на равенство, а не просто выполняет просто == сравнение двух строк заголовка. Без этого утверждения такая недопустимая реализация метода equals () может остаться незамеченной, поскольку две строки заголовка в сравниваемом объекте могут быть ссылками на один и тот же объект String, что также даст ожидаемый результат при использовании (неправильно) == оператор, чтобы проверить их на равенство.

1 голос
/ 29 января 2012

Разница заключается в следующем:

Если в VideoObj метод equals() был переопределен и использует String, который передается через конструктор как title, он проверяет, работает ли он, если String нет буквальный

Если в equals() кто-то сделал это:

...
if (otherObj.getTitle() == this.title) {
...

Первое утверждение выполнится успешно, а второе - если 10101 * будет строковым литералом. Строковые литералы в Java объединяются в пул, что означает, что вы получите несколько ссылок на один и тот же литерал, если он используется несколько раз;

String a = "This is a string";
String b = "This is a string";
// a and b will both be the same reference
String c = new String("This is a string");
// c will *not* be the same reference

Редактировать: Обратите внимание, что предполагается, что title в вашем первом утверждении действительно String

1 голос
/ 29 января 2012

new String () явно создает новый объект String.И:

Assert.assertTrue(a.equals(new VideoObj(title, year, director)));

повторно использует существующий объект String (который может дать вам разные результаты в зависимости от реализации метода equals в VideoObj), или использует какой-то другой объект, например byte[], так как есть конструктор для new String(byte[]).Конечно, есть много других (см. Java API).

... edit Проверьте это:

String s1=new String("abcxyz");
String s2=new String("abc"+"xyz");
String s3=s1+s2;
String s4="abcxyz";    // string literal will go to string pool
String s5="abc"+"xyz"; // string literal will go to string pool

System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s3==s4);
System.out.println(s4==s5); // TRUE (the rest are false)
System.out.println(s2==s4);
System.out.println(s2==s5);
System.out.println(s3==s1);
System.out.println(s3==s5);
1 голос
/ 29 января 2012

Если title не является String, то второй оператор assert может вызывать другой конструктор VideoObj. Без дополнительной информации о title и о классе VideoObj трудно сказать больше.

Выполните веб-поиск по junit tutorial , чтобы получить множество ресурсов для обучения написанию тестовых классов.

РЕДАКТИРОВАТЬ Из вашего комментария к ответу @BrianRoach я понял, что ваш VideoObj.equals(Object) метод реализован следующим образом:

public boolean equals(Object thatObject) {
    if (!(thatObject instanceof VideoObj)) return false;
    VideoObj that = (VideoObj) thatObject;
    return ((_title.equals(that.title()))
        || (_director.equals(that.director()))
        || (_year == that.year()));
}

Если это так, то проблема в том, что в вашем операторе return должны использоваться && вместо || операторов. Это объясняет, почему ваши утверждения не жалуются.

0 голосов
/ 29 января 2012

title может быть либо String, StringBuffer, StringBuilder, char[] или byte[]. Если это String, он будет запускать тот же конструктор, что и другой вызов, но во всех других случаях он может запускать совершенно другой перегруженный конструктор.

Не видя типа title, невозможно сказать, какой именно.

Редактировать: Поскольку типом является String, причина новой String, скорее всего, состоит в том, что основной код не сравнивает строки, используя == (reference-equals) по ошибке. Если это так, первый тест может пройти (строковые константы с тем же значением могут действительно ссылаться на один и тот же объект String, и тест может использовать константы для настройки и тестирования), в то время как второй тест будет прерван, поскольку == больше не будет соответствовать свежему созданная строка.

0 голосов
/ 29 января 2012

Не должно быть никакой разницы между двумя операторами, при условии, что 'title' является String.

0 голосов
/ 29 января 2012

Java делает некоторую оптимизацию. Если у вас есть две строки с одинаковым значением, это, скорее всего, один и тот же объект. Это может быть сделано, потому что строки являются неизменяемыми. Но если вы явно создадите новую строку с вызовом конструктора, будет создан новый объект.

...