После переопределения hashCode toString () возвращает то же значение для того же объекта, но после использования «==» возвращает false - PullRequest
0 голосов
/ 23 января 2020

Как вы, возможно, знаете, у Object есть какая-то функция, например, у нас есть toString () из oracle Documentacion, по умолчанию мы можем знать, что он возвращает HexValue из hashCode () https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString () Мы также можем используйте hashCode () для проверки объекта равенства (конечно, реализация зависит от вас). Поэтому я сделал реализацию для моего Class Projekt:

public class Projekt {

    int i;
    public Projekt(int i) {
        this.i=i;
        // TODO Auto-generated constructor stub
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + i;
        return result;
    }   
}

Тестовый код:

Projekt projekt = new Projekt(1);
System.out.println(projekt.toString());
System.out.println(projekt.toString() == projekt.toString());

Вывод:

Projekt@20
false

Также я пытаюсь получить значение из projekt.toString () в StringPool, написав:

    String string = projekt.toString();
    String stringABC = projekt.toString();
    System.out.println(string == stringABC);

В соответствии с PoolString у меня должна быть та же ссылка, но outPrint имеет значение false.

Так что этот метод возвращает другое значение ссылки, но я не могу понять, почему?

Ответы [ 3 ]

0 голосов
/ 23 января 2020

String class - это просто указатель на строковые (char) данные где-то в памяти. Это класс, это не примитивный тип, такой как boolean, byte, char, short, int, long, float и double.

Итак, сравнивая две строки, вы сравниваете указатели.

Вы сгенерируйте две строки:

String string = projekt.toString();
String stringABC = projekt.toString();

Итак, у вас есть 2 разных указателя. У них внутри одинаковый текст, но они находятся в разных местах памяти.

Но вы можете использовать метод объекта equals ():

System.out.println(string.equals(stringABC));
0 голосов
/ 23 января 2020

Из вашего комментария:

Я скопировал это из другой коменатрии: Но для экономии памяти мы используем StringPool. Если у нас одно и то же значение, то ссылка та же самая, она работает только для создания String не конструктором. Если бы у меня было String s = new String("a"); String s2 = new String("a");, я использовал бы 2 пробела в памяти, но когда я использовал String s = "a"; String s2 = "a", я использовал бы 1 пробел в памяти. То есть это означает toString() return «new String ()»?

Ваш источник должен был сказать:

... он работает только для создания String с использованием строковые литералы.

Таким образом, это могло бы быть яснее, потому что есть много способов создания новых String объектов без непосредственного вызова конструктора. Строковые литералы - это те вещи, которые окружены " (включая кавычки), такие как "a" или "b" или "Welcome to Stack Overflow".

Только строковые литералы 1 объединяются автоматически. Вы можете вручную поместить строку в пул, вызвав intern().

Когда вы объединяете две строки (например, stringA + stringB), обычно создается новая строка, как описано здесь .

Теперь давайте посмотрим, что делает Object.toString:

Метод toString для класса Object возвращает строку, состоящую из имени класса, для которого Объект - это экземпляр, символ знака @ и шестнадцатеричное представление без знака хеш-кода объекта. Другими словами, этот метод возвращает строку, равную значению:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Обратите внимание, что строки объединяются здесь, поэтому здесь создается новый строковый объект, следовательно, вывод.

И чтобы ответить на вопрос:

Значит, toString() return "new String ()"?

Да, но не напрямую. Компилятор превратит операторы + в Object.toString в некоторый код, используя StringBuilder (точнее, «компилятор превратил ...», так как класс Object уже скомпилирован) , В конце она вызовет StringBuilder.toString, и это создаст новый объект String.


1 Постоянные выражения строк, чтобы быть более точными .

0 голосов
/ 23 января 2020

Это потому, что метод "toString ()" возвращает строку. Поэтому каждый раз, когда вы вызываете toString(), он возвращает новую ссылку, потому что строки неизменны (даже если они имеют одинаковый текст)

...