Regarding String type equivalence comparison in Java

Overview

In the programming language "Java", "==" is supported as a comparison operator for equality, but when used when comparing ** reference types ** that are not ** primitive types ** such as String types It will be an unexpected processing result. The bottom line is that you should not use the equality operator "==" when comparing whether the values of ** reference types are equal. ** **

In this article, I'll write about why you shouldn't use equality operators when doing String type comparisons, and what happens if you do. However, this time the article focuses only on the String type, but this is also a general reference type.

Basic knowledge

Primitive type (basic data type)

Primitive types are types that represent the data itself and have no behavior for manipulating the data. You cannot assign null to a primitive type.

For example, there are the following types.

Reference type

Unlike primitive types, reference types require the use of the new operator to create and assign instances (entities) to objects, and each type has its own type-specific behavior. You can assign null to the reference type.

For example, there are the following types. In addition, the manufacturer can define the types and processes required to process the application other than the following.

By the way, if you were studying a language that uses pointers, you probably already know it. For those who say "** Reference **" in the first place, it is recommended because it is described in detail in the following article. https://qiita.com/hys-rabbit/items/2e94c8722dc8f950e77c

Main subject

What happens when you compare String types with equality operators

First, consider the output result by looking at the following processing.

TestEquals.java


public final class TestEquals {
	public static void main(String[] args) {
		final String sequence1 = "test";
		final String newSequence = new String("test");

		System.out.println("Comparison with equality operator 1:");
		System.out.println(sequence1 == newSequence);
	}
}

Now, what is the result of comparing the same string "test" with the equality operator? At first glance, the same character strings are compared, so the comparison result is likely to be true. ** However, in the above case, the comparison result will always be false. ** **

Why do you get this result? This is because the comparison with the equality operator "==" determines ** whether the data is stored at the same address in memory **.

It's a technical story, so I won't go into details here, but it's important to ask what memory is. However, in this article, I will only introduce some recommended articles. If you can afford to study, you may want to take a look.

** Java heap memory management mechanism ** https://www.atmarkit.co.jp/ait/articles/0504/02/news005.html

** Memory as seen by the program ** https://qiita.com/shinpeinkt/items/55c0d30754482e8235b9

In other words, in the above case, the variable "sequence1" and the variable "newSequence" are stored in different areas in the memory, so if you compare with the equality operator, false will be returned.

Supplement

Basically, the above understanding is sufficient for the equality operator, In some cases, please check them as well.

TestEquals.java


public final class TestEquals {
	public static void main(String[] args) {
		final String sequence1 = "test";
		final String sequence2 = "test";

		System.out.println("Comparison with equality operator 2:");
		System.out.println(sequence1 == sequence2);
	}
}

The difference from the first example is that the variable "newSequence" was initialized using the new operator, but the string "test" is simply assigned to the variable "sequence2". What will happen to the processing result in the above cases? Is it false? ** No, in the above case it will be judged as true. ** **

This is due to a Java feature, which I will briefly explain. If you initialize by assigning the character string "test" to one variable and then initialize by assigning the character string "test" to another variable in the same way, it will be managed in the same area on the memory. Java has built-in features that make adjustments as if they were. Therefore, in the above case, the processing result is true.

Comparison with equals method

Now, let's touch on the equals method defined in the leading String class. As a reminder, use the equals method as follows:

TestEquals.java


public final class TestEquals {
	public static void main(String[] args) {
		final String sequence1 = "test";
		final String sequence2 = "test";
		
		System.out.println("Comparison with equals method 1:");
		System.out.println(sequence1.equals(sequence2));
		
		final String newSequence = new String("test");
		
		System.out.println("Comparison with equals method 2:");
		System.out.println(sequence1.equals(newSequence));
	}
}

By comparing with the equals method, true is returned in both of the two patterns in the above example. Now then, who is the equals method defined in the String class and what kind of processing is defined?

How the equals method defined in the String class works

The following code is the processing of the equals method defined in the String class.

String.java


    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = length();
            if (n == anotherString.length()) {
                int i = 0;
                while (n-- != 0) {
                    if (charAt(i) != anotherString.charAt(i))
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

At first glance it may seem difficult, but if you look at how it works while disassembling it, it's a very simple implementation.

First of all, the comparison is performed by the equality operator, and true is returned if the references are equal. This is the case of initializing by directly assigning a character string to a variable as mentioned in the previous example.

Then, it will be the judgment process when the reference destination is different from the next block. First, it determines whether the instance of the object passed as an argument is of type String, and if it is not of type String, it returns false because it is completely different data in the first place. Next, if the argument object is of type String, it is verified character by character from the beginning to see if it is equal to the character string to be compared. Finally, if all the characters are equal to the comparison target, true is returned.

From the above, you can see that the equals method implemented in the String class covers all the weaknesses of the comparison with the equality operator we saw earlier.

Attention (common sense in Java)

If you're comfortable reading this far, you may have noticed that if the String class that uses the equals method becomes null, a NullPointerException will always occur. Therefore, as a Java user, you must follow the rules below.

--When using the eauals method, it must be in the form ** "constants other than null.equals (variables or constants)" **

That is, the implementer must ensure that the String class that uses the equals method is not null. Of course, depending on the implementation, there may be situations where it cannot be made a constant, but if you still guarantee the processing of the program, you should design it so that null does not enter.

Finally

I've written this for a long time, but how was it? I know some explanations are missing, but I hope this article will be of some help to those who have started studying programming in Java.

Reference material

https://morizyun.github.io/java/type-primitive-reference.html --Java primitive and reference types https://qiita.com/hys-rabbit/items/2e94c8722dc8f950e77c --Java reference to understand in the figure https://www.atmarkit.co.jp/ait/articles/0504/02/news005.html --Java heap memory management mechanism https://qiita.com/shinpeinkt/items/55c0d30754482e8235b9 --Memory as seen from the program

Recommended Posts

Regarding String type equivalence comparison in Java
[Java] Correct comparison of String type
[Java] Comparison of String type character strings
[Java] String comparison and && and ||
Type determination in Java
The story of low-level string comparison in Java
Try functional type in Java! ①
[Java] Type conversion speed comparison
I tried to convert a string to a LocalDate type in Java
[Java] Speed comparison of string concatenation
Java string
[Easy-to-understand explanation! ] Reference type type conversion in Java
[Java] Data type / string class cheat sheet
Notes on operators using Java ~ String type ~
[Java] Convert Object type null to String type
All same hash code string in Java
Split a string with ". (Dot)" in Java
Java 8 LocalDateTime type conversion stuff (String, java.util.Date)
Type conversion from java BigDecimal type to String type
[Java] Display the bit string stored in the byte type variable on the console
[Java] Equivalence comparison where beginners fail in string comparison. You may not even be aware of the mistake! ??
Java type conversion
Regarding the transient modifier and serialization in Java
[Java] Difference between equals and == in a character string that is a reference type
Read a string in a PDF file with Java
[JAVA] Stream type
Partization in Java
[Java] String padding
MyBatis string comparison
The intersection type introduced in Java 10 is amazing (?)
[Java] Enumeration type
Java Optional type
Code to escape a JSON string in Java
Changes in Java 11
About var used in Java (Local Variable Type)
Rock-paper-scissors in Java
Java double type
[Java] Map comparison
Java string processing
Java framework comparison
Organized memo in the head (Java --Data type)
Java type conversion (String, int, Date, Calendar, etc.)
Pi in Java
Split string (Java)
Why Java String typeclass comparison (==) cannot be used
How to write Java String # getBytes in Kotlin?
FizzBuzz in Java
Sample code to convert List to List <String> in Java Stream
[String type vs String Builder] Difference in processing speed in string concatenation
[Java] String join execution speed comparison (+ operator vs StringBuilder)
[Java] Things to note about type inference extended in Java 10
Equivalence comparison of Java wrapper classes and primitive types
[java] sort in list
Read JSON in Java
Interpreter implementation in Java
Make Blackjack in Java
Rock-paper-scissors app in Java
Constraint programming in Java
Put java8 in centos7
NVL-ish guy in Java
Combine arrays in Java