Java beginners must understand these issues

  • 2020-04-01 03:29:52
  • OfStack

The questions in this series should be understood by anyone learning Java. Of course, it doesn't matter if you just learn Java and play with it. If you think you are over the beginner, but do not understand these questions, please return yourself to the beginner team.

Question 1: what do I say clearly?

String s = "Hello world!" ;

Many people have done this, but what exactly are we claiming? The answer is usually a String that says "Hello world!" . Such vague answers are often the source of confusion. Given the right answer, half of us would probably get it wrong.
This statement declares a reference to an object called "s," which can point to any object of type String, and currently to "Hello world!" This object of type String. This is what really happened. We're not declaring a String object, we're just declaring a reference variable that can only point to a String object. So, if you follow that sentence, if you run another sentence:

String String = s;

We're declaring another reference that can only point to a String object, called String, and there's no second object, and the String is still pointing to the same object, that is, to the same object as s.

Question 2: what is the difference between "==" and equals method?

The == operator is used to compare the equality of values of variables. One of the easier things to understand is:


int a=10;
int b=10;

Then a==b will be true.

But here's what's hard to understand:


String a=new String("foo");
String b=new String("foo");

A ==b returns false.

As mentioned in the previous post, an object variable is actually a reference, and its value refers to the memory address where the object is located, not the object itself. Both a and b use the new operator, which means that two strings containing "foo" will be generated in memory, and since they are "two," they naturally reside at different memory addresses. The values of a and b are actually the values of two different memory addresses, so using the "==" operator will result in false. Sure, the objects a and b refer to have "foo" in their contents, which should be "equal," but the == operator does not involve a comparison of object contents.

Comparing the contents of an object is exactly what the equals method does.

Take a look at how the equals method of Object is implemented:


boolean equals(Object o){   
return this==o;
}

Object USES the = = operator by default. So if your class doesn't override the equals method, your class will get the same result using equals and ==. You can also see that the equals method of Object does not achieve what the equals method should: compare the contents of two objects to be equal. Because the answer should be determined by the creator of the class, Object leaves this task to the creator of the class.

Take a look at an extreme class:


Class Monster{
private String content;
...
boolean equals(Object another){ return true;}
}

I override the equals method. This implementation causes comparisons between Monster instances to always return true regardless of their contents.
So don't take it for granted when you're using equals. Because maybe you think equals, and the author of the class doesn't, and the implementation of the equals method of the class is in his hands. If you need to use the equals method, or using any collection based on hash code (HashSet, HashMap, HashTable), please check the Java doc to confirm the equals this class is how to implement the logic.

Question 3: has the String changed ??

No. Because String is designed to be immutable, all of its objects are immutable. See the following code:


String s = "Hello";
s = s + " world!";

Can the policy that s points to be changed? The conclusion from the first article in this series is a simple one. Let's see what works. In this code, s originally points to a String policy, which says "Hello", and then we do a + operation on s, so can the policy that s points to be changed? The answer is no. At this point, s does not point to the policy, but to a String policy that says "Hello world!" The original policy still exists in memory, except that the reference variable s no longer refers to it.
 
After the above clarification, we can simply derive another conclusion, if the String is often modified in various ways, perhaps not foreseen, then the use of String to represent the String will cause a large memory cost. Since the String policy cannot be changed after it is set up, a String policy is required for each different String. Instead of generating a new policy for each different string, consider using the StringBuffer class, which promises to fix it. Moreover, these two types of policy changes are very simple.
Together, we can also learn that if we want to use the same String, we don't have to use a new String every time. For example, if we want to initialize a String reference variable named s in the struct and set it to the initial value, we should do this:


  public class Demo {
  private String s;
...
   public Demo {
  s = "Initial Value";
  }
...
  }
 

Rather than
S = new String ("Initial Value");
 
The latter calls the struct every time to generate a new policy, which is inefficient and memory consuming, and meaningless. Since the String policy cannot be changed, it only needs a String policy to indicate the same content of the String. In other words, the structors above are called repeatedly to create multiple policies whose string-type feature s points to the same policy.
The conclusion above is also based on the fact that for String constants, if the content is the same, they represent the same String policy. Calling structors with the keyword new always creates a new policy, whether the content is the same or not.
As for why the String class should be depicted as a non-variable class, that's what it's for. In fact, not only String, many classes in the Java specification class library are not allowed to change. In the development of a system, we sometimes also need to describe not to change the class, to pass a set of associated values, which is also the performance of policy-oriented thinking. There are some advantages to not changing classes, such as the fact that because its policy is read-only, there is no problem with concurrent calls from multiple threads. Of course, there are some drawbacks, such as a policy for each different situation, which can lead to functional problems. So the Java specification class library also provides a mutable version, StringBuffer.


Related articles: