深入剖析Java编程中的序列化

Java提供一种机制叫做序列化,通过有序的格式或者字节序列持久化java对象,其中包含对象的数据,还有对象的类型,和保存在对象中的数据类型。

所以,如果我们已经序列化了一个对象,那么它可以被读取并通过对象的类型和其他信息进行反序列化,并最终获取对象的原型。

ObjectInputStream 和 ObjectOutputStream对象是高级别的流对象,包含序列化和反序列化的方法。

ObjectOutputStream 拥有很多序列化对象的方法,最常用的是:

private void writeObject(ObjectOutputStream os) throws IOException
 {

 }

类似的 ObjectInputStream 提供如下方法:

 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException
 {

 }

那么哪里会需要序列化呢?序列化通常在需要通过网络传输数据,或者保存对象到文件的场合使用。这里说的数据是对象而不是文本。

现在的问题是,我们的网络架构和硬盘都只能识别二进制和字节,而不能识别Java对象。

序列化就是把Java对象中的value/states翻译为字节,以便通过网络传输或者保存。另外,反序列化就是通过读取字节码,并把它翻译回java对象。

serialVersionUID概念

serialVersionUID 是用于保证同一个对象(在序列化中会被用到)可以在Deserialization过程中被载入。serialVersionUID 是用于对象的版本控制。你可以参考serialVersionUID in java serialization获取更多信息。

对于序列化:

步骤如下:

让我们看一个列子:

在 src->org.arpit.javapostsforlearning 创建Employee.java

1.Employee.java

package org.arpit.javapostsforlearning;
import java.io.Serializable;
public class Employee implements Serializable{

 int employeeId;
 String employeeName;
 String department;

 public int getEmployeeId() {
  return employeeId;
 }
 public void setEmployeeId(int employeeId) {
  this.employeeId = employeeId;
 }
 public String getEmployeeName() {
  return employeeName;
 }
 public void setEmployeeName(String employeeName) {
  this.employeeName = employeeName;
 }
 public String getDepartment() {
  return department;
 }
 public void setDepartment(String department) {
  this.department = department;
 }
}

就如你所见的,如果你需要序列化任何类,那么你 必须实现 Serializable 接口 ,这个接口是标记接口(marker interface)。

Java中的标记接口(marker interface)就是一个没有任何字段或者方法的接口,简单的来说,java中把空接口叫做标记接口(marker interface)

2.SerializeMain.java

package org.arpit.javapostsforlearning;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
 public class SerializeMain {

 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {

 Employee emp = new Employee();
 emp.setEmployeeId(101);
 emp.setEmployeeName("Arpit");
 emp.setDepartment("CS");
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }
 }
}

对于反序列化:
步骤是

在包src->org.arpit.javapostsforlearning中,创建 DeserializeMain.java
3.DeserializeMain.java

package org.arpit.javapostsforlearning;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeMain {
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {

 Employee emp = null;
  try
  {
   FileInputStream fileIn =new FileInputStream("employee.ser");
   ObjectInputStream in = new ObjectInputStream(fileIn);
   emp = (Employee) in.readObject();
   in.close();
   fileIn.close();
  }catch(IOException i)
  {
   i.printStackTrace();
   return;
  }catch(ClassNotFoundException c)
  {
   System.out.println("Employee class not found");
   c.printStackTrace();
   return;
  }
  System.out.println("Deserialized Employee...");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getEmployeeName());
  System.out.println("Department: " + emp.getDepartment());
 }
}

4.运行:
首先运行SerializeMain.java,然后运行 DeserializeMain.java,你会得到如下的结果:

Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS

就这样,我们序列化了一个employee对象,并对它进行反序列化。这看起来和简单,但是如果其中包含对象引用,继承,那么情况就会变得复杂。接下来让我们一个接一个的看一下例子,看看如何在各种场合中实现序列化。

案例1 - 如果对象引用了其他对象,那该如何

我们已经看过最简单的序列化例子,现在看看,如何处理对象中引用了其他对象的场合。我们该如何序列化?引用对象也会被序列化吗?对的,你不需要显式的序列化引用对象。当你序列化任何对象,如果它包含引用对象,那么Java序列化会自动序列化该对象的整个对象图。例如,Employee现在引用了一个address对象,并且Address也引用了其他对象(例如,Home),那么当你序列化Employee对象的时候,所有其他引用对象,例如address和home将会被自动地被序列化。让我们来创建Address类,并它Address的对象作为引用,添加到employee类中。

Employee.java:

package org.arpit.javapostsforlearning;
import java.io.Serializable;

public class Employee implements Serializable{

 int employeeId;
 String employeeName;
 String department;
 Address address;

 public int getEmployeeId() {
 return employeeId;
 }
 public void setEmployeeId(int employeeId) {
 this.employeeId = employeeId;
 }
 public String getEmployeeName() {
 return employeeName;
 }
 public void setEmployeeName(String employeeName) {
 this.employeeName = employeeName;
 }
 public String getDepartment() {
 return department;
 }
 public void setDepartment(String department) {
 this.department = department;
 }
 public Address getAddress() {
 return address;
 }
 public void setAddress(Address address) {
 this.address = address;
 }
}

在 org.arpit.javapostsforlearning 包中,创建Address.java
Address.java:

package org.arpit.javapostsforlearning;
public class Address {

 int homeNo;
 String street;
 String city;
 public Address(int homeNo, String street, String city) {
 super();
 this.homeNo = homeNo;
 this.street = street;
 this.city = city;
 }
 public int getHomeNo() {
 return homeNo;
 }
 public void setHomeNo(int homeNo) {
 this.homeNo = homeNo;
 }
 public String getStreet() {
 return street;
 }
 public void setStreet(String street) {
 this.street = street;
 }
 public String getCity() {
 return city;
 }
 public void setCity(String city) {
 this.city = city;
 }
}

在包 org.arpit.javapostsforlearning中,创建SerializeDeserializeMain.java
SerializeDeserializeMain.java:

package org.arpit.javapostsforlearning;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeDeserializeMain {
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {

 Employee emp = new Employee();
 emp.setEmployeeId(101);
 emp.setEmployeeName("Arpit");
 emp.setDepartment("CS");
 Address address=new Address(88,"MG road","Pune");
 emp.setAddress(address);
 //Serialize
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }

 //Deserialize
 emp = null;
 try
 {
 FileInputStream fileIn =new FileInputStream("employee.ser");
 ObjectInputStream in = new ObjectInputStream(fileIn);
 emp = (Employee) in.readObject();
 in.close();
 fileIn.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 return;
 }catch(ClassNotFoundException c)
 {
 System.out.println("Employee class not found");
 c.printStackTrace();
 return;
 }
 System.out.println("Deserialized Employee...");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getEmployeeName());
 System.out.println("Department: " + emp.getDepartment());
 address=emp.getAddress();
 System.out.println("City :"+address.getCity());
 }
}

运行它:
当你运行SerializeDeserializeMain.java。你会得到这样的结果:

java.io.NotSerializableException: org.arpit.javapostsforlearning.Address
 at java.io.ObjectOutputStream.writeObject0(Unknown Source)
 at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
 at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
 at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
 at java.io.ObjectOutputStream.writeObject0(Unknown Source)
 at java.io.ObjectOutputStream.writeObject(Unknown Source)

我们将解释哪里出错了。我忘记了说,Address 类也必须是serializable。那么Address类必须继承serialzable接口。

Address.java:

import java.io.Serializable;

public class Address implements Serializable{

 int homeNo;
 String street;
 String city;
 public Address(int homeNo, String street, String city) {
 super();
 this.homeNo = homeNo;
 this.street = street;
 this.city = city;
 }
 public int getHomeNo() {
 return homeNo;
 }
 public void setHomeNo(int homeNo) {
 this.homeNo = homeNo;
 }
 public String getStreet() {
 return street;
 }
 public void setStreet(String street) {
 this.street = street;
 }
 public String getCity() {
 return city;
 }
 public void setCity(String city) {
 this.city = city;
 }
}

再次运行:
当你再次运行SerializeDeserializeMain.java。你可以得到如下的结果

Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS
City :Pune

案例2:如果我们不能访问引用对象的源代码(例如,你不能访问上面的Address类的源码)

如果我们不能访问到address类,那么我们该如何在Address类中实现serializable 接口?是否有另外的途径来实现呢?对的,你可以创建另外一个类,并继承Address,然后让它继承serializable 接口,但是对于下面的情况,这个方案会失败:

如果引用类被定义为final
    如果引用类引用了另外一个非可序列化的对象

那么,我们该如何序列化Employee对象?解决的办法是,标记transient。如果你不需要序列化任何字段,只需把它标记为transient。
 
transient Address address
在Employee类中,标记了address为transient之后,运行程序。你会得到nullPointerException,因为在反序列化过程中,Address引用将会是null。

案例3 - 如果我仍然需要保存引用对象的状态呢?(例如address对象)

如果你在反序列化过程中,标记了address为transient,它将会返回null结果。但是如果你仍然需要保存它的状态,你就需要序列化address对象。 Java序列化提供一个机制,如果你有特定签名的private方法,那么它们就会在序列化和反序列化过程中被调用,所以我们将重写Employee类的writeObject和readObject方法,然后它们就会在Employee对象序列化/反序列化过程中被调用。

Employee.java:

package org.arpit.javapostsforlearning;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Employee implements Serializable{

 int employeeId;
 String employeeName;
 String department;
 transient Address address;

 public int getEmployeeId() {
 return employeeId;
 }
 public void setEmployeeId(int employeeId) {
 this.employeeId = employeeId;
 }
 public String getEmployeeName() {
 return employeeName;
 }
 public void setEmployeeName(String employeeName) {
 this.employeeName = employeeName;
 }
 public String getDepartment() {
 return department;
 }
 public void setDepartment(String department) {
 this.department = department;
 }
 public Address getAddress() {
 return address;
 }
 public void setAddress(Address address) {
 this.address = address;
 }

 private void writeObject(ObjectOutputStream os) throws IOException, ClassNotFoundException
 {
 try {
 os.defaultWriteObject();
 os.writeInt(address.getHomeNo());
 os.writeObject(address.getStreet());
 os.writeObject(address.getCity());
 }
 catch (Exception e)
 { e.printStackTrace(); }
 }

 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException
 {
 try {
 is.defaultReadObject();
 int homeNo=is.readInt();
 String street=(String) is.readObject();
 String city=(String) is.readObject();
 address=new Address(homeNo,street,city);

 } catch (Exception e) { e.printStackTrace(); }
 }
}

另外有一点需要牢记的,ObjectInputStream读取数据的顺序和ObjectOutputStream写入数据的顺序是一致的.

在包org.arpit.javapostsforlearning 中创建Address.java
Address.java:

package org.arpit.javapostsforlearning;
import java.io.Serializable;

public class Address {

 int homeNo;
 String street;
 String city;

 public Address(int homeNo, String street, String city) {
 super();
 this.homeNo = homeNo;
 this.street = street;
 this.city = city;
 }
 public int getHomeNo() {
 return homeNo;
 }
 public void setHomeNo(int homeNo) {
 this.homeNo = homeNo;
 }
 public String getStreet() {
 return street;
 }
 public void setStreet(String street) {
 this.street = street;
 }
 public String getCity() {
 return city;
 }
 public void setCity(String city) {
 this.city = city;
 }
}

在包org.arpit.javapostsforlearning中创建SerializeDeserializeMain.java
SerializeDeserializeMain.java:

package org.arpit.javapostsforlearning;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeDeserializeMain {
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {

 Employee emp = new Employee();
 emp.setEmployeeId(101);
 emp.setEmployeeName("Arpit");
 emp.setDepartment("CS");
 Address address=new Address(88,"MG road","Pune");
 emp.setAddress(address);
 //Serialize
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }

 //Deserialize
 emp = null;
 try
 {
 FileInputStream fileIn =new FileInputStream("employee.ser");
 ObjectInputStream in = new ObjectInputStream(fileIn);
 emp = (Employee) in.readObject();
 in.close();
 fileIn.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 return;
 }catch(ClassNotFoundException c)
 {
 System.out.println("Employee class not found");
 c.printStackTrace();
 return;
 }
 System.out.println("Deserialized Employee...");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getEmployeeName());
 System.out.println("Department: " + emp.getDepartment());
 address=emp.getAddress();
 System.out.println("City :"+address.getCity());
 }
}

运行 :
当你运行SerializeDeserializeMain.java.你会得到如下的结果:

Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS
City :Pune

现在我们就得到了address对象的状态,就如它被序列化前的一样。

序列化中的继承:

现在我们看看继承是如何影响序列化的。不管父类是不是可序列化,这将引出很多个例子。如果父类是非可序列化的,我们将如何处理,并且它是如何工作的。让我们看看例子。

我们将创建一个Person.java,作为 Employee的父类。

案例4: 如果父类是可序列化的

如果父类可序列化,那么所有的继承类将是可序列化的。

案例5: 如果父类为非可序列化呢?

如果父类为非可序列化的 ,那么我们的处理办法会很不一样。

如果父类为非可序列化的,那么它必然不会有参数构造函数。

Person.java

package org.arpit.javapostsforlearning;
public class Person {

 String name="default";
 String nationality;

 public Person()
 {
 System.out.println("Person:Constructor");
 }

 public Person(String name, String nationality) {
 super();
 this.name = name;
 this.nationality = nationality;
 }

 public String getName() {
 return name;
 }

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

 public String getNationality() {
 return nationality;
 }

 public void setNationality(String nationality) {
 this.nationality = nationality;
 }

}

在包org.arpit.javapostsforlearning 中创建Employee.java
Employee.java:

package org.arpit.javapostsforlearning;
import java.io.Serializable;

public class Employee extends Person implements Serializable{

 int employeeId;
 String department;

 public Employee(int employeeId,String name,String department,String nationality)
 {
 super(name,nationality);
 this.employeeId=employeeId;
 this.department=department;
 System.out.println("Employee:Constructor");
 }

 public int getEmployeeId() {
 return employeeId;
 }
 public void setEmployeeId(int employeeId) {
 this.employeeId = employeeId;
 }

 public String getDepartment() {
 return department;
 }
 public void setDepartment(String department) {
 this.department = department;
 }
}

在org.arpit.javapostsforlearning包中创建SerializeDeserializeMain.java

SerializeDeserializeMain.java:


package org.arpit.javapostsforlearning;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeDeserializeMain {

 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {

 //Serialize
 Employee emp = new Employee(101,"Arpit","CS","Indian");
 System.out.println("Before serializing");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getName());
 System.out.println("Department: " + emp.getDepartment());
 System.out.println("Nationality: " + emp.getNationality());
 System.out.println("************");
 System.out.println("Serializing");
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }

 //Deserialize
 System.out.println("************");
 System.out.println("Deserializing");
 emp = null;
 try
 {
 FileInputStream fileIn =new FileInputStream("employee.ser");
 ObjectInputStream in = new ObjectInputStream(fileIn);
 emp = (Employee) in.readObject();
 in.close();
 fileIn.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 return;
 }catch(ClassNotFoundException c)
 {
 System.out.println("Employee class not found");
 c.printStackTrace();
 return;
 }
 System.out.println("After serializing");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getName());
 System.out.println("Department: " + emp.getDepartment());
 System.out.println("Nationality: " + emp.getNationality());
 }
}

运行:

当你运行SerializeDeserializeMain.java后,你会得到如下的输出,如果父类是非可序列化的,那么在反序列化过程中,所有继承于父类的实例变量值,将会通过调用非序列化构造函数来初始化。 这里 name继承于person,所以在反序列化过程中,name将会被初始化为默认值。


案例6 - 如果父类是可序列化,但你不需要继承类为可序列化

如果你不希望继承类为可序列化,那么你需要实现 writeObject() 和readObject() 方法,并且需要抛出NotSerializableException 异常。

案例7 - 可否序列化静态变量?

不能。因为静态变量是类级别的,不是对象级别的,当你序列化一个对象的时候,是不能序列化静态变量。

总结:

  • 序列化是java对象的values/states转化为字节并在网络中传输或者保存它的过程。另外反序列化是把字节码翻译为对应的对象的过程。
  • 序列化的好处是,JVM的独立性,也就是说,一个对象可以在一个平台中被序列化,然后在另外一个不同的平台反序列化。
  • 如果你需要序列化任何对象,你必须实现标记接口Serializable。
  • Java中的标记接口(Marker interface)就是没有字段或者方法的接口,或者更简单的说,空接口
  • serialVersionUID 是用于保证同一个对象(在序列化中会被用到)可以在Deserialization过程中被载入。serialVersionUID 是用于对象的版本控制。
  • 当你需要序列化任何包含引用对象的对象,那么Java会自动序列化该对象的整个对象图。
  • 如果你不希望序列化某个字段,你可以标记它为trasient
  • 如果父类为可序列化,那么它的继承类也将是可序列化的。
  • 如果父类为非可序列化,那么在反序列化过程中,所有继承于父类的实例变量值将会通过调用非可序列化的构造器来初始化。
  • 如果你需希望子类为可序列化的,那么你需要实现writeObject() 和 readObject() 方法,并在这两个方法中抛出NotSerializableException异常
  • 你不能序列化静态变量。
(0)

相关推荐

  • 基于序列化存取实现java对象深度克隆的方法详解

    我们知道,在java中,将一个非原型类型类型的对象引用,赋值给另一个对象的引用之后,这两个引用就指向了同一个对象,如: 复制代码 代码如下: public class DeepCloneTest { private class CloneTest {  private Long myLong = new Long(1); } public static void main(String args[]) {  new DeepCloneTest().Test(); } public void Te

  • java教程之对象序列化使用基础示例详解

    这个过程也可以通过网络实现,可以先在Windows机器上创建一个对象,对其序列化,然后通过网络发给一台Unix机器,然后在那里准确无误地重新"装配".像RMI.Socket.JMS.EJB它们中的一种,彼此为什么能够传递Java对象,当然都是对象序列化机制的功劳. Java对象序列化机制一般来讲有两种用途: Java的JavaBeans: Bean的状态信息通常是在设计时配置的,Bean的状态信息必须被存起来,以便当程序运行时能恢复这些状态信息,这需要将对象的状态保存到文件中,而后能够

  • Java利用序列化实现对象深度clone的方法

    本文实例讲述了Java利用序列化实现对象深度clone的方法.分享给大家供大家参考.具体实现方法如下: ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(obj); ByteArrayInputStream byteIn = new ByteArrayInputStream(by

  • java对象序列化与反序列化的默认格式和json格式使用示例

    默认格式 复制代码 代码如下: public class MyClass implements Serializable{...} 序列化: 复制代码 代码如下: ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(outputPath)); output.writeObject(myObject); 反序列化: 复制代码 代码如下: ObjectInputStream input = new Objec

  • Java序列化机制与原理的深入分析

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一种处理对象序列化的标准机制.在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的.序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端.这就需要有一种可以在

  • 深入理解Java对象的序列化与反序列化的应用

    当两个进程在进行远程通信时,彼此可以发送各种类型的数据.无论是何种类型的数据,都会以二进制序列的形式在网络上传送.发送方需要把这个Java对象转换为字节序列,才能在网络上传送:接收方则需要把字节序列再恢复为Java对象. 把Java对象转换为字节序列的过程称为对象的序列化.把字节序列恢复为Java对象的过程称为对象的反序列化.对象的序列化主要有两种用途:1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中:2) 在网络上传送对象的字节序列.一. JDK类库中的序列化APIjava.io

  • Java中对象序列化与反序列化详解

    本文实例讲述了Java中对象序列化与反序列化.分享给大家供大家参考.具体如下: 一.简介 对象序列化(Serializable)是指将对象转换为字节序列的过程,而反序列化则是根据字节序列恢复对象的过程. 序列化一般用于以下场景: 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.通过序列化对象在网络中传递对象: 3.通过序列化在进程间传递对象. 对象所属的类必须实现Serializable或是Externalizable接口才能被序列化.对实现了Serializable接口的类,其序列化

  • java序列化和java反序列化示例

    序列化一般应用与以下场景之中:1.永久性保存对象,把对象通过序列化字节流保存到本地文件中:2.通过序列化在网络中传输对象3.通过序列化在进程间传递对象 复制代码 代码如下: import java.io.Serializable;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream; public class javaSerializable_fun { /**  

  • java 序列化对象 serializable 读写数据的实例

    序列化对象: 复制代码 代码如下: package com.chen.seriaizable; import java.io.Serializable;import java.util.List; @SuppressWarnings("serial")public class Student implements Serializable{ private String name; private String id; private int age; private List<

  • 深入剖析Java编程中的序列化

    Java提供一种机制叫做序列化,通过有序的格式或者字节序列持久化java对象,其中包含对象的数据,还有对象的类型,和保存在对象中的数据类型. 所以,如果我们已经序列化了一个对象,那么它可以被读取并通过对象的类型和其他信息进行反序列化,并最终获取对象的原型. ObjectInputStream 和 ObjectOutputStream对象是高级别的流对象,包含序列化和反序列化的方法. ObjectOutputStream 拥有很多序列化对象的方法,最常用的是: private void write

  • Java编程中ArrayList源码分析

    之前看过一句话,说的特别好.有人问阅读源码有什么用?学习别人实现某个功能的设计思路,提高自己的编程水平. 是的,大家都实现一个功能,不同的人有不同的设计思路,有的人用一万行代码,有的人用五千行.有的人代码运行需要的几十秒,有的人只需要的几秒..下面进入正题了. 本文的主要内容: · 详细注释了ArrayList的实现,基于JDK 1.8 . ·迭代器SubList部分未详细解释,会放到其他源码解读里面.此处重点关注ArrayList本身实现. ·没有采用标准的注释,并适当调整了代码的缩进以方便介

  • java编程中实现调用js方法分析

    本文实例讲述了java编程中实现调用js方法.分享给大家供大家参考,具体如下: /* * 加载脚本引擎,并在java中调用js方法 */ public void test2() { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); try { String str="2&1"

  • java编程中字节流转换成字符流的实现方法

    java编程中字节流转换成字符流的实现方法 import java.io.*; /*readLine方法是字符流BufferReader类中的方法 * 而键盘录入的方法是字节流InputStream的方法 * 那么能不能将字节流转成字符流再使用字符流缓冲区中的readLine方法呢? * * InputStreamReader类是字节流转向字符流的桥梁.(它本身是一个字符流所以在构造时接受一个字节流) * * */ public class TransStreamDemo { public st

  • Java编程中10个最佳的异常处理技巧

    在实践中,异常处理不单单是知道语法这么简单.编写健壮的代码是更像是一门艺术,在本文中,将讨论Java异常处理最佳实践.这些Java最佳实践遵循标准的JDK库,和几个处理错误和异常的开源代码.这还是一个提供给java程序员编写健壮代码的便利手册.Java 编程中异常处理的最佳实践 这里是我收集的10个Java编程中进行异常处理的10最佳实践.在Java编程中对于检查异常有褒有贬,强制处理异常是一门语言的功能.在本文中,我们将尽量减少使用检查型异常,同时学会在Java编程中使用检查型VS非检查型异常

  • 浅谈Java编程中的synthetic关键字

    java synthetic关键字.有synthetic标记的field和method是class内部使用的,正常的源代码里不会出现synthetic field.小颖编译工具用的就是jad.所有反编译工具都不能保证完全正确地反编译class.所以你不能要求太多. 下面我给大家介绍一下synthetic 下面的例子是最常见的synthetic field Java代码 class parent { public void foo() { } class inner { inner() { foo

  • 深入理解Java编程中异常处理的优劣

    Java编程中的异常处理是一个很常见的话题了,几乎任何一门介绍性的Java课程都会提到异常处理.不过,我认为很多人其实没有真正掌握正确处理异常情况的方法和策略,最多也就不过了解个大概,知道概念.我想对三种不同程度和质量的Java异常处理进行了讨论,所阐述的处理异常的方式按手法的高下分为:好,不好和恶劣三种.同时提供了一些解决这些问题的技巧.首先解释一些java异常处理中必须搞清楚的定义和机制.Java语言规范将自Error类或RuntimeException类衍生出来的任何违例都称作"不可检查&

  • Java编程中的HashSet和BitSet详解

    Java编程中的HashSet和BitSet详解 我在Apache的开发邮件列表中发现一件很有趣的事,Apache Commons包的ArrayUtils类的removeElements方法,原先使用的HashSet现在换成了BitSet. HashSet<Integer> toRemove = new HashSet<Integer>(); for (Map.Entry<Character, MutableInt> e : occurrences.entrySet()

  • java编程中自动拆箱与自动装箱详解

    什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象实例的时候,我们会这样: Class a = new Class(parameter); 当我们创建一个Integer对象时,却可以这样: Integer i = 100; (注意:不是 int i = 100; ) 实际上,执行上面那句代码的时候,系统为我们执行了:Integer i = Integer.valueOf(100); (感谢@

  • 浅谈Java编程中string的理解与运用

    一,"=="与equals() 运行以下代码,如何解释其输出结果? public class StringPool { public static void main(String args[]) { String s0="Hello"; String s1="Hello"; String s2="He"+"llo"; System.out.println(s0==s1);//true System.out

随机推荐