《编写高质量代码:改善Java程序的151个建议》的一些笔记

一、int 最大值为2147483647,若计算溢出,则结果为负值。java

如,2147483647+1,结果为-2147483648。apache

因此,若是一个方法接收的是int 类型的参数,那如下三个值是必测的:0、正最大、负最小,其中正最大和负最小是边数组

界值。dom

二、包装类型的比较大小
ide

Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.println(i == j);   //false
System.out.println(i > j);    //false
System.out.println(i < j);    //false

在Java 中“==”是用来判断两个操做数是否有相等关系的,若是是基本类型则判断值是否相等,若是是对象则判断是不是一个对象的两个引用,也就是地址是否相等,这里很明显是两个对象,两个地址,不可能相等。工具

因此,比较包装类型的大小,用compareTo 方法,相等返回0,小于返回-1,大于返回1。ui

三、随机数
spa

在Java 中有两种方法能够得到不一样的随机数:经过java.util.Random 类获得随机数的原理和Math.random 方法相同,Math.random() 方法也是经过生成一个Random类的实例,而后委托nextDouble() 方法的。code

Random类的默认种子(无参构造)是System.nanoTime() 的返回值(JDK 1.5 版本之前默认种子是System.currentTimeMillis() 的返回值)对象

随机数的产生取决于种子,随机数和种子之间的关系听从如下两个规则:a、种子不一样,产生不一样的随机数。b、种子相同,即便实例不一样也产生相同的随机数。

因此,若非必要,不要设置随机数种子。


四、静态变量

静态变量是在类初始化时首先被加载的,JVM 会去查找类中全部的静态声明,而后分配空间,这时候只是完成了地址空间的分配,尚未赋值,以后JVM 会根据类中静态赋值(包括静态类赋值和静态块赋值)的前后顺序来执行。

static {
		i = 100;
	}
	public static int i = 1;
	public static void main(String[] args) {
		System.out.println(i); //结果为1
	}

public static int i = 1;
	static {
		i = 100;
	}
	public static void main(String[] args) {
		System.out.println(i); //结果为100
	}

静态变量是类加载时被分配到数据区(Data Area)的,它在内存中只有一个拷贝,不会被分配屡次,其后的全部赋值操做都是值改变,地址则保持不变。

五、静态方法

实例对象有两个类型:表面类型(Apparent Type)和实际类型(ActualType),表面类型是声明时的类型,实际类型是对象产生时的类型。

静态方法不依赖实例对象,它是经过类名访问的;其次,能够经过对象访问静态方法,如果是经过对象调用静态方法,JVM 则会经过对象的表面类型查找到静态方法的入口,继而执行之。

public class StaticMethod {
	public static void main(String[] args) {
		Base base = new Sub();
		// 调用非静态方法
		base.doAnything();    //结果,我是子类非静态方法
		// 调用静态方法
		base.doSomething();   //结果, 我是父类静态方法 
	}
}
class Base{
	// 父类静态方法
	public static void doSomething(){
		System.out.println(" 我是父类静态方法");
	}
	// 父类非静态方法
	public void doAnything(){
		System.out.println(" 我是父类非静态方法");
	}
}
class Sub extends Base{
	// 子类同名、同参数的静态方法
	public static void doSomething(){
		System.out.println(" 我是子类静态方法");
	}
	// 覆写父类的非静态方法
	@Override
	public void doAnything(){
		System.out.println(" 我是子类非静态方法");
	}
}

六、构造代码块

public class Client {
    {
        // 构造代码块
        System.out.println(" 执行构造代码块");
    }
    public Client(){
        System.out.println(" 执行无参构造");
    }
    public Client(String _str){
        System.out.println(" 执行有参构造");
    }
}

至关于

public class Client {
    public Client(){
        System.out.println(" 执行构造代码块");
        System.out.println(" 执行无参构造");
    }
    public Client(String _str){
        System.out.println(" 执行构造代码块");
        System.out.println(" 执行有参构造");
    }
}

七、若是一个类不容许实例化,就要保证“日常”渠道都不能实例化它。

public class UtilsClass {
    private UtilsClass(){
        throw new Error(" 不要实例化我! ");
    }
}

八、浅拷贝

 Object 提供了一个对象拷贝的默认方法clone(),实现Cloneable 接口就具有了拷贝能力,拷贝规则以下:

(1)基本类型,若是变量是基本类型,则拷贝其值,好比int、float 等。

(2)对象,若是变量是一个实例对象,则拷贝地址引用

(3)String 字符串,这个比较特殊,拷贝的也是一个地址,是个引用,可是在修改时,它会从字符串池

(String Pool)中从新生成新的字符串,原有的字符串对象保持不变,在此处咱们能够认为String 是一个基本类型。

九、hashCode

Map 的底层处理机制是以数组的方式保存Map 条目(Map Entry)的,这其中的关键是这个数组下标的处理机制:依据传入元素hashCode 方法的返回值决定其数组的下标,若是该数组位置上已经有了Map 条目,且与传入的键值相等则不处理,若不相等则覆盖;若是数组位置没有条目,则插入,并加入到Map 条目的链表中。同理,检查键是否存在也是根据哈希码肯定位置,而后遍历查找键值的。

Set  集合是按hashCode来判断对象是否相等。

HashCodeBuilder 是org.apache.commons.lang.builder 包下的一个哈希码生成工具。

相关文章
相关标签/搜索