Java: Object Stream

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Data stream hỗ trợ I/O đối với các kiểu dữ liệu nguyên thủy, còn object stream hỗ trợ I/O đối với các đối tượng. Hầu hết các lớp chuẩn hỗ trợ tính tuần tự (serialization) đối với các đối tượng của chúng. Những lớp này sẽ thực thi giao diện Serializable.

Có hai lớp object stream bao gồm ObjectInputStream và ObjectOutputStream, những lớp này thực thi ObjectInput và ObjectOutput, đây là những giao diện con của DataInput và DataOutput. Có nghĩa rằng tất cả các phương thức I/O đối với các dữ liệu kiểu nguyên thủy được bảo đảm với data stream thì cũng được thực thi với object stream. Vì vậy, mỗi object stream có thể chứa một hỗn hợp của các giá trị nguyên thủy và đối tượng. Ví dụ có tên ObjectStreams dưới đây sẽ minh họa điều này:

package solutions;

import java.io.*;
import java.math.BigDecimal;
import java.util.Calendar;

public class ObjectStreams {
  static final String dataFile = "invoicedata";

  static final BigDecimal[] prices = {
    new BigDecimal("19.99"),
    new BigDecimal("9.99"),
    new BigDecimal("15.99"),
    new BigDecimal("3.99"),
    new BigDecimal("4.99")};
  static final int[] units = {12, 8, 13, 29, 50};
  static final String[] descs = {"Java T-shirt",
    "Java Mug",
    "Duke Juggling Dolls",
    "Java Pin",
    "Java Key Chain"};

  public static void main(String[] args)
    throws IOException, ClassNotFoundException {


    ObjectOutputStream out = null;
    try {
      out = new ObjectOutputStream(new
        BufferedOutputStream(new FileOutputStream(dataFile)));

      out.writeObject(Calendar.getInstance());
      for (int i = 0; i < prices.length; i++) {
        out.writeObject(prices[i]);
        out.writeInt(units[i]);
        out.writeUTF(descs[i]);
      }
    } finally {
      out.close();
    }

    ObjectInputStream in = null;
    try {
      in = new ObjectInputStream(new
        BufferedInputStream(new FileInputStream(dataFile)));

      Calendar date = null;
      BigDecimal price;
      int unit;
      String desc;
      BigDecimal total = new BigDecimal(0);

      date = (Calendar) in.readObject();

      System.out.format("On %tA, %<tB %<te, %<tY:%n", date);

      try {
        while (true) {
          price = (BigDecimal) in.readObject();
          unit = in.readInt();
          desc = in.readUTF();
          System.out.format("You ordered %d units of %s at $%.2f%n",
            unit, desc, price);
          total = total.add(price.multiply(new BigDecimal(unit)));
        }
      } catch (EOFException e) {
      }
      System.out.format("For a TOTAL of: $%.2f%n", total);
    } finally {
      in.close();
    }
  }
}

Lớp ObjectStreams tạo các ứng dụng tương tự như lớp DataStreams, với hai thay đổi, thứ nhất, giá lúc này là các đối tượng thuộc lớp BigDecimal, để thể hiện tốt hơn các giá trị phân số, thứ hai, một đối tượng Calendar được ghi vào tập tin dữ liệu, nó thể hiện ngày lập hóa đơn.

Nếu phương thức readObject() không trả về kiểu đối tượng theo dự kiến thì ta cố gắng ép sang kiểu đúng để có thể ném một ngoại lệ ClassNotFoundException. Trong ví dụ đơn giản này thì điều đó không thể xảy ra, vì vậy ta không cần cố bắt các ngoại lệ, thay vào đó, ta thông báo cho trình biên dịch rằng ta nhận thức được vấn đề này bằng cách thêm ngoại lệ ClassNotFoundException vào mệnh đề throws của phương thức main().

Đầu ra và đầu vào của đối tượng Complex

Các phương thức writeObject và readObject rất dễ dùng, nhưng chúng chứa một số logic quản lý đối tượng rất tinh vi. Điều này không quan trọng đối với một lớp như lớp Calendar, nó chỉ quan trọng đối với các giá trị kiểu nguyên thủy. Tuy nhiên, có nhiều đối tượng chứa tham chiếu đến các đối tượng khác. Nếu readObject dùng để tạo lại đối tượng từ stream, thì nó có thể để tạo lại tất cả các đối tượng mà đối tượng gốc đã tham chiếu tới. Vậy nên, những đối tượng bổ sung này có thể có tham khảo riêng của chúng. Trong tình huống này, writeObject sẽ đi qua toàn bộ các tham chiếu đối tượng và ghi chúng lên stream. Như vậy thì, một lời gọi duy nhất của writeObject có thể gây ra một số lượng lớn các đối tượng được ghi vào stream.

Điều này được thể hiện trong hình sau đây, trong đó phương thức writeObject được gọi để viết một đối tượng duy nhất được đặt tên là a. Đối tượng này chứa các tham chiếu đến các đối tượng b và c, trong khi b chứa tham chiếu đến d và e. Lời gọi phương thức writeObject(a) không chỉ ghi a, mà còn là tất cả các đối tượng cần thiết để tái tạo a, vì vậy bốn đối tượng khác trong hình cũng được ghi. Khi a được đọc lại bởi phương thức readObject thì bốn đối tượng khác cũng được đọc lại, và tất cả các đối tượng tham chiếu gốc được bảo toàn.

I / O của nhiều gọi đến đối tượng
I/O của nhiều gọi đến đối tượng

Có một câu hỏi đặt ra là điều gì sẽ xảy ra nếu hai đối tượng trên cùng một stream đều chứa các tham chiếu đến cùng một đối tượng. Chúng có được tham chiếu tới một đối tượng duy nhất khi chúng được đọc lại không? Câu trả lời là "có". Mỗi stream chỉ có thể chứa một bản sao của một đối tượng, mặc dù nó có thể chứa bất kỳ số tham chiếu nào đến nó. Vì vậy, nếu bạn ghi một cách tường minh một đối tượng đến một stream hai lần thì bạn đang thực sự chỉ ghi tham chiếu hai lần. Ví dụ, nếu đoạn mã sau đây viết một đối tượng có tên ob hai lần cho một stream:

Object ob = new Object();
out.writeObject(ob);
out.writeObject(ob);

Mỗi phương thức writeObject phải được kết hợp với một phương thức readObject, vì vậy mà đoạn mã đọc stream trở lại sẽ giống như thế này:

Object ob1 = in.readObject();
đối tượng ob2 = in.readObject();

Điều này dẫn đến hai biến ob1 và ob2 tham chiếu đến một đối tượng duy nhất.

Tuy nhiên, nếu một đối tượng duy nhất được ghi tới hai dòng khác nhau thì hiệu quả sẽ được nhân đôi - một chương trình duy nhất đọc cả hai stream trở lại sẽ thấy hai đối tượng riêng biệt.

» Tiếp: Đường dẫn là gì? (và sự kiện hệ thống tập tin khác)
« Trước: Data Stream
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!