The first two described Java 's self-understanding of the JVM, JDK, JRE, collection, ClassLoader, and some design pattern. This is still not ready to start the transition to the Java EE, because there are still some trivial j2se the problem is not summed up.
1. Understanding of the object class
Everyone knows that object is the base class for all Java classes, meaning that all Java classes inherit the 11 methods of object. We recommend that you take a look at the source code of the 11 member functions of object, and you will know the default implementation. For example, the Equals method, the default implementation is to use "= =" to compare, that is, directly compare memory address, return TRUE or false. and the ToString () method, the string that is returned is composed in the following way:
"GetClass (). GetName () +" @"+ integer.tohexstring (hashcode ())" |
In fact, I do not have to explain too much, we can understand the composition of this string. Then look at Hashcode ():
Public native int hashcode (); |
Because the native method is related to how the OS is handled, there is only one statement in the source code. If we are interested, we can go to the bottom of it. How is the OS generated by the hashcode? But I suggest that the most important thing is to remember to use it in a few principles! First, if the Equals () method has the same object as the hashcode, but the Equals () object does not communicate, the Hashcode () method is not guaranteed to return a different integer. And the next time to run the same program, the same object may not be the original hashcode () Oh.
What about the rest of the way? Nofigy (), Notifyall (), Clone (), and wait () are all native methods, and the description depends on the implementation of the operating system . The last interesting method is finalize (), similar to C + + destructor, the signature is protected, proof that only the inheritance extension can be used, the method body is empty, the implied do nothing. Its role according to the author's understanding is only to inform the JVM that this object is no longer used, can be destroyed at any time, and the actual destruction right is still on the virtual operator. So it's really not doing anything? Not necessarily, in fact, if it is a thread object it causes the thread's priority level to increase within a certain range, resulting in faster destruction to save memory and improve performance. In fact, from the common sense, we can probably guess the purpose of JVM practice.
2. About the relationship between the overloaded hashcode () and the collection framework
I once listened to a Java training for many years of the predecessor said in his view Hashcode method does not have any meaning, just to cooperate to prove that having the same hashcode will lead to equal equality method exists. Even some predecessors have made such a mistake, in fact, it is still full of easy to ignore. So what exactly does the Hashcode () method do?
Learn the course of data structure everyone will know that there is a structure called hash table, which aims to improve the efficiency of the query by assigning a unique index to each object. Then Java does not distort the concept arbitrarily, so hashcode's only function is to support the structure of the hash table in the data structure. In other words, only the Hashtable, HashMap, and HashSet of the set framework need to be overloaded with the Hashcode () method, so that we can artificially control whether the indexes are equal in the hash structure. The author gives an example:
Once in order to write a solution class program, you need to randomly list the different permutations of 1,2,3,4 composition, so I wrote an array class with int[] to save the combined results, The randomly generated combination is then added to a hashset to make use of the hashset features that do not include duplicate elements. But hashset how to judge is not the element of repetition? Of course, judging by whether the results returned by hashcode () are equal, you can do this experiment:
- int [] a = {1,2, 3,4};
- int [] b = {1,2,3,4};
- system.out.println ( A.hashcode ());
-
|
This is clearly the same combination, but it is a different hashcode, when added to the set will be treated as a different object. This time we need to rewrite the hashcode () method, how to write it? In fact, it is based on the original Hashcode (), after all, it is the implementation of the operating system, find the unique identity of the object, the implementation of a lot of ways, the author's implementation is:
The ToString () method is overridden first:
return a[0] "+" a[1] "+" a[2] "+" a[3]; //display on the more intuitive |
Then use ToString () to calculate hashcode ():
return This . toString (). Hashcode (); |
So the above A and B return is "1234", in the Test ToString (). Hashcode (), because the copy of string in memory is the same, "1234". Hashcode () must return the same result.
Speaking of which, I believe everyone can understand better than me, and never again misunderstand the role of the Hashcode () method.
3. About the class member function and the Java reflection mechanism
Very early contact with Java to listen to a lot of teachers said Java Dynamic Runtime mechanism, reflection mechanism. It is true that they are all notable features of Java, and the runtime is loaded by the author in the first article, and now I want to talk about the reflection mechanism. In Java, the memory reflection mechanism is implemented primarily through the class and method classes in the Java.lang package.
People familiar with C + + must know that the following is not possible in C + +: The runtime passes a class name with a string parameter, and you get all the information about that class, including all of its methods, and the details of the method. You can also instantiate an object and invoke any method of that object by the name of the method found. This is because the Java class in memory, in addition to the static Dynamic Data area in C + +, also includes a description of the class itself, it is through the information in this description, to help us to read the contents of the runtime, get all the information needed to load the target class, so as to implement the reflection mechanism. Have you ever thought about how we know what the properties are when we need to get an instance of JavaBean? The obvious simple example is to write a JavaBean parser:
A. Get the class object by Class.forName ("Bean's class name"), e.g. called Abeanclass
B. Get the method[] object through the GetMethods () method of the Abeanclass
C. The word that follows the specification of all Get method names represents a property of the bean
D. When you already know a method name, you can call Newinstance () to get an instance, and then use the Invoke () method to pass in the name of the method and the parameters required by the method, and you can call this method dynamically.
Of course, there are more complex applications, here do not repeat, we can refer to the class and method methods.
4. Admit the essence of synchronize
Synchronize we all know is the meaning of synchronization, locking, in fact, it is far from the essence of the people think so complex. When the method of declaring synchronize is called, the lock is actually loaded on the object, of course, if the static class is added to the lock on the class, the call end lock is lifted. The principle of its implementation is simple, simply not allowing the second lock to be added to the same object or class again, that's all. A simple example is enough to illustrate the problem:
- class a{
- synchronized void f () {}
- void g () {}
- }
|
When an object A of a is called its F () method by the first thread, the second thread cannot call a's synchronized method such as f () because it is attempting to add a second lock to the object. But calling G () is possible, because there is no act of adding two locks on the same object.
So, can everyone understand? Understand its principle can better help you design synchronization mechanism, do not abuse lock.
Java experience: Very inspiring (iii)