概述
“不积跬步,无以至千里,不积小流,无以成江海”,程序员如何提高代码质量?我们不仅要知其然,还要知其所以然,我们要从点点滴滴的积累开始的。这篇帖子里记录了编程时的应该注意的一些细节,如有需要后续还会补充,希望通过不断的积累,提高编程质量。
可序列化接口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方法来判断值相等,而对于在内存中只存在一份的判断可以用“==”例如字节码等。
最后
以上就是正直鱼为你收集整理的养成良好的编程习惯,提高代码质量的全部内容,希望文章能够帮你解决养成良好的编程习惯,提高代码质量所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复