Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the indistinguishable details in Java?

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article focuses on "what are the indistinguishable details in Java?" friends who are interested might as well take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn what are the indistinguishable details in Java.

Preface

Recently, we found a lot of code problems in the project through sonar static code detection, together with human code review. In addition to regular bug and security vulnerabilities, there are several usage errors that have aroused my great interest. Why am I so interested in these methods? Because they are so confusing, they may confuse us foolishly.

1. Will replace replace all characters?

Many times when we use a string, we want to replace the character An in ATYSDFA*Y with the character B. the first thing that comes to mind may be to use the replace method.

If you want to replace all A with B, you can obviously use the replaceAll method, because it's so intuitive that you can guess its purpose just from the method name.

So the question is: will the replace method replace all matching characters?

Jdk officials gave the answer.

This method replaces each matching string.

Since both replace and replaceAll can replace all matching characters, what's the difference between them?

1.replace has two overloaded methods.

The parameters of one of the methods, char oldChar and char newChar, support character substitution.

Source.replace ('Aids,' B')

The parameters of another method are: CharSequence target and CharSequence replacement, which support string substitution.

Source.replace ("A", "B")

The arguments to the 2.replaceAll method are: String regex and String replacement, based on the substitution of regular expressions. Normal string substitution:

Source.replaceAll ("A", "B")

Replace regular expression (replace * with C):

Source.replaceAll ("\ *", "C")

By the way, replacing * with C can also be done using the replace method:

Source.replace ("*", "C")

There is no need to escape special characters.

However, please be careful not to use the following words:

Source.replace ("\ *", "C")

This way of writing causes strings to be irreplaceable.

There is also a small problem. What if I just want to replace the first matching string?

You can use the replaceFirst method at this point:

Source.replaceFirst ("A", "B")

2. Integer can't use = = to judge equality?

I don't know if you have ever seen some colleagues compare the two parameters of type Integer using = = to see if they are equal.

Anyway, I've seen it before, so is this usage right?

My answer is to look at the specific scene, I cannot say that it must be right or wrong.

Some status fields, such as: orderStatus have:-1 (order not placed), 0 (order has been placed), 1 (paid), 2 (completed), 3 (cancellation), 5 states.

At this point, if you use = to judge whether it is equal or not:

Integer orderStatus1 = new Integer (1); Integer orderStatus2 = new Integer (1); System.out.println (orderStatus1 = = orderStatus2)

Will the return result be true?

The answer is false.

Some students may retort that there is not a range of caches in Integer:-128127?

Why false?

Let's first take a look at the construction of Integer:

It doesn't really use caching.

So where is the cache used?

The answer is in the valueOf method:

If the above judgment is changed like this:

String orderStatus1 = new String ("1"); String orderStatus2 = new String ("1"); System.out.println (Integer.valueOf (orderStatus1) = = Integer.valueOf (orderStatus2))

Will the return result be true?

Answer: it's really true.

We should form a good coding habit and use = = as little as possible to determine whether two Integer type data are equal, only in the above very special scenarios.

Instead, use the equals method to judge:

Integer orderStatus1 = new Integer (1); Integer orderStatus2 = new Integer (1); System.out.println (orderStatus1.equals (orderStatus2))

3. Do not lose precision with BigDecimal?

Usually we define some decimal fields (such as amount) as BigDecimal rather than Double to avoid the loss of precision.

There may be such a scenario when using Double:

Double amount1 = 0.02; double amount2 = 0.03; System.out.println (amount2-amount1)

Normally, it is expected that amount2-amount1 should be equal to 0.01.

But the result of the implementation is:

0.009999999999999998

The actual result is smaller than the expected result.

The subtraction of the two parameters of the Double type is converted to binary because the significant digits of the Double are 16 digits, which leads to insufficient storage of decimal places, in which case an error occurs.

Common sense tells us that using BigDecimal can avoid losing precision.

But can the loss of precision be avoided with BigDecimal?

The answer is no.

Why?

BigDecimal amount1 = new BigDecimal (0.02) BigDecimal amount2 = new BigDecimal (0.03) System.out.println (amount2.subtract (amount1))

In this example, two BigDecimal type parameters are defined, initialize the data using the constructor, and then print the subtracted values of the two parameters.

Results:

0.0099999999999999984734433411404097569175064563751220703125

Unscientific, why is the precision still lost?

The construction method of BigDecimal in jdk has the following description:

It roughly means that the result of this constructor may be unpredictable, and it may be 0.1 when it is created, but it is actually 0.10000000000000055511151231257827021181583404541015625.

Thus, using the BigDecimal constructor to initialize an object also loses precision.

So, how can we not lose precision?

BigDecimal amount1 = new BigDecimal (Double.toString 0.02); BigDecimal amount2 = new BigDecimal (Double.toString 0.03); System.out.println (amount2.subtract (amount1))

Use the Double.toString method to convert decimals of type double to ensure that the precision is not lost.

In fact, there is a better way:

BigDecimal amount1 = BigDecimal.valueOf (0.02) BigDecimal amount2 = BigDecimal.valueOf (0.03) System.out.println (amount2.subtract (amount1))

Initializing BigDecimal type parameters using the BigDecimal.valueOf method also ensures that precision is not lost. In the new version of Alibaba's development manual, it is also recommended to create BigDecimal parameters in this way.

4. String concatenation cannot be used with String?

A string of type String is called an immutable sequence, which means that the data of the object cannot be modified after it is defined, and if you want to modify it, you need to create a new object.

String a = "123"; String b =" 456 "; String c = a + b; System.out.println (c)

In the scene of a large number of string concatenation, if the object is defined as String type, it will produce a lot of useless intermediate objects, wasting memory space and inefficient.

At this point, we can define objects with more efficient variable character sequences: StringBuilder and StringBuffer.

So, what's the difference between StringBuilder and StringBuffer?

StringBuffer adds the synchronized keyword to the main methods, while StringBuilder does not. So, StringBuffer is thread-safe, while StringBuilder is not.

In fact, we rarely see scenarios where strings need to be concatenated in multithreading, so StringBuffer is actually very rarely used. In general, we recommend using StringBuilder when concatenating strings, and append strings through its append method, which produces only one object and is not locked, which is more efficient.

String a = "123"; String b =" 456 "; StringBuilder c = new StringBuilder (); c.append (a) .append (b); System.out.println (c)

Next, the key question comes: objects of type String must be less efficient than objects of type StringBuilder when strings are concatenated.

The answer is no.

Why?

Use the javap-c StringTest command to decompile:

You can see from the figure that two parameters of type String are defined, another parameter of the StringBuilder class is defined, and then the string is appended twice using the append method.

If the code looks like this:

String a = "123"; String b =" 789 "; String c = a + b; System.out.println (c)

What happens when you decompile with the javap-c StringTest command?

We will be surprised to find that we have also defined two parameters of type String, defined a parameter of the StringBuilder class, and then appended the string twice using the append method. The result is the same as the above.

In fact, since jdk5, java has optimized the + operation of String-type strings, which will be optimized to StringBuilder's append operation after being compiled into a bytecode file.

5. The difference between isEmpty and isBlank

When we operate on a string, we often need to determine whether the string is empty. If we don't use any tools, we usually judge like this:

If (null! = source & &! ".equals (source)) {System.out.println (" not empty ");}

But if you judge it this way every time, it will be troublesome, so many jar packages encapsulate the null string. At present, the mainstream tools on the market are:

StringUtils in spring

StringUtils in jdbc

StringUtils in apache common3

However, the StringUtils class in spring has only isEmpty methods, not isNotEmpty methods.

The StringUtils class in jdbc has only isNullOrEmpty methods and no isNotNullOrEmpty methods.

So I highly recommend the StringUtils class in apache common3, which contains a lot of practical null detection methods: isEmpty, isBlank, isNotEmpty, isNotBlank, etc., as well as other string processing methods.

The question is, what's the difference between isEmpty and isBlank?

Use the isEmpty method to determine:

StringUtils.isNotEmpty (null) = true StringUtils.isNotEmpty (") = true StringUtils.isNotEmpty (") = false StringUtils.isNotEmpty ("bob") = false StringUtils.isNotEmpty ("bob") = false

Use the isBlank method to determine:

StringUtils.isBlank (null) = true StringUtils.isBlank (") = true StringUtils.isBlank (") = true StringUtils.isBlank ("bob") = false StringUtils.isBlank ("bob") = false

The key difference between the two methods is in the case of an empty string, where isNotEmpty returns false and isBlank returns true.

6. Should the mapper query result be empty?

On one occasion, when I was coding review, a colleague said that the void here could be removed, which is still fresh in my memory:

List list = userMapper.query (search); if (CollectionUtils.isNotEmpty (list)) {List idList = list.stream (). Map (User::getId) .requests (Collectors.toList ());}

Because according to common sense, the collection queried by the general calling method may be null, which needs to be empty. However, this is quite special. I checked the source code of mybatis, and the null code can really be removed.

What's going on?

The query method of mybatis will eventually be called to the handleResultSets method of the DefaultResultSetHandler class:

This method returns a multipleResultsList collection object, which is new at the beginning of the method, and certainly will not be empty.

So, don't be surprised if you see someone in the code of the project using the results of the query directly:

List list = userMapper.query (search); List idList = list.stream () .map (User::getId) .duration (Collectors.toList ())

Because mapper has already been handled by the underlying layer, it does not have a null pointer exception.

7. The correct use of indexOf method

Once when I was review other people's code, I was impressed to see a place where indexOf used this method of writing:

String source = "# ATYSDFA*Y"; if (source.indexOf ("#") > 0) {System.out.println ("do something");}

Do you think this code will print out do something?

The answer is no.

Why?

JDK officials said that situations that do not exist will return-1

The indexOf method returns the position of the specified element in the string, starting at 0. The above example # is in the first position of the string, so the value after calling the indexOf method is actually 0. Therefore, the condition is false, do something will not be printed.

If you want to determine whether an element exists through indexOf, use:

If (source.indexOf ("#") > 1) {System.out.println ("do something");}

In fact, there is a more elegant way to contains:

If (source.contains ("#")) {System.out.println ("do something");} at this point, I believe you have a deeper understanding of "what are the indistinguishable details in Java". You might as well do it in practice! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report