rss· 投稿· 设为首页· 加入收藏· 繁體版
当前位置: 火魔网 » 程序开发 » Java基础

java pitfalls

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。

顶一下
(0)
踩一下
(0)