简介

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/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

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

java安全编码指南之:方法编写指南的更多相关文章

  1. 基于Asterisk的VoIP开发指南——Asterisk 模块编写指南(1)

    原文:基于Asterisk的VoIP开发指南--Asterisk 模块编写指南(1) 1 开源项目概述 Asterisk是一个开源的软件包,通常运行在Linux操作系统平台上.Asterisk可以用三 ...

  2. 阿里巴巴Java编码规范插件安装使用指南

    编码规范插件安装使用指南 阿里技术公众号公布的<阿里巴巴Java开发规约>,瞬间引起全民代码规范的热潮,后又发布了PDF的终极版,大家踊跃留言,期待配套的静态扫描工具开放出来. 为了让开发 ...

  3. java安全编码指南之:Thread API调用规则

    目录 简介 start一个Thread 不要使用ThreadGroup 不要使用stop()方法 wait 和 await 需要放在循环中调用 简介 java中多线程的开发中少不了使用Thread,我 ...

  4. 基于Asterisk的VoIP开发指南——(2)Asterisk AGI程序编写指南

    原文:基于Asterisk的VoIP开发指南--(2)Asterisk AGI程序编写指南 5. Asterisk AGI程序编写指南 5.1概述 很多时候,我们需要在拨号方案中做某些业务逻辑的判断或 ...

  5. Html Email 邮件html页编写指南

    前言 写过邮件的html的童学应该都知道,邮件的html一般都用table来布局,为什么呢?原因是大多数的邮件客户端(比如Outlook和Gmail),会过滤HTML设置,让邮件面目全非. 经过多次的 ...

  6. Bookmarklet编写指南

    作者: 阮一峰 日期: 2011年6月11日 前一段日子,我写了两个Bookmarklet----"短网址生成"和"短网址还原". 它们用起来很方便,除了我本人 ...

  7. 《SystemVerilog验证-测试平台编写指南》学习 - 第3章 过程语句和子程序

    <SystemVerilog验证-测试平台编写指南>学习 - 第3章 过程语句和子程序 3.1 过程语句 3.2 任务.函数以及void函数 3.3 任务和函数概述 3.4 子程序参数 3 ...

  8. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  9. Java使用POI读取和写入Excel指南

    Java使用POI读取和写入Excel指南 做项目时经常有通过程序读取Excel数据,或是创建新的Excel并写入数据的需求: 网上很多经验教程里使用的POI版本都比较老了,一些API在新版里已经废弃 ...

随机推荐

  1. Python的UI库

    https://github.com/realitix/vulkan https://github.com/swistakm/pyimgui https://wxpython.org

  2. Mongos WoW

    http://blog.csdn.net/yuleslie/article/details/7430094 https://github.com/mangostwo/ https://www.getm ...

  3. <string name="xxx"> 的复杂用法:格式化及使用html标签

    1.官方文档: https://developer.android.com/guide/topics/resources/string-resource 2.格式化字符串 2.1 示例 <res ...

  4. GitHub 热点速览 Vol.36:当股票遇到机器学习,异常股无所遁形

    作者:HelloGitHub-小鱼干 摘要:虽然上周的 GitHub Trending 榜新项目寥寥无几,但胜在表现不俗,例如:通过机器学习来检测异常股票的项目 Surpriver,还有腾讯开源的管理 ...

  5. Java8 日期和时间类

    新的日期和时间API 新的日期和时间类解决了Date和Calendar类出现的问题 浅尝 LocalDate 日期类 LocalDate of = LocalDate.of(2018, 7, 13); ...

  6. 跟着兄弟连系统学习Linux-【day04】

    day04-20200601 p15.链接文件 [ln -s 原文件   连接文件]软连接,所有人都可以操作软连接文件(实际上是取决于原文件的权限),类似于Windows的快捷方式,方便进行管理.软连 ...

  7. FFmpeg开发笔记(三):ffmpeg介绍、windows编译以及开发环境搭建

    前言   本篇章是对之前windows环境的补充,之前windows的是无需进行编译的,此篇使用源码进行编译,版本就使用3.4.8.   FFmpeg简介   FFmpeg是领先的多媒体框架,能够解码 ...

  8. Mybatis注解开发相关

    一.项目构建 1.Java项目目录结构 2.在domain包下创建User实体类 package sun.domain; import java.io.Serializable; import jav ...

  9. Solon详解(七)- Solon Ioc 的注解对比Spring及JSR330

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  10. linux6.4内核由2.6升级成3.6

    安装CentOS 6.4之后,内核默认是2.6.32.由于docker需要3.0以上的内核,所以需要对内核进行升级. 1. 安装必要组件# yum -y install ncurses-devel # ...