Reprint---Write high-quality code: 151 recommendations for improving Java programs (3rd: Classes, objects, and methods ___ recommendation 47~51)

Source: Internet
Author: User
Tags true true

Read Catalogue

    • Recommendation 47: Use GetClass for type determination in equals
    • Recommendation 48: Overwrite the Equals method must overwrite the Hashcode method
    • Recommendation 49: Recommended Overwrite ToString Method
    • Recommendation 50: Use the Package-info class for the package service
    • Recommendation 51: Do not take proactive garbage collection
Back to top recommendation 47: Use GetClass in equals for type determination

In this section we continue to discuss the issue of overwrite equals, this time we write an employee employee class inherits the person class, which is normal, the staff is also human, and in the JavaBean inherited also many see, the code is as follows:

 1 public class Employee extends person {2 private int ID; 3 4 public Employee (String _name, int _id) {5 Super (_name); 6 id = _id; 7} 8 9 public int getId () {Ten return id;11}12 public void setId (int id) {This.id             = id;15}16 @Override18 public boolean equals (Object obj) {if (obj instanceof Employee) {20         Employee E = (employee) obj;21 return super.equals (obj) && e.getid () = = Id;22}23         Return false;24}25}27 class Person {private string name;30 to public person (String _name) {32 Name = _name;33}34 public String getName () {}38 return name;37 Setnam         E (String name) {this.name = name;41}42 @Override44 public boolean equals (Object obj) {45 if (obj instanceof person) {The person P = (person) obj;47 if (null = = P.getname () | | | NULL = = name) {false;49} else {name.equalsignorecase return (P.G Etname ());}52}53 return false;54}55}

The employee class adds the id attribute and also the Equals method, which represents the same employee only if the name and ID are the same, in order to avoid a situation in which the same employee with the same name is present in a company. Look at the above code, the conditions here are quite perfect, should not be wrong, then we test, the code is as follows:

1 public static void main (string[] args) {2         employee e1 = new Employee ("Zhang San"); 3         Employee e2 = new Employee ("Zhang San 4 person         p1 = new Person ("Zhang San"), 5         System.out.println (P1.equals (E1)), 6         System.out.println ( P1.equals (E2)); 7         System.out.println (E1.equals (E2)); 8     }

The above defined two employees and a social homeless, although they have the same name, but certainly not the same, the output should be false, but after the result is: True true false

Very not to force Ah, P1 unexpectedly equal to E1, also equals E2, why is not the same class of two instances will also be equal? This is simple because p1.equals (E1) is judged by the Equals method that calls the parent class person, and it uses the INSTANCEOF keyword to check whether E1 is an instance of person, and because of the inheritance of the two villages, the result is, of course, true. Equality there is no problem, but the reverse is not established, E1 and E2 is not equal to P1, which is a violation of the principle of symmetry is a typical case.

More Xuan is P1 and E1, E2 equal, but E1 and E2 is not equal, it seems that a simple symbolic transfer can not be achieved, this is the focus of our analysis: E1.equals (E2) call is the sub-class employee Equals method, not only to determine the same name, but also to determine the same ID , the work number is different, not equal is also natural. The equation is not passed because it violates the transitive principle of equals, and the transitivity principle refers to the instance object x, Y, Z, if X.equals (y) returns true for True,y.equals (z), then x.equals (z) should also return true.

The key to this is that the parent class refers to the instanceof keyword, which is used to determine the instance object of a class, which makes it easy for subclasses to exploit. To solve it is also very simple, using getclass instead of instanceof for type judgment, the person's Equals method is modified as follows:

@Override public    boolean equals (Object obj) {        if (null! = obj && obj.getclass () = = This.getclass ()) {            Person P = (person) obj;            if (null = = P.getname () | | null = = name) {                return false;            } else {                return name.equalsignorecase (P.getname ()); 
   }        }        return false;    }

Of course, given that the employee is also likely to be inherited, it also needs to change its instanceof to GetClass. In summary, it is recommended that you use GetClass for type judgments when you overwrite equals instead of using instanceof.

Back to top tip 48: Overwrite the Equals method must overwrite the Hashcode method

Overwrite Equals method must overwrite Hascode method, this rule basically every javaer know, this is also the JDK API repeatedly explain, but why do this? What is the relationship between the two methods? This recommendation is to explain the problem, let's look at the code first:

public class Client48 {public    static void Main (string[] args) {        //The instance of the person class as the Map's key        Map<person, object> map = new Hashmap<person, object> () {            {                put (new person ("Zhang San"), New Object ());            }        };        instance of the person class        list<person> list = new arraylist<person> () {                Add ("Zhang San") as an element of list );            }        };        Boolean B1 = list.contains (New person ("Zhang San"));        Boolean b2 = Map.containskey (New person ("Zhang San"));        System.out.println (B1);        System.out.println (B2);    }}

The person class in the code is the same as the previous suggested person, and the Equals method is perfect. In this code, we call the method assignment directly in the Declaration, which is also an internal anonymous class, and now the question is whether the B1 and B2 values are true?

Let's first look at the equals of the B1,person class, no longer judging two addresses equal, but judging whether two objects are equal based on the person's name, so no matter how many objects are produced by our new Man ("Zhang San"), they are equal. Put the Zhang San into the list, and then check whether the list contains, the result must be true.

Next look at B2, we put Zhang San this object as a map of the key (key), put in the Zhang San, check the object or Zhang San, that should be the same as the results of the list, but unfortunately, the result is false. What is the reason?

  The reason is that HashMap's underlying processing mechanism is to save the map entries in an array (map Entry), the key of which is this The subscript processing mechanism for arrays: determines the subscript of an array based on the return value of the passed-in element hashcode method, if there is already a map entry in the array position, and is not processed if the value is equal to the passed in, and if the array position has no entry, it is inserted and added to the list of map entries. Similarly, checking whether a key exists is also based on the hash code to determine the location, and then traverse the lookup key value.

  And then delve into it, what value does the Hashcode method of the object element return? It is a hash code of an object, generated by the local method of the object class, ensuring that each object has a hash code (which is also the basic requirement of the hashing algorithm: any input k, through an algorithm f (k), convert it to a non-reversible output, for two input K1 and K2, if K1=K2 is required, You must have f (K1) =f (K2), but also allow k1! = K2, F (K1) =f ( K2) to exist.

Back to our example, since we did not overwrite the Hashcode method, the return value (that is, the hash code) of the two-sheet three-object Hashcode method is definitely not the same, and the corresponding map entry is not found in the HashMap array, so it returns false.

The problem is clear, the modification is very simple, rewrite the Hashcode method in the person class, the code is as follows:

Class person{   @Override public    int hashcode () {        return new Hashcodebuilder (). Append (name). Tohashcode ();   }

Where Hashcodebuilder is a hash code generation tool under the Org.apache.commons.lang.builder package, it is very convenient to use, you can integrate directly into the project (why not write the Hashcode method directly?). Because the hash code generation has many kinds of algorithms, its own trouble, the matter is many, so when necessary to take "take doctrine", do not repeat to build the wheel is the best way. )

Back to top recommendation 49: Recommended Overwrite ToString Method

Why overwrite the ToString method, the problem is very simple, because Java provides the default ToString method is not friendly, printed out can not understand, do not overwrite, see such a piece of code:

public class Client49 {public    static void Main (string[] args) {        System.out.println (new person ("Zhang San"));}    } Class Person {    private String name;    Public person (String _name) {        name = _name;    }    Public String GetName () {        return name;    }    public void SetName (String name) {        this.name = name;    }}

The output is: [email protected] If the machine is different, the content after the @ will be different, but the format is the same: class name [email Protected]+hashcode, this thing is for the machine to see, people can understand it! This is because we did not overwrite the ToString method of the object class, modify the code as follows:

@Override public    String toString () {        return String.Format ("%s.name=%s", This.getclass (), name);    }

So that you can output debugging information when needed, but also very friendly, especially in the Bean Popular project (the General Web project is this), with such output to better debug, or find the error is a bit troublesome! Of course, when the bean properties are more, their implementation is not available, but you can directly use the Apache Commons Toolkit in the Tostringbuilder class, concise, practical and convenient. One might say, why is it called by the ToString method to print an object through the Println method? That's the printer from println: if it's a primitive type, print directly, and if it's a class type, print out the return value of its ToString method, that's all. At the same time, the IDE is also very advanced, you can also view the Debug object variables, but it is recommended that you overwrite the ToString method, so debugging will be more convenient oh.

Back to top recommendation 50: Use the Package-info class for the package service

There is a special class in Java: The Package-info class, which is dedicated to this package, why it is special, mainly in three aspects:

    1. It can not be created casually: in the General IDE, Eclipse, Package-info and other files can not be randomly created, will be reported "Type name is Notvalid" error, the class name is invalid. In Java, the variable definition specification specifies that the following characters are allowed: letters, numbers, underscores, and the $ symbol that doesn't write, but not in the column, so how do you create this file? Very simply, create one with Notepad, and then copy it and change it, the more straightforward way is to copy it from another project.
    2. The object it serves is very special: A class is a description of a category or group of things, such as the Dog class, which describes "Huang", what does the Package-info class describe? It always has to have a description or statement of the object, it is to describe and record the package information.
    3. The Package-info class cannot have implementation code: The Package-info class is also a class, and it is compiled into Package-info.class, but the Package-info class cannot be declared in the Package-info.java file.

Package-info class also has a few special places, such as can not inherit, no interface, no inter-class relationship (association, composition, aggregation, etc.), since there is such a special class in Java, it certainly has its special role, we look at its special role, mainly in the following three aspects:

    • Declaration-friendly class and in-Package access constants: This is relatively simple, and very useful, such as a package has a lot of internal access to the class or constant, it can be unified into the Package-info class, this is convenient, easy to centralize management, can reduce the friendly class roaming around the situation, the code is as follows:
Class Pkgclazz {public        void Test () {        }    }        class Pkgconstant {        static final String package_const = "ABC ";    }

Note that the above code is placed in Package-info.java, although it does not write the Package-info implementation, but the Package-info.class class file will still be generated. With this definition, we put the constants and classes required for a package in this package, both semantically and habitually, to make the programmer more adaptable.

    • To facilitate the provision of annotations on the package: for example, we will write an annotation (Annotation), look at the object under the package, as long as the annotations to the Package-info file, and in many open source projects also adopted this method, such as Struts2 @namespace , Hibernate @filterdef and so on.
    • Provides an overall comment description of the package: if it is a subcontracting development, which means that a package implements a business logic or function point or module or component, then the package needs a good documentation of what the package is for, the version change history, the logical relationship with other packages, etc. The role of the Package-info file is played out here, which can be directly defined in this file, when the document is generated through Javadoc, these instructions are used as the home page of the package document, making it easier for readers to have a holistic understanding of the package. Of course it works the same as package.html on this point, but package-info can maintain the integrity of the document in the Code, and can implement synchronous updates of the code with the document.

Create Package-info, or you can take advantage of IDE tools such as:

  

Explained so much, summed up into a sentence: in the need to use the package, you can consider the Package-info this special class, perhaps can play a multiplier effect.

Back to top recommendation 51: Do not take proactive garbage collection

A long, long time ago, In the java1.1 era, we often see the call of SYSTEM.GC such as---active garbage collection, but after the Java knowledge, such code gradually disappeared---this is a good phenomenon, because the active garbage collection is a very dangerous action.

It is dangerous because system.gc to stop all responses in order to check if there are objects in memory that can be recycled, which is risky for an application, and if it is a Web application, all requests are paused, waiting for the garbage collector to execute, if the heap memory The object is also acceptable, but the object is more (now the Web project is bigger, the framework, tools are more and more, loaded into the memory of the object of course more), the process is very time-consuming, may be 0.01 seconds, it may be 1 seconds, or even 20 seconds, which seriously affect the operation of the business.

For example: We write a piece of code: New String ("ABC"), which has no references and is a garbage object to the JVM. The JVM's garbage collector thread scans for the first time (the scan time is uncertain, executes when the system is not busy), says "You can recycle", the second scan actually reclaims the object, and frees up memory space, if we call System.GC directly, it says "Hi, you, The garbage collector came by to check if there are any garbage objects, recycle ". Look, the program is actively looking for the garbage collector, which means that the running system is going to give away the resources for the garbage collector to execute, think about it, it will check all the objects once, and then dispose of the garbage objects. Note that you are checking each object.

Do not call System.GC, even if memory overflow is often not called, memory overflow is can be analyzed, can find the reason, GC is not a good trick.

Reprint---Write high-quality code: 151 recommendations for improving Java programs (3rd: Classes, objects, and methods ___ recommendation 47~51)

Related Article

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.