乐趣区

关于java:java安全编码指南之方法编写指南

简介

java 程序的逻辑是由一个个的办法组成的,而在编写办法的过程中,咱们也须要恪守肯定的平安规定,比方办法的参数进行校验,不要在 assert 中增加业务逻辑,不要应用废除或者过期的办法,做安全检查的办法肯定要设置为 private 等。

明天咱们再来深刻的探讨一下,java 办法的编写过程中还有哪些要留神的中央。

不要在构造函数中调用能够被重写的办法

一般来说在构造函数中只能调用 static,final 或者 private 的办法。为什么呢?

如果父类在执行构造函数的时候调用了一个能够被重写的办法,那么在该办法中可能会应用到未初始化的数据,从而导致运行时异样或者意外完结。

另外,还可能到办法获取到未初始化结束的实例,从而导致数据不一致性。

举个例子,咱们定义了一个 Person 的父类:

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

    public Person(){printValue();
    }
}

而后定义了一个 Boy 的子类,然而在 Boy 子类中,从新了父类的 printValue 办法。

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();}
}

输入后果:

this is person!
this is Boy!

能够看到 Boy 调用了本人重写过的 printValue 办法。

留神,这里并不是说会产生语法错误,而是这样会导致业务逻辑看起来十分凌乱。

怎么解决呢?简略方法就是将 Person 中的 printValue 置位 final 即可。

不要在 clone() 办法中调用可重写的办法

同样的,咱们在定义 clone 办法的时候也不要调用可重写的办法,否则也会产生意想不到的变动。

还是下面的例子,这次咱们增加了 clone 办法到 Person 类:

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

接下来咱们增加 clone 办法到 Boy 类:

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

因为在 clone 办法中调用了可重写的办法,从而让零碎逻辑变得凌乱。不举荐这样应用。

重写 equals() 办法

考虑一下父类和子类的状况,如果在父类中咱们定义了一个 equals 办法,这个办法是依据父类中的字段来进行比拟判断,最终决定两个对象是否相等。

如果子类增加了一些新的字段,如果不重写 equals 办法,而是应用父类的 equals 办法,那么就会脱漏子类中新增加的字段,最终导致 equals 返回意想不到的后果。

所以一般来说,子类须要重写 equals 办法。

如果从新 equals 办法,须要满足上面几个个性:

  1. reflexive 反射性

对于一个 Object a 来说,a.equals(a) 必须成立。

  1. symmetric 对称性

对于一个 Object a 和 Object b 来说,如果 a.equals(b)==true,那么 b.equals(a)==true 肯定成立。

  1. transitive 传递性

对于 Object a,b,c 来说,如果 a.equals(b)==true,b.equals(c)==true, 那么 a.equals(c)==true 肯定成立。

  1. consistent 一致性

对于 Object a,b 来说,如果 a 和 b 没有产生任何变动,那么 a.equals(b) 的后果也不能变。

  1. 对于非空的援用 a,a.equals(null) 肯定要等于 false

具体代码的例子,这里就不写了,大家能够自行练习一下。

hashCode 和 equals

hashCode 是 Object 中定义的一个 native 办法:

    @HotSpotIntrinsicCandidate
    public native int hashCode();

依据 Oracle 的倡议,如果两个对象的 equals 办法返回的后果是 true,那么这两个对象的 hashCode 肯定要返回同样的 int 值。

为什么呢?

咱们看下上面的一个例子:

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)));
    }
}

下面的 Girl 中,咱们定义了 equals 办法,然而并没有重写 hashCode,最初返回的后果是 null。

因为咱们 new 了两次 Girl 这个对象,最初导致 native 办法中两个不同对象的 hashCode 是不一样的。

咱们能够给 Girl 类中增加一个 hashCode 办法:

    public int hashCode() {return age;}

这样就能够返回正确的值。

compareTo 办法的实现

咱们在实现可比拟类的时候,通常须要实现 Comparable 接口。Comparable 接口定义了一个 compareTo 办法,用来进行两个对象的比拟。

咱们在实现 compareTo 办法的时候,要留神保障比拟的通用规定,也就是说,如果 x.compareTo(y) > 0 && y.compareTo(z) > 0 那么示意 x.compareTo(z) > 0.

所以,咱们不能应用 compareTo 来实现非凡的逻辑。

最近看了一个日本的电影,叫做 dubo 默示录,外面有一集就是石头,剪刀,布来判断输赢。

当然,石头,剪刀,布不满足咱们的通用 compareTo 办法,所以不能将逻辑定义在 compareTo 办法中。

本文的代码:

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

本文已收录于 http://www.flydean.com/java-security-code-line-method/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!

退出移动版