您的位置:首页 > 其它

大作业心得记录及错误分析

2013-06-06 15:46 225 查看
写到迭代三了,前面的代码逻辑写的不够好,复用代码是件很头痛的事情,socket编程也出现了各种奇葩的错误

挖个坑记录一下出现的错误和解决方案,以及用到的一些小技巧。

1.空指针异常 NullPointerException

比较常见的错误。经常由于只声明了引用,而没有新建对象给引用造成。用ArrayList时经常出现

2.main方法中不能新建内部类的对象

解决方法:新建一个其他方法调用,main中调用该方法

3.Socket发送写到自建的send()方法里

4.setContentPane() 多个JPanel类, 可以轻松实现多个界面跳转,个人感觉比cardLayout好用

5.把命令封装在不同的xxxCmd类中,xxxCmd实现接口Command,接口Command:excute(); 各自实现

6.EOF异常

7.

setOpaque(true);设置控件不透明
setOpaque(false);设置控件透明

8.java.io.InvalidClassException异常

java.io.InvalidClassException: server.CourseSystem; local class incompatible: stream classdesc serialVersionUID = 6006469664506583150, local class serialVersionUID = 5860300662680845999

at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)

at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)

at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)

at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)

at helper.SocketHelper.deSerialization(SocketHelper.java:113)

at server.Server$Start.run(Server.java:119)

at java.lang.Thread.run(Thread.java:722)

解决方案:

a.将本地的序列化的类中的版本号(serialVersionUID )改成和远程中一样
b.重新建了项目,拷贝过去。。居然也可以

9.依然是序列化错误。java.io.NotSerializableException:

查询资料:

序列化对类的处理原则

并不是一个实现了序列化接口的类的所有字段及属性都是可以序列化的。分为以下几个部分来说明:

1、 如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列化接口。则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接口,则该类的父类所有的字段属性将不会序列化。

2、如果该类的某个属性标识为static类型的,则该属性不能序列化;

3、如果该类的某个属性采用transient关键字标识,则该属性不能序列化;

需要注意的是,在我们标注一个类可以序列化的时候,其以下属性应该设置为transient

来避免序列化:

(1) 线程相关的属性;

(2) 需要访问IO、本地资源、网络资源等的属性;

(3) 没有实现可序列化接口的属性;(注:如果一个属性没有实现可序列化,而我们又没有将其用

transient 标识, 则在对象序列化的时候, 会抛出java.io.NotSerializableException 异常)。 构造函数和序列化

4、对于父类的处理,如果父类没有实现序列化接口,则其必须有默认的构造函数(即没有参数的构造函数)如果没有给父类一个默认构造函数,则编译的时候就会报错。在反序列化的时候,如果父类也是可序列化的话,则其默认构造函数也不会 调用。Java 对序列化的对象进行反序列化的时候,直接从流里获取其对象数据来生成一个对象实例,而不是通过其构造函数来完成,毕竟我们的可序列化的类可能有多个构造函数,如果我们的可序列化的类没有默认的构造函数,反序列化机制并不知道要调用哪个构造函数才是正确的。

serialVersionUID作用

java在序列化的时候涉及到很多检查,serialVersionUID就是其中一个。

那这个serialVersionUID有什么用处?

这个值可以由类指定,也可以不指定。如果不指定的话java会根据class计算serialVersionUID,相当于hash的原理(但不是hash不要混淆),只要类没有变化,计算出来的serialVersionUID也会变化。

它用在反序列化的时候“检查”当前的类是不是已经被修改过。如果发现serialVersionUID对不上号,那么会抛出 java.io.InvalidClassException的异常,这种情况发生在由于种种因素修改了序列化对象的类文件时。

但是有时候我们有这样的需求,将A类对象序列化之后,版本升级,修改了A类,这时候,希望反序列化的时候还能认识之前版本的序列化对象。这时候serialVersionUID就在笑了,对,只要指定序列化对象类的serialVersionUID就可以了。

指定了序列化对象的serialVersionUID,即使你删除了类的某个成员变量,其他未修改信息仍然能正确解析,对他就是这么变态。

Java
的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的 serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

  当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量 时,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的 class才会生成相同的serialVersionUID 。

  如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
最后处理方法:把实现了serializable接口中,不可序列化的加了transient

10.推选课程后,表中信息不能立刻消失。。。还未解决

11.各种奇葩的空指针异常QAQ不能忍啊


12.又出现了新问题:选课后,再退出重登陆,在学生选课列表里课程会消失,但是课程仍然持有该学生。。为什么会消失(已解决

13.检查功能是否完备

14.发现问题:当教师修改课程信息后,学生已选择的课程信息不会随之更新

还需要完善的功能

选课时确保不重复
对老师和学生列表的维护中,是否需要删除功能
老师的查看课程分为查看自己的课程和全部课程
修改课程时只能改自己的课程,否则提示受限

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐