Java several interesting questions

Recently, Ali sister (sister also out of the question so difficult) published an article, "offered a prize! 5 questions before collecting source world 3% super king "- see this title, my heart is very, very excited, because finally prove their technology is very Niubi.

Unfortunately, with 8 years of Java development experience, I found this whole solution yourself five questions wrong! Painful lesson once again proves that I was one of those engineers spike of 97%.

However, whatever the outcome, my people particularly thick skinned, although all wrong, but still dare to peace with himself.

01, float primitive types
first question is such that the code is as follows:

{class FloatPrimitiveTest public
public static void main (String [] args) {
a float A = 1.0f - 0.9F;
a float 0.9F B = - 0.8 F;
IF (A == B) {
System.out.println ( "to true" );
} the else {
System.out.println ( "to false");
}
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
At first glance, this question is too simple, right?

1.0f - 0.9f result is 0.1f, 0.9f - 0.8f result is 0.1f, it is naturally a == b ah.

But the actual result, it is not the case, the hurts too.

A = 1.0f a float - 0.9F;
System.out.println (A); // 0.100000024
a float 0.9F B = - 0.8 F;
System.out.println (B); // 0.099999964
. 1
2
. 3
. 4
plus two after printing the statement, I understand, accuracy problems had occurred.

Java language supports two basic floating-point type: float and double, wrapper class Float and Double as well as their corresponding. They are based on IEEE 754 standard, which is used to base number in scientific notation is represented as a decimal floating-point number 2.

But floating-point operations are rarely accurate. While some numbers can be accurately represented as a binary fraction, for example 0.5, which is equal to 2-1; however, some figures are not accurately represented, for example, 0.1. Therefore, floating-point operations could lead to rounding errors, the result is close to but does not mean that we want results.

So, we see two similar floating-point value of 0.1, a slightly larger than the 0.1 a little bit of 0.100000024, one is a little bit of 0.099999964 slightly smaller than 0.1.

For any Java floating point literal, eventually rounded to the nearest floating-point value that can be represented encountered when the value is equal to the distance, defaults from about two floating-point values ​​can be expressed even the principle of priority - that is why we will see both ends of a floating point value 4 of reasons.

02, the type of packaging Float
look second question, as follows:

{class FloatWrapperTest public
public static void main (String [] args) {
the Float Float.valueOf A = (1.0f - 0.9F);
the Float Float.valueOf B = (0.9F - 0.8 F);
IF (a.equals (B )) {
System.out.println ( "to true");
} the else {
System.out.println ( "to false");
}
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
At first glance, this question also not difficult, right? Simply float to turn into the original type of packaging type Float, and the use of alternative equals == judgment.

This time, I thought that the package will solve the problem out accuracy, so I guess the output is true. But the results of her face again - although I have a thick skin, but still feel some face slightly red again.

A = Float.valueOf float (1.0f - 0.9F);
System.out.println (A); // 0.100000024
float Float.valueOf B = (0.9F - 0.8 F);
System.out.println (B); / / 0.099999964
1
2
3
4
after adding two print statements, I realized that the original wrapper and will not solve the problem of accuracy.

a float value Final Private;
public the Float (a float value) {
this.value = value;
}
public static valueOf the Float (a float F) {
return new new the Float (F);
}
public Boolean the equals (Object obj) {
return (the instanceof the Float obj)
&& (the floatToIntBits (((Float) obj) .Value) == the floatToIntBits (value));
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
from the source can be seen, the wrapper Float does not do any processing accuracy Moreover, inside the equals method still used == judge.

03, switch determines null string value
leads to the third problem, as follows:

{class SwitchTest public
public static void main (String [] args) {
String param = null;
Switch (param) {
Case "null":
System.out.println ( "null");
BREAK;
default:
System.out.println ( "default");
}
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
this question to me bit of blurred vision.

As we all know, switch is an efficient judge sentences than if / else is really much more readily. Especially after JDK 1.7, case condition switch can be char, byte, short, int, Character, Byte, Short, Integer, String, or enum type.

In this problem, param of type String, then I think it is a case of switch condition, but the value of param is null, null and "null" is certainly not a match, I think the program should enter into default statement output default.

But the results make up their faces again! Program throws an exception:

In the Thread Exception "main" java.lang.NullPointerException
AT com.cmower.java_demo.Test.main (Test.java:7)
1
2
brackets that is, switch () is not allowed in the incoming null. why?

I flipped through the JDK's official documentation, see that there is such a description, I look directly move over everyone will understand.

When the switch statement is executed, first the Expression is evaluated. If the Expression evaluates to null, a NullPointerException is thrown and the entire switch statement completes abruptly for that reason. Otherwise, if the result is of a reference type, it is subject to unboxing conversion.

Generally means is that, when the switch statement is executed, it will first execute switch () expression, if the expression is null, a NullPointerException is thrown.

That in the end is why?

public static void main(String args[])
{
String param = null;
String s;
switch((s = param).hashCode())
{
case 3392903:
if(s.equals("null"))
{
System.out.println("null");
break;
}
// fall through

default:
System.out.println ( "default");
BREAK;
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
by JAD, what we switch to decompile bytecode The results shown above. Internal execution of the original switch () turned out to be the expression (s = param) .hashCode () , the time when param is null, s is also null, calling hashCode () methods when nature throws a NullPointerException.

04, the assignment of BigDecimal way
to see the fourth question, the code is as follows:

{class BigDecimalTest public
public static void main (String [] args) {
the BigDecimal the BigDecimal new new A = (0.1);
System.out.println (A);
the BigDecimal new new B = the BigDecimal ( "0.1");
System.out.println ( b);
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
This question is really difficult, the only difference is that a and b in a float when the incoming call to the constructor BigDecimal assignment, the incoming string b , a and b are the result should be 0.1, so I think these two assignment is the same way.

But in fact, the output totally surprised me:

A new new = the BigDecimal the BigDecimal (0.1);
System.out.println (A); // 0.1000000000000000055511151231257827021181583404541015625
the BigDecimal new new B = the BigDecimal ( "0.1");
System.out.println (B); // 0.1
. 1
2
. 3
. 4
whether this how is going on here?

You must see the official documents, it is time to move out BigDecimal (double val) of the floor JavaDoc town.

The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal (0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 can not be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, . appearances notwithstanding
explain: when using a double pass parameters will produce unexpected results, such as the actual value is 0.1 0.1000000000000000055511151231257827021181583404541015625, put it plainly, this is the accuracy issue. (That being the case, why not scrap it?)

The String constructor, on the other hand , is perfectly predictable: writing new BigDecimal ( "0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect Therefore, it is generally recommended that the String constructor be used in preference. . to this one
explanation: the use of the resulting string parameter passing of time will produce the expected, such as new BigDecimal ( "0.1") actual results is 0.1.

When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString (double) method and then using the BigDecimal . (string) constructor to get that result, use the static valueOf (double) method.
explanation: If you must BigDecimal to a double pass as a parameter, it is recommended that the double pass string value matching values. There are two ways:

A = 0.1 Double;
// 0.1; System.out.println (new new the BigDecimal (String.valueOf (A)))
System.out.println (BigDecimal.valueOf (A)); // 0.1
. 1
2
. 3
a first, use String.valueOf () to double to a string.

Second, use the valueOf () method, the internal method calls Double.toString () will double to a string, source code as follows:

public static BigDecimal valueOf(double val) {
// Reminder: a zero double returns '0.0', so we cannot fastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
return new BigDecimal(Double.toString(val));
}
1
2
3
4
5
6
7
05、ReentrantLock
最后一题,也就是第五题,代码如下:

public class LockTest {
private final static Lock lock = new ReentrantLock();

public static void main(String[] args) {
try {
lock.tryLock();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
问题如下:

A: lock latch is non-Fair
B: finally block does not throw
C: tryLock fails to acquire the lock is performed directly downward

Very ashamed, I do not know ReentrantLock is not fair locks; do not know finally block will throw an exception; but do not know tryLock acquire the lock when the failure will not be executed directly down. Not the answer.

Five consecutive road solution to a problem does not come out, although I'm very thick skinned, but also felt his face burning, like being mercilessly pumping a slap in the face.

Let me research study it.

1) lock lock non-fair

ReentrantLock is a very high frequency lock, support reentrancy can repeat lock to shared resources, namely current thread does not get blocked again after getting the lock.

ReentrantLock both equity and non-equity lock lock. When no call is non-fair constructor parameter lock, the following source code:

of ReentrantLock public () {
Sync new new NonfairSync = ();
}
. 1
2
. 3
so that a non-lock locking this question is fair, A is the correct option.

ReentrantLock construction also provides another method, the following source code:

of ReentrantLock public (Boolean Fair) {
Sync = Fair new new FairSync ():? new new NonfairSync ();
}
. 1
2
. 3
when true is passed to the fair lock, false lock when the non-fair.

That fair and unfair lock lock in the end what difference does it make?

Fair lock request can guarantee absolute order of resources in terms of time, rather than a fair lock may result in other threads can never get to lock, resulting in the phenomenon of "hunger" of.

In order to guarantee a fair lock on the order of time, need frequent context switching, rather than a fair lock will reduce the number of context switches, the performance overhead is relatively small, the system can ensure greater throughput.

2) finally block does not throw

Lock the object when calling the unlock method, method calls tryRelease AbstractQueuedSynchronizer if the current thread does not hold the lock, then throwing IllegalMonitorStateException exception.

It is recommended that the sample code to this question optimized for the form (before entering the service code block, first determine whether the current thread holds the lock):

lock.tryLock isLocked = Boolean ();
IF (isLocked) {
the try {
// doSomething ();
} the catch (Exception E) {
e.printStackTrace ();
} {the finally
lock.unlock ();
}
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 3) fails to acquire the lock tryLock performed directly downward

Javadoc tryLock () method is as follows:

Acquires the lock if it is available and returns immediately with the value true. If the lock is not available then this method will return immediately with the value false.

Chinese meaning that if the lock can be used, then acquire the lock immediately and return true if the lock is not available, then immediately returns false.

For this question, then, in tryLock acquire the lock fails, the program will execute code in the finally block.

Guess you like

Origin www.cnblogs.com/yxs98/p/11210622.html