An easy implementation of a simple code

Source: Internet
Author: User

A few days ago to see someone posted a Java code problem, it is really interesting to take out today and share with you. The topic is this: given two variables A and b of the integer type, a function swap is required to exchange their values. The code is as follows:


= = = Think about the dividing line = =

Let's think about it for 30 seconds.

= = time to the dividing line = =

Reckoned a lot of pot friends a look at this topic, the first reaction is: rub, so simple problem, let me do, is not insulting my IQ!!!

The simplest implementation:

This topic at first glance, it is really good simple, it may take only 10 seconds to complete (the main time spent typing):



OK, this is the implementation code, three lines! Let's take a look at the results:

Before:a= 1, b = 2

AFTER:A = 1, b = 2

What, you guessed the right result? Is that there is no exchange at all. What's that for? Lao Wang drew a picture:



In our main function, there are two object variables A and B, each pointing to two integer objects on the heap, respectively, 0x1234 and 0x1265, with values 1 and 2 respectively. In Java, object A = new object () This sentence executes similar to C + + cobj* c = new CObj (), where a and C are actually pointers (Java called references), A and C values, actually a memory address, instead of 1, 2, 3 such a specific number. So, when making the swap function call, pass the value, that is, the value of a i1 obtained: A memory address, pointing to 0x1234. In the same vein, I2 gets the value of B: The other memory address: 0x1265.

OK, now swap into the stack, I1, I2, tmp are pointers:

TMP = I1; // tmp Get I1 values of: 0x1234

I1 =i2; //I1 Get I2 values of: 0x1265

I2 = tmp; //I2 Get tmp values of: 0x1234

As you can see, in swap, I1 and I2 do a pointer exchange, and the final result is as follows:


Finally, A and B still point to the corresponding memory area, and the value of this memory area remains unchanged. So, the swap function equals nothing, it's a waste of expression ...

So the subject seems to be a no-no, right? (who is so bored to make a problem with no solution to waste expression!!!) )

Change the value, the dawn of solving the problem:

Before we were ready to give up, we found that there was a solution that seemed to work: if you swapped the values 1 and 2 in the address 0x1234 and 0x1265, the values of A and B change, right!

So how do we focus on how we can change this value?

If the integer provides a function called Setintvalue (intvalue), it's all right. We can implement this code:

Public static void swap (integer i1, integer i2)

{

// the second possible implementation

int tmp = I1. Getintvalue ()

I1.setintvalue (i2. Getintvalue());

I2. Setintvalue (tmp);

}

So, we went to the Java.lang.Integer code implementation. Unfortunately, he does not have this function ... Our dream, our dawn, so shattered ...

Reflection, and a new dawn:

When we were about to despair, we suddenly found this stuff:

/**

* The value of the {@code Integer}.

*

* @serial

*/

Private Final int value;

The integer implementation of Java, in which an integer value is stored inside a value variable called an int type. Although he has a get function, it does not have a set function. Because he is final (not modifiable)!

What about that? Oh, we almost forgot that there is an artifact in Java: Reflection! We can use reflection to take this variable and assign it to him, right?




So, we write down the code as above. We take the Value property from the integer class and set the corresponding value separately. Hahaha, this is always perfect! Run A:



Sad ... We get this exception: Private, final members are not allowed to visit!

It seems that there is really no way out.

Lao Wang's Lore:

At this time, Lao Wang took out from his pocket the previously stored up the weapon: the Reflection access control variables:

Accessibleobject.setaccessible (boolean flag)

field This class is inherited from AccessibleObject, and AccessibleObject provides a method called Setaccessible, which allows us to change the access control of the property.



He will set the override variable to the value we want, and then in the field class:



As long as this override is set to True, we can call the set function smoothly, so we'll simply change the implementation code:



Only add this sentence, we succeeded! haha haha!!! Let's see the results:

Before:a= 1, b = 2

AFTER:A = 2, b = 2

Wait, wait, it seems a has changed, but B seems to have not changed! What the hell is this? The same implementation method, A has changed, B has not changed, completely does not make sense ah, is there a problem with the Java virtual machine? This time, the heart is really 10,000 grass mud horse ran over ...

Looks like only one step, and actually there are miles away:

So where exactly is the problem? So let's start over and look at this piece of code.



At the beginning of the function, we defined two variables: Integer a = 1; Integer B = 2; Here 1 and 2 are the main types, in other words they are of type int, and A and B are integer types. are they equivalent? The answer is:NO!!!

Packing

If the type is not equivalent, why not error when compiling? Here comes a feature of a Java compiler: boxing. What's this one?

According to reason, when we give a value, it should be written like this: integer a =new integer (1), this is the standard way of writing, right. However, so much trouble to write, so, the Java compiler to do a convenient thing, is that you can Integera = 1 to write, and then by the compiler to help you to add the rest of the complete (Java compiler is really cute, he also has a lot of other icing, the opportunity to introduce the old king).

What did the compiler do to us? Is it:

A = 1 = = = Compile ===> a = new Integer (1)?

Lao Wang initially thought so, but later found that, wrong, he did the operation is:

A = 1 = = = Compile ===> a = integer.valueof (1)

Does the above process look like the 1 int type into the box of the integer?

How is this confirmed? Quite simply, we use JAVAP to look at the compiled Swap.class code:



Look, the first line of our main function, which defines integer a = 1, is actually done with an integer a = integer.valueof (1). This is really surprising. So what does this function do?



The parameter of this function is an int, and if the int is between the low and high of integercache, it is obtained from the Integercache, and only a new integer type is created if this range is exceeded.



This is the implementation of the Integercache, the default number between 128 and 127, was created in the beginning, so they have only one instance. Lao Wang painted the following (for everyone to see clearly, did not finish drawing all the memory)



We can verify this by:

Integer i1= 1;

Integer i2= 1;

Integer i3= 128;

Integer i4= 128;

System. out. println (I1 = = I2);

System. out. println (i3 = = I4);

Have you guessed the answer? The result is: true, False

Because the integer i1 = 1; Actually is the Integer i1 = integer.valueof (1), in the cache, we found 1 corresponding object address, and then returned directly, similarly, I2 is also found in the cache and returned directly. In this way, they have the same address, so the double equals address comparison is the same. I3 and I4 are not in the cache, so they have two new objects, so the addresses are different.

Well, after doing this cushion, let's go back to the initial question and look at the swap function implementation.



The parameter of this function: I1 and I2 respectively point to A and b corresponding memory address, this time, the value of I1 (that is value) passed to the type of TMP, the value of TMP is an integer value of 1, then we want to set the I2 integer value 2 to I1:f.set (I1, I2.intvalue ()); This place looks normal, doesn't it?

Let's take a look at the prototype of this function: public voidSet (Object obj, object value) the incoming parameter that he needs is two Object, and what are we passing in? The integer i1, and the int's I2.intvalue (). For the first parameter, there is no problem, and the second argument, the compiler gives us a boxing, the final code is transformed like this:

I1.value =integer.valueof (I2.intvalue ()). Intvalue ();

Let's do it manually,

A, I2.intvalue ()-2

B, integer.valueof (2), 0x1265

C, 0x1265.intvalue ()-2

D, I1.value-2

So this time, the data in memory is like this:0x1234 was changed to 2 ! !!



Then, we execute the next sentence: F.set (i2,tmp); To follow the above steps, we'll start by:

I2.value =integer.valueof (TMP). Intvalue ();

Here, TMP equals 1, so the steps are executed as follows:

A, integer.valueof (1), 0x1234

B, 0x1234.intvalue ()- 2

C, I2.value-2

Note that the value of step B is the value of the previous step changed from 1 to 2, so the final memory value is:



So, we see that the final A and B outputs are all 2. Finally, finally, we analyzed the results ~ ~

What about the exchange that we asked for at the end, and how to change it? We have two ways.

1, do not let integer.valueof boxing play a role, avoid using the cache, so you can write:



We replaced the integer.valueof with Newinteger, so that TMP was assigned to a different address;

2, we use the Setint function instead of the SET function, so that the need to pass in an int, not an integer, will not occur automatically boxing



So ... The problem is solved!

= = Summary of the division line = =

Look at the simple implementation of a code that hides a simple implementation that contains:

1, the value of the function call is passed;

2, the value of the object reference is the memory address;

3, the accessibility of reflection;

4, the Java compiler Automatic boxing;

5. An integer-boxed object cache.

So good a few hidden questions. What do you think you understand?

If you think Lao Wang speaks good, next Sunday afternoon continue to pay attention to the old King's Bar (Simplemain)


An easy implementation of a simple code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.