论坛首页 综合技术论坛

养成良好的编程习惯,提高代码质量

浏览 5485 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-01-23  

    “不积跬步,无以至千里,不积小流,无以成江海”,程序员如何提高代码质量?我们不仅要知其然,还要知其所以然,我们要从点点滴滴的积累开始的。这篇帖子里记录了编程时的应该注意的一些细节,如有需要后续还会补充,希望通过不断的积累,提高编程质量。

可序列化接口Serializable

类实现Serializable接口的目的是为了可持久化,比如网络传输或本地存储,为系统的分布或异步部署提供先决支持条件。若没有序列化,现在我们熟悉的远程调用,对象数据库都不可能存在。

    序列化和反序列化是对应的,以下用代码描述实现了序列化接口Serializable的类在磁盘上的存储过程及反序列化,其在网络上的传输道理也是一样的。

 

package org.iti.wxl.serializable;

import java.io.Serializable;

/**
 * 实现了Serializable的实体类
 *
 */
public class Person implements Serializable{
	
	private static final long serialVersionUID = 6388172609871883630L;
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

 为模拟序列化的过程我们创建序列化工具类,如下:

package org.iti.wxl.serializable;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializableUtils {
	private static String FILE_NAME="e:/obj.bin";
	//序列化数据保存到磁盘
	public static void writeObject(Serializable s){
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_NAME));
		    oos.writeObject(s);
		    oos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	//反序列化从磁盘读取数据
	public static Object readObject(){
		Object obj = null;
		try {
			ObjectInput input = new ObjectInputStream(new FileInputStream(FILE_NAME));
			obj = input.readObject();
			input.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return obj;
	}
}

序列化保存数据到磁盘上

package org.iti.wxl.serializable;
public class Producer {
	public static void main(String[] args) {
		Person p = new Person();
		p.setName("小明");
		// 序列化保存到磁盘上
		SerializableUtils.writeObject(p);
	}
}

反序列化,从磁盘读取数据:

package org.iti.wxl.serializable;

public class Consumer {
	public static void main(String[] args) {
		//反序列化
		Person p =(Person)SerializableUtils.readObject();
		System.out.println(p.getName());
	}
}

在反序列化时,若类的版本号serialVersionUID不一致,反序列化时会报一个InvalidClassexception异常,另外在反序列化时,类中的构造函数不会执行。

奇偶校验用偶校验,避免使用奇校验

JDK提供的奇偶校验代码模拟如下:

public class Remainder {
       //dividend被除数,divisor除数
	public static int remainder(int dividend, int divisor) {
		return dividend - dividend/divisor*divisor;
	}
}

 当使用取模运算“%”做奇偶校验时,JDK会依照以上公式进行运算,此时dividend为要校验的数,divisor=2我们发现当被除数为负数且为奇数时,余数为-1,如果我们的奇偶校验公式为i%2 =1 ? "奇数":"偶数";那么当i为负奇数时结果判断会错误,因此我们做奇偶校验时要用偶校验,即:i%2 == 0 ? "偶数":"奇数";

java中的引用问题

java中没有指针的概念,但我们要理解另一个名词“引用”。看下面的例子:

实体类

 

public class IntString {
	private Integer no;
	private String str;
	public Integer getNo() {
		return no;
	}
	public void setNo(Integer no) {
		this.no = no;
	}
	public String getStr() {
		return str;
	}
	public void setStr(String str) {
		this.str = str;
	}
	@Override
	public String toString() {
		return "IntString [" + (no != null ? "no=" + no + ", " : "")
				+ (str != null ? "str=" + str : "") + "]";
	}
}

测试类:

public class Test {
    public static void main(String[] args) {
		List<IntString> test = new ArrayList<IntString>();
		IntString is1 = new IntString();
		is1.setNo(1);
		is1.setStr("一");
		IntString is2 = new IntString();
		is2.setNo(2);
		is2.setStr("二");
		IntString is3 = new IntString();
		is3.setNo(3);
		is3.setStr("三");
		test.add(is1);
		test.add(is2);
		test.add(is3);
		List<IntString> newtest = new ArrayList<IntString>();
		newtest = test;
//		List<IntString> newtest = test;
		System.out.println("前" + newtest);
		test.get(0).setStr("1");
		System.out.println("后" + newtest);
	}
}

 输出结果:

前[IntString [no=1, str=一], IntString [no=2, str=二], IntString [no=3, str=三]]
后[IntString [no=1, str=1], IntString [no=2, str=二], IntString [no=3, str=三]]

程序中改变了test实体里的一个对象的某个参数的值,但是打印出newTest后发现它的内部对象值发生了变化,解释如下:newtest = test时,newTest和test两个名字虽然不一样,但是都指向同一块内存地址,test发生变化也就是newTest发生了变化。

java中基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double,对于非基本类型的对象类数据都是采用引用的方式来处理,那么在做赋值操作“=”时,是引用的赋值,两个不用名称的应用指向同一个地址,其中一个数值发生变化两个就都发生变化了。

另外,对于基本类型,JVM提供常量池,用到某数值的时从常量池里取值,这个时候用==判断是否相等,数值相等时一定相等,“==”判断的是地址相等。而对于非基本类型数值相等也不一定“==”,因此我们应该用equals方法来判断值相等,而对于在内存中只存在一份的判断可以用“==”例如字节码等。

 

 

 

论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics