Java secure coding guide: Method writing guide

brief introduction

The logic of a java program consists of methods. In the process of writing methods, we also need to abide by certain security rules, such as verifying the parameters of methods, not adding business logic to assert, not using obsolete or expired methods, and the method for security check must be set to private.

Today, let's discuss in depth what we should pay attention to in the process of writing Java methods.

Do not call a method that can be rewritten in the constructor.

Generally speaking, only static, final or private methods can be called in the constructor. Why?

If the parent class calls a method that can be overridden when executing the constructor, uninitialized data may be used in the method, resulting in runtime exception or unexpected end.

In addition, it is also possible for the method to obtain uninitialized instances, resulting in data inconsistency.

For example, we define a parent class of person:

public class Person {

    public void printValue(){
        System.out.println("this is person!");
    }

    public Person(){
        printValue();
    }
}

Then a subclass of boy is defined, but in the subclass of boy, the printvalue method of the parent class is redefined.

public class Boy extends Person{

    public void printValue(){
        System.out.println("this is Boy!");
    }

    public Boy(){
        super();
    }

    public static void main(String[] args) {
        Person persion= new Person();
        Boy boy= new Boy();
    }
}

Output results:

this is person!
this is Boy!

You can see that boy called his rewritten printvalue method.

How to solve it? The simple way is to set the printvalue in person to final.

Do not call a rewritable method in the clone () method.

Similarly, we should not call rewritable methods when defining clone methods, otherwise unexpected changes will occur.

As in the above example, we added the clone method to the person class this time:

    public Object clone() throws CloneNotSupportedException {
        Person person= (Person)super.clone();
        person.printValue();
        return person;
    }

Next, we add the clone method to the boy class:

    public Object clone() throws CloneNotSupportedException {
        Boy clone = (Boy) super.clone();
        clone.printValue();
        return clone;
    }

Because the method of rewriting can be called in the clone method, which makes the system logic chaotic. This is not recommended.

Override the equals() method

Consider the parent and child classes. If we define an equals method in the parent class, this method compares and judges according to the fields in the parent class, and finally determines whether the two objects are equal.

If some new fields are added to the subclass, if the equals method of the parent class is used instead of overriding the equals method, the newly added fields in the subclass will be omitted, resulting in unexpected results from equals.

So in general, subclasses need to override the equals method.

If you re the equals method, you need to meet the following characteristics:

For an object a, A. equals (a) must be true.

For object a and object B, if a.equals (b) is true, then b.equals (a) true must be true.

For objects a, B and C, if a.equals (b) true and b.equals (c) true, then a.equals (c) = = true must be true.

For objects a and B, if there is no change in a and B, the result of A. equals (b) cannot change.

Specific code examples are not written here. You can practice by yourself.

Hashcode and equals

Hashcode is a native method defined in object:

    @HotSpotIntrinsicCandidate
    public native int hashCode();

According to Oracle's suggestion, if the result returned by the equals method of two objects is true, the hashcodes of the two objects must return the same int value.

Why?

Let's take a look at the following example:

public class Girl {

    private final int age;

    public Girl(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof Girl)) {
            return false;
        }
        Girl cc = (Girl)o;
        return cc.age == age;
    }

    public static void main(String[] args) {

        HashMap<Girl,Integer> hashMap= new HashMap<>();
        hashMap.put(new Girl(20),20);
        System.out.println(hashMap.get(new Girl(20)));
    }
}

In the above girl, we defined the equals method, but did not override the hashcode. The final result returned is null.

Because we new the girl object twice, the hashcodes of two different objects in the native method are different.

We can add a hashcode method to the girl class:

    public int hashCode() {
        return age;
    }

This returns the correct value.

Implementation of CompareTo method

When implementing comparable classes, we usually need to implement the comparable interface. The comparable interface defines a CompareTo method to compare two objects.

When implementing the CompareTo method, we should pay attention to the general rules of comparison, that is, if x.compareto (y) > 0 & & y.compareto (z) > 0, it means x.compareto (z) > 0

Therefore, we cannot use CompareTo to implement special logic.

Recently, I saw a Japanese film called Dubo's silent recording. There is an episode in which stones, scissors and cloth are used to judge whether to win or lose.

Of course, stone, scissors and cloth do not meet our general CompareTo method, so logic cannot be defined in the CompareTo method.

Code for this article:

learn-java-base-9-to-20/tree/master/security

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>