1 重写hashCode规则 1 一个对象调用多次方法,方法返回值相同 2 两个对象调用equals方法true,hashCode相同 3 equals方法比较的field,都应该即使hashcode
2 hashset 用对象equals比较对象是否相等 TreeSet使用compateTo()比较相等,treeset中的对象必须实现compareable接口,
3 重写equals方法时,如果两个对象true 他们的hashcode应该相同(hashset)compareTo为0 (treeset)
4 TreeSet定制排序,传入实现comparator接口的一个类 该类有compare方法
5 Properities 类是hashtable子类,可以把map对象和属性文件关联起来,把map对象中的key-value对写入属性文件也可以把属性文件“属性名-属性值”加入map对象
public static void main(String[] args) throws Exception, IOException { Properties p = new Properties(); p.setProperty("dss", "ds"); p.getProperty("v", "dss"); p.store(new FileOutputStream("a.ini"), "comment line"); Properties p2 = new Properties(); p2.load(new FileInputStream("a.ini")); System.out.println(p2.getProperty("v")); System.out.println(p2); }
6 WeakHashMap的key只保留了对对象的弱引用,如果key引用的对象没有被其他强引用变量引用,key对象可能被垃圾回收,weakhashmap会删除key-value 对
public static void main(String[] args) throws Exception, IOException { WeakHashMap<String, String> map = new WeakHashMap<>(); map.put(new String("dssd"), new String("dssd")); map.put(new String("dss"), new String("dssd")); map.put(new String("dd"), new String("dssd")); // weak quote String s = "f"; map.put("s", new String("dssd")); // strong quote System.out.println(map); System.gc(); System.runFinalization(); System.out.println(map); } {dssd=dssd, dss=dssd, s=dssd, dd=dssd} {s=dssd}
7 Java参数化类型被称为泛型
8 所谓泛型:允许在定义类,接口,方法时使用类型参数,这个类型形参将在声明变量,创建对象,调用方法时动态指定(既传入实际类型参数,称为类型实参)
9 从泛型类派生子类,创建代泛型接口,父类后,可以为该接口创建实现类,或派生子类,但使用这些接口,父类时不能再包含类型形参
class Apple<T> { } class BlueApple extends Apple<T> { // error } class BlueApple1 extends Apple<String> { // true } class BlueApple2 extends Apple { // default true <Object> }
10 不管泛型类型参数传入哪种类型参数,他们被当成同一个类处理,只占一块内存空间,因此在静态方法,静态初始化块,静态变量的声明和初始化中不允许使用类型参数,instanceof 也不允许‘
public class My<T> { public static void main(String[] args) { ArrayList<String> l1 = new ArrayList<>(); ArrayList<Integer> l2 = new ArrayList<>(); System.out.println(l1.getClass() == l2.getClass()); // true if (l1 instanceof ArrayList<String>) { // error } } static T a; // error static void f() { T b; // error } static { T c; //error } }
11 类型通配符 ? 为了表示各种泛型List的父类,需要使用类型通配符(?), 将一个问号作为类型实参传给List集合,LIst<?>,他的元素类型可以匹配任何类型。表示各种泛型List的父类,不能把元素加入其中
public class My { public static void main(String[] args) { List<?> c = new ArrayList<>(); c.add("ffs"); // error } void test(List<?> l) { for (int i = 0; i < l.size(); i++) { System.out.println(l.get(i)); } } }
12 通配符上限 LIst<?> 表示List集合是任何泛型List的父类,但如果只想表示它是一类泛型List的父类,可以使用List<? extends Class> 所有class泛型父类
abstract class Shape { public abstract void draw(Canvas c); } class Circle extends Shape { @Override public void draw(Canvas c) { // TODO Auto-generated method stub System.out.println("draw circle on " + c); } } class Rectangle extends Shape { @Override public void draw(Canvas c) { // TODO Auto-generated method stub System.out.println("draw Rectangle on " + c); } } class Canvas{ public void drawAll(List<Shape> list) { for (Shape shape : list) { shape.draw(this); } } public void drawAll(List<?> list) { for (Object shape : list) { ((Shape)shape).draw(this); } } public void drawAll(List<? extends Shape> list) { for (Shape shape : list) { shape.draw(this); } list.add(new Circle()) // error dont't know the Class ? , so don't add } }
13 设定类型形参上限
既允许在使用通配符形参时设定上限,还可以在定义类型形参时设定上限,表示传递给类型形参的实际类型要么是该上限类型,要么是其子类
class Apple<T extends Number> { public static void main(String[] args) { Apple<Number> a = new Apple(); Apple<Integer> b = new Apple(); Apple<String> c = new Apple(); // error } }
14 通配符下限
<? super Type> 必须是type或type的父类。用于接收元素
class MyUtils { // 会丢失类型 public static <T> T copy(Collection<T> c1, Collection<? extends T> c2) { T t = null; for(T i : c2) { t = i; c1.add(t); } return t; } // good public static <T> T copy(Collection<? super T> c1, Collection<T> c2) { T t = null; for(T i : c2) { t = i; c1.add(t); } return t; } }
15 泛型方法
在定义类,接口时没有使用泛型,但定义方法时想自己定义类型形参,这是可以的
在声明方法时定义一个或多个类型形参。
class MyUtils { // 只能复制object型 Collection<String...> 不是 Collection<Object>子类 public void fromArrayToCollection(Object[] o, Collection<Object> ob) { for (Object object : o) { ob.add(object); } } //good public <T> void fromArrayToCollection(T[] o, Collection<T> ob) { for (T object : o) { ob.add(object); } } }
16 类型擦除
当把一个具有泛型信息的对象赋给没有泛型信息的变量时,尖括号间 类型信息都被扔掉,类型参数为原始类型,声明参数时第一个上限类型
public static void main(String[] args) { List<Integer> l = new ArrayList<>(); l.add(1); List l2 = l; // 类型擦除 String s = (String) l2.get(0); // 编译无错, 运行 java.lang.ClassCastException: }
17 error 一般指与虚拟机相关的问题,如系统崩溃,虚拟机错误,动态连接失败,无法恢复或不可捕获,导致应用程序中断。
18 catch 捕获多种类型异常 1 多异常间用| 分开 2 异常变量有隐式final修饰,不能对异常变量赋值。
public class My { public static void main(String[] args) { try { int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); int c = a / b; System.out.println(c); } catch (IndexOutOfBoundsException | NumberFormatException | ArithmeticException e) { e = new ArithmeticException(); // error e is final } catch (Exception e) { // TODO: handle exception } } }
如果在异常处理代码中使用system.exit(1) 语句退出虚拟机,finally块将失去执行机会
19 自动关闭资源try语句。1 资源类必须实现autocloseable或closeable接口,2 把需要关闭的资源定义在try块后括号内
public static void main(String[] args) { try (PrintStream p = new PrintStream(new FileOutputStream("a.txt"))) { p.print("df"); } }
public class My { public static void main(String[] args) throws FileNotFoundException { try (PrintStream p = new PrintStream(new FileOutputStream("a.txt"))) { p.print("df"); } } }
20 Check异常处理
1 如果当前方法知道如何处理异常,使用try ... catch捕获异常,处理
2 否则,在定义方法时声明抛出异常。throws抛出异常限制:方法重写,子类方法声明抛出的异常类型应该是父类方法声明抛出异常的子类或相同,子类方法声明抛出的异常不允许比父类方法声明抛出异常多。
’