对象序列化对象流国际化.ppt
对象序列化的概念,对象的持续性可以永久性保存一个对象的状态并在需要时获取该对象的信息(重新创建一个完全相同的对象);对象序列化通过写出对象的状态数据来记录一个对象。对象序列化的主要任务:写出对象所有成员变量的值,包括引用类型成员变量对应的对象的信息。,对象序列化的概念,目标:将对象保存到磁盘或者在网络中传递通过对象序列化,可以将对象保存在磁盘或网络中为了实现对象序列化,对应的类必须实现下面的两种接口之一:SerializableExternalizable,对象序列化的实现方式,要序列化一个对象,其所属的类必须实现以下两种 接口之一:Serializable 在流中必须保存有恢复成兼容类型对象所需的各成员变量的值。Externalizable类自身定义其对象的外部存储格式。,ObjectOutputStream,ObjectOutputStream 类提供对象的序列化处写出功能。FileOutputStream f=new FileOutputStream(tmp);ObjectOutputStream s=new ObjectOutputStream(f);s.writeObject(Today);s.writeObject(new Date();s.flush();writeObject方法序列化指定的对象,并遍历该对象对其它对象的引用,递归的序列化所有被引用到的其它对象,从而建立一个完整的序列化流。,ObjectInputStream,ObjectInputStream类提供读取序列化对象的功能FileInputStream in=new FileInputStream(tmp);ObjectInputStream s=new ObjectInputStream(in);String today=(String)s.readObject();Date date=(Date)s.readObject();readObject方法反序列化输入流中的下一个对象,遍历该对象中所有对其它对象的引用,并递归的反序列化这些引用对象。,Serializable 接口,接口只是用来标识出一个类 能够被序列化,并未定义任何抽象方法public interface Serializable,序列化的内容,被序列化的内容:成员变量(包括基本数据类型、数组、对其它对象 的引用)类 名不被序列化的内容:static的属性 方法 加了transient修饰符的属性,对象序列化举例 1,class Name implements Comparable,Serializable private String firstName,lastName;public Name(String f,String l)firstName=f;public String getFirstName()return firstName;public String getLastName()return lastName;public String toString()return firstName+.+lastName;,对象序列化举例 1(续1),public boolean equals(Object obj)if(obj instanceof Name)Name name=(Name)obj;return(firstName.equals(name.firstName),对象序列化举例 1(续2),import java.io.*;import java.util.*;public class Test public static void main(String args)List nameList=new ArrayList();nameList.add(new Name(A,C);nameList.add(new Name(B,B);nameList.add(new Name(C,A);nameList.add(new Name(D,A);nameList.add(new Name(E,B);System.out.println(nameList);Collections.sort(nameList);System.out.println(nameList);try FileOutputStream fos=new FileOutputStream(d:namelist.obj);ObjectOutputStream oos=new ObjectOutputStream(fos);System.out.println(save object.);oos.writeObject(nameList);catch(IOException e)e.printStackTrace();System.exit(-1);,对象序列化举例 1(续3),try FileInputStream fis=new FileInputStream(d:namelist.obj);ObjectInputStream ois=new ObjectInputStream(fis);System.out.println(loading object.);List arrayList=(ArrayList)ois.readObject();System.out.println(nameList);Collections.shuffle(nameList);System.out.println(nameList);catch(FileNotFoundException e1)e1.printStackTrace();catch(IOException e1)e1.printStackTrace();catch(ClassNotFoundException e1)e1.printStackTrace();,在网络中传递对象,建立一个Socket连接,在这个连接之间传递系列化后的对象,对象序列化举例 2,import java.io.*;import.*;import java.util.Date;public class Server public static void main(String args)try ServerSocket server=new ServerSocket(6888);Socket socket=server.accept();ObjectInputStream ois=new ObjectInputStream(socket.getInputStream();Name name=(Name)ois.readObject();Date date=(Date)ois.readObject();socket.close();System.out.println(date);System.out.println(name);catch(Exception e)e.printStackTrace();,对象序列化举例 2(续),import java.io.*;import.*;import java.util.Date;public class Client public static void main(String args)try Socket socket=new Socket(localhost,8020);ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream();oos.writeObject(new Name(A,B);oos.writeObject(new Date();oos.flush();oos.close();catch(Exception e)System.exit(1);,定制对象系列化,可以通过定制对象系列化改变默认的系列化机制通过在可系列化的类中实现方法writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in),可以实现定制,使用transient关键字保护数据,通过在属性前面加上transient关键字,限制属性写入到文件或网络中还可以在未实现系列化接口的引用类型属性前面加上transient关键字,避免对此类属性进行递归系列化时出现异常,系列化的另一种方式,可以让需要系列化的类实现Serializable接口的子接口ExternalizableExternalizable接口表示实现该接口的类在序列化中由该类本身来控制信息的写出和读入。Externalizable接口定义:package java.io;public interface Externalizable extends Serializablepublic void writeExternal(ObjectOutput out)throws IOException;public void readExternal(ObjectInput in)throws IOException,java.lang.ClassNotFoundException;,系列化的另一种方式,步骤:实现Externalizable接口实现readExternal()/writeExternal()方法需要一个不带参数的构造器(是否需要显式定义根据类是否有定义构造器而定),小结,描述对象序列化的目标编程实现对象序列化了解java.io包中和系列化有关的内容,掌握主要的接口编程实现序列化的对象在网络上的传输描述对象序列化的原理transient的用法Serializable/Externalizable的异同,国际化,软件国际化的意义如何确定locale数字、货币的国际化日期和时间的国际化使用资源文件使用属性文件消息的国际化,确定locale,一个locale包括:国家(地区)以及语言使用Locale类来表示Locale(String language)Locale(String language,String country)Locale(String language,String country,String variant)country表示有效的ISO国家代码Variant是预留给第三方软件开发商或浏览器使用的一个附加变量,Locale类,常用方法:getLanguage()getCountry()getDisplayLanguage()getDisplayCountry()toString():语言_国家,获取默认的locale,Locale.getDefault():获取系统默认的locale,和数字相关的格式化,NumberFormat类数字(Numeric):getNumberInstance()/getNumberInstance(Locale lcl)货币(Currency):getCurrencyInstance()/getCurrencyInstance(Locale lcl)百分比(Percent):getPercentInstance()/getPercentInstance(Locale lcl),日期/时间格式化,DateFormatDateFormat getDateInstance()DateFormat getDateInstance(int dateStyle,Locale lcl)DateFormat getTimeFormat()DateFormat getTimeFormat(int timeStyle,Locale lcl)DateFormat getDateTimeFormat()DateFormat getDateTimeFormat(int dateStyle,int timeStyle,Locale lcl)dateStyle/timeStyle可以取如下的值:DateFormat.DEFAULTDateFormat.LONGDateFormat.MEDIUMDateFormat.SHORTDateFormat.FULL,使用SimpleDateFormat,SimpleDateFormat简化了日期和时间的格式化它主要用于本地化,资源包,讲信息封装在资源包(Resource Bundle)中在java.util中提供了一个ResouceBundle类,用于表示资源包资源包命名规定:XXXResource_language_country_variant/XXXResource_language_country/XXXResource_language/XXXResource通过ResourceBundle类的getBundle(String bundleName,Locale lcl)方法可以取得对应locale的资源包得到bundle后,使用ResourceBundle对象的getObject()/getString()方法可以获得对应的信息,资源包(con.),我们通常将自己定义的ResouceBundle类继承ListResourceBundle或者PropertyResourceBundle类,然后实现其中的getContents()方法如果资源中有除String外的其他对象,使用ListResourceBundle,否则使用PropertyResourceBundle,使用属性文件,如果只有String类型资源,只需要使用属性文件即可属性文件的命名和资源包文件类似,并且注意将扩展名命名为.propertiesResourceBundle的getBundle()方法将会找出对应的属性文件,并且将它转换成PropertyResourceBundle对象,我们不需要自己去产生PropertyResourceBundel对象,消息的格式化,使用MessageFormat来对消息进行格式化将文本消息写成一个字符串,在其中不确定的部分使用占位符,在一个字符串中最多可以使用10个占位符(09),每个占位符可以多次使用;建立一个MessageFormat对象,将格式字符串作为构造器的参数;使用MessageFormat的setLocale()方法设置它的Locale属性;建立一个用于取代占位符的对象的数组,让占位符中的数字和数组的索引匹配;调用MessageFormat的format()方法,将对象数组作为参数。,