1. 有些方法不能覆盖:静态方法(static)和最终方法(final)不会被覆盖,在编译时期就可以确定说要调用的具体方法;如果他们和实例方法同名时,编译器就会报错,所以他们没有多态性。
2. 逻辑判断用equals而不是==:String有intern函数可以取得常量池中唯一字符串,所以s1.intern()==s2.intern()和s1.equals(s2)等价,但这种方法并不推荐,也不适于其他类。
3. java是强类型语言:需要时可以自动扩展基本类型(或向上转型),而窄化类型(或向下转型)需要显示转换,byte b=4也能编译但不是普遍规律。
4. 构造函数没有返回类型,若有只是默认与类名相同。
5. 被覆盖的方法只有通过super.function()访问,将子类强制转换为父类都不行。
6. 变量可能被隐藏:局部变量隐藏类变量或实例变量,子类变量隐藏父类变量。
7. 类变量不能提前引用后面声明的变量,静态方法也不能提前引用。
8. 构造函数不宜做太多工作以免影响继承。
9. 基本类型的包装类型可以引用传递。
10. 优先使用短路布尔运算。
11. 使用SoftReference包装的对象就像回收站一样在虚拟机内存不够时自动释放。
12. 同步方法中调用同步方法易造成死锁。
13. 正确地克隆对象:实例变量要调用其clone进行深拷贝,不变量(基本类型,String,Integer)等不需要,因为每次复制都是新的,不会影响原来的对象。
14. 类的对象将用于映射中时,即作为键使用时,请覆盖equals和hashCode方法。
15. 总是使用super.clone克隆对象,不要试图调用构造函数建立内容相同的对象,它不能转换为子类,而super.clone是影子复制,将当前对象拷贝一份,所以能够正确转换类型。
16. 反射、接口和匿名类的方法调用:反射可以参数[]args向对象objs分派操作methods,这些methods不必要求同样的方法名和参数个数;接口要求同样的方法实现,多态地分派方法;匿名类可以具体化抽象类,在每个地方提供独特的处理逻辑;
17. 可以捕捉OutOfMemoryError然后清理内存让程序继续执行,比如清空map等。
18. 有序的属性键:Properties的keys()返回的属性集是哈希顺序,而不是属性文件中的顺序,如果要保持属性文件中的顺序,可以扩展它(put和remove),使用额外的ArrayList来保存属性键的顺序,工具类EnhancedProperties。
19. 使用缓存和持久性机制处理偶发性超大集合:工具类PersistentCacheVector和ObjectFile。
20. 合理使用属性文件和ResourceBoundle:Properties和EnhancedProperties可以处理属性配置文件,而ResourceBoundle更适合于处理国际化资源文本。
21. 属性对象的路径问题:使用Class对象加载属性文件时,路径“/myApp.properties”是绝对的,只在根目录查找属性文件,而路径“myApp.properties”是相对的,会在所有资源目录中自动寻找属性文件。
22. 使用集合中的新API:使用Iterator而不是Enumeration。
23. 序列化:Image对象序列化后会变大,因为它默认将缓存图像也保存了,这时可以继承ImageIcon实现Extenalizable接口通过read/writeExternal完全控制序列化内容。
24. 流的分类与字符编码:输入或输出,字节或字符,数据流或过滤流。使用过滤流可以形成链。使用InputStreamReader可以指定字符编码读取字节流,常用的有utf、gbk等。
25. 使用套接字收发序列化对象:客户端建立Socket(host,port),用ObjectInputStream和ObjectOutputStream包装Socket的输入输出流。服务器端建立ServerSocket(port),调用accept方法监听端口,当有请求时返回一个Socket,包装一下就可以在单独的线程中跟客户端通信。
26. finally块的便利性:文件读写等处理异常时将关闭文件等清理工作放在finally块中,而不是try中或各个catch中。
27. 刷新图像资源:使用Image的flush方法保证图像数据重新建立或从源读取,否则将总是使用缓存的图像而不更新。
28. 提供进度反馈:使用忙指针,并保存恢复旧指针;使用进度监控器ProgressMonitor、Measurable、Timer协同工作,Timer间隔一段时间就从Measurable读取进度值,告诉ProgressMonitor并显示出来,后者也可以提供cancel的反馈。
29. 重新布局组件:组件重绘可以使用repaint,但容器有一些不同,需要同时使用invalidate(告诉容器当前布局不合法)、validate(检查布局是否合法,若不合法将导致重新布局)、repaint(重绘组件)。组件被删除时可只使用repaint。
30. Z-Order与重叠的组件:添加组件时add(component)先加的在上面,后加的在下面;如果指定索引add(component,0),则后加的在上面;但更好的是使用JLayeredPane,他的方法add(component,object)可以接受Integer参数指定Z-Order,并且有预定义的常量JLayeredPane.DEFAULT_LAYER等可以使用,这个参数越小,就越在后面。
31. 重绘组件的谜题:revalidate会invalidate调用它的组件及所有父组件,然后被传给RepaintManager检查第一个isValidateRoot返回true的父组件(如JScrollPane、JRootPane、JTextField),然后递归地validate所有子组件;repaint只是重绘dirty区域,并不会迫使重新布局;validate将重新布局所有子组件。所以如果JScrollPane的组件需要更新,可以对它调用validate,也可以对它的组件调用revalidate方法(这样比较绕一些)。
32. 垂直排列组件:GridBagLayout和嵌套容器解决得并不是很好;可以使用定制的VerticalFlowLayout;或者BoxLayout和Box.createVerticalBox()创建垂直布局的容器。
33. 恰当地使用GridBagLayout:每个组件相关的GridBagConstraints都会有拷贝,所以实际使用时可以只实例化一个约束对象;gridx、gridy、gridwidth、gridheight指定位置和计算长宽,weightx、weighty计算多余空间(可能会忽略某些列);这些计算结果都可以用指定columnWeights、columnWidths、rowWeights、rowHeights为double或int数组来覆盖,这样所有的列都按要求显示了(标准网格和拉伸比例)。
34. 避免闪烁:(AWT)系统重绘使用paint,应用级重绘使用repaint,它会导致update方法被调用。默认情况下update会清除背景再调用paint,这样就导致闪烁;如果覆盖update方法,只让它调用paint,闪烁会好一些,但paint描绘背景时也会清除前景,所以还有一些闪烁;我们还可以更模块化一点,将绘制分为paintBackground和paintForeground,而update只是paintForeground,paint两个都调用,这样所有的闪烁都消失了。Swing的每个JComponent都使用双缓冲来绘制自己(默认使用),即先被绘制在第二个缓冲区内,然后再转移到屏幕上,在系统级上解决了AWT中的闪烁问题;这时可以覆盖paintComponent和使用clipping区域使重绘更加高效。
35. 支持HTML的组件:JButton、JLabel、JMenuItem、JMenu、JCheckBoxMenuItem、JRadioButtonMenuItem、JTabbedPane、JToolTip;只是支持HTML标记的一个子集,如html、b、u、i、br等。
36. 数据有效性验证:过滤器(输入时阻止非法字符的键入)FilterAdapter和验证器(输入后验证数据合法性)ValidatorAdapter。
37. 根据状态启用或禁用组件:StateMonitor。
38. 事件处理中使用线程以避免冻结主界面:调用线程的interrupt可以中断它,最好是设置标志flag让线程子集结束。
39. JTree的模型:树JTree可以用DefaultMutableTreeNode作为root节点构建,但向roo添加删除子节点后JTree并没有同步更新,根据模型、视图、控制器的设计应该是模型的更改会导致视图的更新,实际上JTree使用的是DefaultTreeModel作为模型,应该用root构建model,再用model构建tree,并用model.insertNodeInto(node,root,index)添加节点。
40. 转移非文本数据:数据包含在Transferable接口的具体实现中,然后通过Clipboard传递,数据类型由DataFlavor的静态常量标识。
41. JComboBox是个容器:它包含JButton(视外观会有不同)、CellRenderer、ComboBoxEditor(如果可编辑),因此在JComboBox上注册KeyListener并没有效果,简单的解决办法是注册到子组件上(现在的JComboBox已经支持page_up,page_down)。
42. 打印JEditorPane中的文本、超文本和图像:PrinterJob控制打印,PageFormat设置页面,Printable为可打印对象,Pageable表示可打印对象的集合。JComponent有printAll方法。
43. 延迟加载:如设置界面
44. 对大量对象使用对象池:JavaSpaces技术。
45. 数组与矢量对比:装对象用矢量,而基本类型用数组+矢量的容量倍增策略和System.arrayCopy。ArrayList是比Vector更轻量级的,并且Collections.synchronizedList也能让它有同步能力。
46. 对于动态增长的数组避免使用临时数组,而用矢量。
47. 循环体类字符串不用+,而用StringBuffer或StringBuilder。
48. 可配的调试日记开关:系统变量控制,不需要更改代码。
49. 用接口封装JNI调用:在本地代码与java之间用接口抽象,简化JNI调用。
50. java中的断言:assert。