java开发150个建议( 六 )


回到顶部
建议10:不要在本类中覆盖静态导入的变量和方法
如果在一个类中的方法及属性与静态导入的方法及属性相同会出现什么问题呢?看下面的代码
1 import static java.lang.Math.PI;2 import static java.lang.Math.abs;3 4 public class Client10 {5// 常量名于静态导入的PI相同6public final static String PI = "祖冲之";7//方法名于静态导入的方法相同8public static int abs(int abs) {9return 0;10}11 12public static void main(String[] args) {13System.out.println("PI = "+PI);14System.out.println("abs(-100) = "+abs(-100));15}16 }
以上代码中定义了一个类型的常量PI,又定义了一个abs方法,与静态导入的相同 。首先说好消息,代码没有报错,接下来是坏消息:我们不知道那个属性和方法别调用了,因为常量名和方法名相同,到底调用了那一个方法呢?运行之后结果为:
PI = "祖冲之",abs(-100) = 0;
很明显是本地的方法被调用了,为何不调用Math类中的属性和方法呢?那是因为编译器有一个"最短路径"原则:如果能够在本类中查找到相关的变量、常量、方法、就不会去其它包或父类、接口中查找,以确保本类中的属性、方法优先 。
因此,如果要变更一个被静态导入的方法,最好的办法是在原始类中重构,而不是在本类中覆盖.
建议11:养成良好习惯,显示声明UID
我们编写一个实现了接口(序列化标志接口)的类,马上就会给一个黄色警告:需要添加一个ID 。为什么要增加?他是怎么计算出来的?有什么用?下面就来解释该问题 。
类实现接口的目的是为了可持久化,比如网络传输或本地存储,为系统的分布和异构部署提供先决条件支持 。若没有序列化,现在我们熟悉的远程调用、对象数据库都不可能存在,我们来看一个简单的序列化类:
1 import java.io.Serializable;2 public class Person implements Serializable {3private String name;4 5public String getName() {6return name;7}8 9public void setName(String name) {10this.name = name;11}12 13 }
这是一个简单的,实现了接口,可以在网络上传输,也可以在本地存储然后读取 。这里我们以java消息服务(Java)方式传递对象(即通过网络传递一个对象),定义在消息队列中的数据类型为,首先定义一个消息的生产者(),代码如下:
1 public class Producer {2public static void main(String[] args) {3Person p = new Person();4p.setName("混世魔王");5// 序列化,保存到磁盘上6SerializationUtils.writeObject(p);7}8 }
这里引入了一个工具类,其作用是对一个类进行序列化和反序列化,并存储到硬盘上(模拟网络传输),其代码如下:
1 import java.io.FileInputStream;2 import java.io.FileNotFoundException;3 import java.io.FileOutputStream;4 import java.io.IOException;5 import java.io.ObjectInputStream;6 import java.io.ObjectOutputStream;7 import java.io.Serializable;8 9 public class SerializationUtils {10private static String FILE_NAME = "c:/obj.bin";11//序列化12public static void writeObject(Serializable s) {13try {14ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_NAME));15oos.writeObject(s);16oos.close();17} catch (FileNotFoundException e) {18e.printStackTrace();19} catch (IOException e) {20e.printStackTrace();21}22}23//反序列化24public static Object readObject() {25Object obj = null;26try {27ObjectInputStream input = new ObjectInputStream(new FileInputStream(FILE_NAME));28obj=input.readObject();29input.close();30} catch (FileNotFoundException e) {31e.printStackTrace();32} catch (IOException e) {33e.printStackTrace();34} catch (ClassNotFoundException e) {35e.printStackTrace();36}37return obj;38}39 }
通过对象序列化过程,把一个内存块转化为可传输的数据流,然后通过网络发送到消息消费者()哪里,进行反序列化,生成实验对象,代码如下: