一些定义及经验
单方法接口:只含有一个方法的接口。
标识接口:没有任何方法和属性的接口。通常使用在工具类中,不推荐过多的使用这种接口。
常量接口:来声明一些常量的接口。不建议使用这种接口。
预定式键值存储方法:在请求一个键值时,首先将数据库中的键值更新为下一个可用之,然后将旧值提供给客户端。预定式键值存储方法可以每一次预定多个键值(即一个键值区间)。
记录式键值存储方法:键值首先被返还给客户端,然后记录到数据库中去。缺点:键值可能重复。
克隆满足的条件:
1、 对任何对象x,都有x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。
2、 对任何对象x,都有:x.clone().getClass == x.getClass(),换言之,克隆对象与原对象的类型一样。
3、 如果对象x的equals()方法定义恰当的话,那么x.clone().equals(x)应当是成立的。
假设被克隆的对象按照它们的内部状态是否可变,划分成可变对象和不变对象的话,那么可变对象和不变对象所提供的equals()方法的工作方式应当是不同的。
可变对象只有当它们是同一个对象时,equals()才会返回true,所以这样的类型可以直接从java.lang.Object继承这个方法。 对象必须含有相同的状态才可能满足这个条件,因此不变类型必须自行实现这个equals()方法。
克隆分浅克隆和深克隆两种。
浅克隆(浅复制):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
深克隆(深复制):被复制对象的所有的变量都含有与原来的对象相同的值,出去那些引用其他对象的变量。那些引用其他对象的变量讲指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制要把复制的对象所引用的对象都复制了一遍,而这种对被引用到的对象的复制叫做间接复制。在深复制过程中,很可能会出现循环引用的的问题,必须小心处理。
利用串行化来做深复制:把对象写到流里德过程就是串行化(Serilization)过程,在Java程序师圈子里有非常形象地成为“冷冻”或者“腌咸菜(pickling)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜”(depickling)过程。写到流里德是对象的拷贝,而原对象让然存在于JVM里面,因此“腌成咸菜”的指示对象的一个拷贝,Java咸菜换可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到流里,在从流里读回来,便可以重建对象。
代码如下:
Public Object deepClone()
{
//讲对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读回来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return(oi.readObject());
}
满足下面四个条件之一的类不应当串行化:
1、 一个类与本地代码(native code)有紧密的关系。比如java.util.zip.Deflater就是一个例子。
2、 对象的内部状态依赖于Java虚拟机或运行环境,而从在每一次运行时这个状态都有可能不同。比如java.lang.Thread,java.io.InputStream,java.io.FileDescriptor,java.awt.PrintJob等。
3、 串行化可能带来潜在的安全隐患。比如,java.lang.SecurityManager以及java.security.MessageDigest等。
4、 一个类仅仅是一些静态方法的存放地,并没有任何的内部状态。比如,java.beans.Beans和java.lang.Math便是此类。
Java I/O库具有两个对称性:
1、 输出-输入对称:比如InputStream和OutputStream各自占据Byte流的输入与输出的两个平行的等级结构的根部,而Reader和Writer各自占据Char流的输入与输出的两个平行的等级结构的根部。
2、 byte-char对称:InputStream和Reader的子类分别负责Byte和Char流的输入;OutputStream和Writer的子类分别负责Byte和Char流的输出,他们分别形成平行的等级结构。
有些人常常用设计模式(Design Pattern)一词来指所有直接处理软件的架构、设计、程序实现的任何种类的模式。另外一些人则强调要划分三种不同层次的模式:架构模式(Architectural Pattern)、设计模式(Design Pattern)、成例(Idiom)。成例有时称为代码模式(Coding Pattern)。
架构模式(Architectural Pattern):一个架构模式描述软件系统里的基本的结构组织或纲要。架构模式提供一些事先定义好的子系统,指定它们的责任,并给出把它们组织在一起的法则和指南。有些作者把这种架构模式叫做系统模式。一个架构模式常常可以分解成很多个设计模式的联合使用。
设计模式(Design Pattern):一个设计模式提供一种提炼子系统或软件系统中的组件或者它们之间的关系的纲要设计。设计模式描述普遍存在的在相互通信的组件中重复出现的结构,这种结构解决在一定的背景中的具有一般性的设计问题。
代码模式或成例(Coding Pattern或Idiom):代码模式(或成例)是较低层次的模式,并与编程语言紧密相关。代码模式描述怎样利用一个特定的编程语言的特点来实现一个组件的某些特定的方面或关系。
为了做到应用层的保护,建议使用如下的保护措施:
1、 使用带有秒的hashing功能,比如md5sum进行数据完整性的核查。
2、 使用像DES这样的行业标准加密算法对数据进行加密(DES即Data Encryption Standard)。
3、 列出所有可能的用户端的无效输入,并在用户输入检查过程中加以排除。
为了保护信息系统的安全,设计师必须要做到以下两点:
1、 系统必须在服务器一端也进行基于安全考虑的用户输入数据的检查。虽然浏览器内部的JavaScript也可以用来对输入数据进行合法性检查,但是恶意用户可以使用诸如Achilles等软件将传到客户端的网页做相应的修改,再传到浏览器上。这样恶意用户可以将妨碍其恶意操作的JavaScript轻易地去掉。
2、 不可将系统内部出错的信息传给客户端,不可以将含有详细程序错误信息的出错信息传给浏览器。
Timer类实际上是用Object.wait(long)方法实现定时的,因此,Timer类不能保证实时效果。Timer类可以处理多达几千个任务。
变量被声明时的类型叫做变量的静态类型(Static Type),有些作者又把静态类型叫做明显类型(Apparent Type);而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type)。这种根据对象的类型而对方法进行的选择,就是分派(Dispatch)。
分派分为两种:静态分派和动态分派。
静态分派(Static Dispatch)发生在编译时期,分派根据静态类型信息发生。比如方法重载(Overloading)。
动态分派(Dynamic Dispatch)发生在运行时期,动态分派动态地置换掉某个方法。如置换(Overriding)。
一个方法所属的对象叫做方法的接收者,方法的接收者与方法的参量统称做方法的宗量。
根据分派可以基于多少种宗量,可以将面向对象的语言划分为单分派(Uni-Dispatch)语言和多分派(Multi-Dispatch)语言1。单分派语言根据一个宗量的类型进行对方法的选择,多分派语言根据多于一个的宗量的类型对方法进行选择。
多重分派(Multiple Dispatch)与多分派(Multi-Dispatch)的区别:多重分派是由一系列的单分派组成的分派过程;而多分派则是不能分解成为多个单分派的分派过程。
C++和Java以及Smalltalk均是单分派语言。
Java语言支持静态的多分派和动态的单分派。