- 每个Java对象都有一个toString方法,有时我们会无意识的在toString方法中使用this,此时就需要注意了,一不小心就会无意识的递归,先看下面的代码:
在toString方法中使用this,当使用toString时,就无限的递归了该方法,解决的方法是:把 this 改为 super.toString()。public class Test { @Override public String toString() { return "memery address: " + this; } public static void main(String[] args) { Test test = new Test(); System.out.println(test); } }
- 正则表达式使用了Pattern和Matcher两个类,Pattern是线程安全的,Mattcher不是线程安全的。
- 使用".class"生成对象的引用不仅简单,而且安全,因为它在编译时就会受到检查(因此不需要置于try块中),而且它根除了对forName()的调用,所以更高效。
- 使用".class"生成对象的时候,不会自动的对该对象进行初始化,初始化会被延迟到对静态方法(构造方法隐式的也是静态的)或非常数静态域进行首次引用时。
- 泛型方法可以独立于类而产生变化,在编码时应尽量使用泛型方法,也就是说,如果使用泛型方法可以取代整个类的泛型化,就应该使用泛型方法,因为它可以使事情更清晰。
- 对于static方法,它无法访问泛型类的类型参数,所以,如果static方法要使用泛型,就必须使其成为泛型方法。
- 定义泛型方法,只需将泛型参数置于返回值之前。例如:public <T> String method(){}
- 当使用泛型类时,必须在创建对象时指定参数类型,而用泛型方法时就不必指明参数类型,因为编译器会为我们找出具体的类型,这称为类型参数推断(type argument inference)。
- 类型推断只对赋值操作有效,其他时候不起作用。如果将一个泛型方法调用的结果作为参数传递给另一个方法,编译器并不执行类型推断。
- 在泛型方法中可以显示的指明类型,通过在点操作符和方法名之间插入带尖括号的类型参数。如果是在定义该方法的内部,必须在点操作符之前使用this,如果是使用static方法,必须在点操作符前加类名。
public class Test { public static void main(String[] args) { M m = new M(); System.out.println(m.<String> f());//点操作符和方法名之间插入带尖括号的类型参数 System.out.println(m.g()); System.out.println(M.<String> h());//如果是使用static方法,必须在点操作符前加类名 } } class M { <T> int f() { return 3; }; int g() { this.<String> f();//如果是在定义该方法的内部,必须在点操作符之前使用this return 4; } static <T> int h() { return 5; } }
- 集合Collection接口有两个重要的字接口List和Set。List中可以有重复的元素,Set中不能有重复的元素。
- 对于Set的选择,一般情况下使用HashSet,LinkedHashSet及TreeSet。HashSet是最常用的,查询速度最快,整体性能最好的,对于没有特殊要求是就选用HashSet,而LinkedHashSet则保持了元素的插入顺序,TreeSet则会把插入的元素以某种规则排序,是有序的Set。
- 对于List的选择,一般情况下使用ArrayList和LinkedList。对于有随机查询访问速度需求是选用ArrayList,因为它底层是基于数组的,而对于插入删除操作则选用LinkedList,它底层是基于节点的。
- 对于Map的选择通常有HashMap,TreeMap和LinkedHashMap,和Set的选择类似,HashMap是最常用的,查询速度最快,整体性能最好的,对于没有特殊要求是就选用HashMap,而LinkedHashMap比HashMap慢一些,保持了元素的插入顺序,TreeMap则会把插入的元素以某种规则排序,是有序的Map。
- 序列化的对象要实现Serializable接口,序列化对象时会序列化对象里面的所有成员变量,除了transient变量和static变量。若包含对象变量,若包含该对象变量未实现Serializable接口,就不能序列化成功。
- 对于想特殊处理精确控制的对象,要使用精确定义的方法
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
private void readObjectNoData() throws ObjectStreamException;
在序列化的时候,这些方法会自动的调用。在调用ObjectOutputStream.writeObject()时,会检查所传递的Serializable对象,看它是否实现了自己的writeObject()。如果实现了,就跳过正常的序列化并调用它的writeObject(),在writeObject()内部,可以调用defaultWriteObject()来选择默认的writeObject()。readObject()也是一样。transient成员变量也可以在这两个方法中得到序列化。 - 也可以通过实现Externalizable接口来序列化,Externalizable和Serializable的区别在于:Serializable对象是以存储的二进制为基础来构造对象的,而不调用构造器;而对于一个Externalizable对象,会调用默认的构造器,然后调用readExternal()方法;Serializable是自动序列化的,而Externalizable却不是自动序列化,要手动在writeExternal()中实现序列化。
- 枚举在添加方法的时候,要在所有的枚举实例最后添加';'号,且枚举的构造函数只能是private的,没有声明是也是private。
enum Color { RED("this is red"), BLUE("this is blue"), GREEN("this is green");//枚举常量最后添加; private String des; //构造函数是private的 private Color(String des) { this.des = des; } public String getDescription() { return des; } }
- 枚举类是final的,不能被继承,但可以实现接口。对枚举而言,实现接口是使其子类化的唯一来源。
- 枚举的每一个实例都是public static final的。