Câu hỏi Tại sao Java có các trường tạm thời?


Tại sao Java lại có tạm thời lĩnh vực?


1202
2018-05-26 12:11


gốc




Các câu trả lời:


Các transient từ khóa trong Java được sử dụng để chỉ ra rằng một trường không nên được tuần tự hóa.

Từ Đặc tả ngôn ngữ Java, Ấn bản Java SE 7, Mục 8.3.1.3. transient Lĩnh vực:

Các biến có thể được đánh dấu transient đến   cho biết rằng họ không phải là một phần của   trạng thái liên tục của một đối tượng.

Ví dụ, bạn có thể có các trường có nguồn gốc từ các trường khác, và chỉ nên được thực hiện để lập trình, thay vì có trạng thái được duy trì thông qua serialization.

Đây là một GalleryImage lớp có chứa hình ảnh và hình thu nhỏ bắt nguồn từ hình ảnh:

class GalleryImage implements Serializable
{
    private Image image;
    private transient Image thumbnailImage;

    private void generateThumbnail()
    {
        // Generate thumbnail.
    }

    private void readObject(ObjectInputStream inputStream)
            throws IOException, ClassNotFoundException
    {
        inputStream.defaultReadObject();
        generateThumbnail();
    }    
}

Trong ví dụ này, thumbnailImage là hình thu nhỏ được tạo bằng cách gọi generateThumbnail phương pháp.

Các thumbnailImage trường được đánh dấu là transient, vì vậy chỉ có bản gốc image được tuần tự hóa thay vì lưu giữ cả hình ảnh gốc và hình thu nhỏ. Điều này có nghĩa là cần ít dung lượng hơn để lưu đối tượng được tuần tự hóa. (Tất nhiên, điều này có thể hoặc có thể không được mong muốn tùy thuộc vào yêu cầu của hệ thống - đây chỉ là một ví dụ.)

Tại thời điểm deserialization, các readObject phương thức được gọi để thực hiện bất kỳ thao tác nào cần thiết để khôi phục trạng thái của đối tượng trở lại trạng thái tại đó việc tuần tự hóa xảy ra. Ở đây, hình thu nhỏ cần được tạo, vì vậy readObject phương pháp được ghi đè để hình thu nhỏ sẽ được tạo bằng cách gọi generateThumbnail phương pháp.

Để biết thêm thông tin, Khám phá những bí mật của API tuần tự hóa Java bài viết (ban đầu có sẵn trên Mạng nhà phát triển Sun) có phần thảo luận về việc sử dụng và trình bày một kịch bản trong đó transient từ khóa được sử dụng để ngăn việc tuần tự hóa các trường nhất định.


1414
2018-05-26 12:53



Nhưng tại sao lại là từ khóa chứ không phải chú thích @DoNotSerialize? - Elazar Leibovich
Tôi đoán, đây là thuộc sở hữu của một thời gian khi không có chú thích trong Java. - Peter Wippermann
Tôi tìm thấy nó lẻ mà serializable là nội bộ để Java. Nó có thể được thực hiện như một giao diện hoặc lớp trừu tượng yêu cầu người dùng ghi đè các phương thức đọc và ghi. - caleb
@MJafar: readObject thường bị xích vào các cơ chế deserialization và do đó được gọi là tự động. Hơn nữa, trong nhiều trường hợp bạn không cần phải ghi đè lên nó - việc triển khai mặc định thực hiện thủ thuật. - Mike Adler
@caleb có lẽ vì giao dịch với các định dạng nhị phân chính mình là cực kỳ đau đớn trong Java do thiếu số nguyên unsigned. - rightfold


Trước khi hiểu transient từ khóa, người ta phải hiểu khái niệm về tuần tự hóa. Nếu người đọc biết về serialization, xin vui lòng bỏ qua điểm đầu tiên.

Serialization là gì?

Tuần tự hóa là quá trình làm cho trạng thái của đối tượng bền bỉ. Điều đó có nghĩa là trạng thái của đối tượng được chuyển đổi thành một luồng byte và được lưu trữ trong một tệp. Trong cùng một cách, chúng ta có thể sử dụng deserialization để mang lại trạng thái của đối tượng từ byte. Đây là một trong những khái niệm quan trọng trong lập trình Java vì việc tuần tự hóa chủ yếu được sử dụng trong lập trình mạng. Các đối tượng cần được truyền qua mạng phải được chuyển đổi thành byte. Vì mục đích đó, mọi lớp hoặc giao diện phải thực hiện Serializable giao diện. Nó là một giao diện đánh dấu mà không có bất kỳ phương pháp nào.

Bây giờ là gì transient từ khóa và mục đích của nó?

Theo mặc định, tất cả các biến của đối tượng được chuyển đổi thành trạng thái liên tục. Trong một số trường hợp, bạn có thể muốn tránh sự tồn tại của một số biến vì bạn không cần phải duy trì các biến đó. Vì vậy, bạn có thể khai báo các biến đó transient. Nếu biến được khai báo là transient, sau đó nó sẽ không được tiếp tục tồn tại. Đó là mục đích chính của transient từ khóa.

Tôi muốn giải thích hai điểm trên với ví dụ sau:

package javabeat.samples;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class NameStore implements Serializable{
    private String firstName;
    private transient String middleName;
    private String lastName;

    public NameStore (String fName, String mName, String lName){
        this.firstName = fName;
        this.middleName = mName;
        this.lastName = lName;
    }

    public String toString(){
        StringBuffer sb = new StringBuffer(40);
        sb.append("First Name : ");
        sb.append(this.firstName);
        sb.append("Middle Name : ");
        sb.append(this.middleName);
        sb.append("Last Name : ");
        sb.append(this.lastName);
        return sb.toString();
    }
}

public class TransientExample{
    public static void main(String args[]) throws Exception {
        NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
        ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
        // writing to object
        o.writeObject(nameStore);
        o.close();

        // reading from object
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
        NameStore nameStore1 = (NameStore)in.readObject();
        System.out.println(nameStore1);
    }
}

Và đầu ra sẽ như sau:

First Name : Steve
Middle Name : null
Last Name : Jobs

Tên đệm được khai báo là transient, do đó, nó sẽ không được lưu trữ trong lưu trữ liên tục.

Nguồn


355
2018-05-26 12:13



Ví dụ này được lấy từ mã này, bạn có thể đọc nó ở đây:javabeat.net/2009/02/what-is-transient-keyword-in-java - Krishna
Phần này đánh tôi là kỳ lạ và có thể gây nhầm lẫn: "Điều đó có nghĩa là trạng thái của đối tượng được chuyển đổi thành một chuỗi các byte và được lưu trữ trong một tập tin"Có vẻ như với tôi rằng phần lớn thời gian serialization không liên quan đến việc viết vào một tập tin (trường hợp tại điểm: các ví dụ về mạng theo sau) - Garcia Hurtado
Ví dụ này là một ví dụ tồi, vì tên đệm rõ ràng không phải một tài sản thoáng qua. - Raphael


Để cho phép bạn xác định các biến mà bạn không muốn nối tiếp.

Trong một đối tượng, bạn có thể có thông tin mà bạn không muốn serialize / persist (có lẽ là một tham chiếu đến một đối tượng factory cha), hoặc có lẽ nó không có ý nghĩa để serialize. Đánh dấu chúng là 'thoáng qua' có nghĩa là cơ chế tuần tự hóa sẽ bỏ qua các trường này.


80
2018-03-18 22:04





Đóng góp nhỏ của tôi:

Biến thoáng qua trong Java là gì?
Trong câu đơn giản, bất kỳ biến nào được sửa đổi với từ khóa tạm thời trở thành biến thoáng qua trong java.

Tại sao chúng ta cần biến thoáng qua trong java?
Từ khóa thoáng qua cung cấp cho bạn một số quyền kiểm soát quá trình tuần tự hóa và cho phép bạn linh hoạt loại trừ một số thuộc tính đối tượng khỏi quá trình tuần tự hóa. Một thời gian không có nghĩa là không tuần tự hóa các thuộc tính nhất định của một đối tượng, chúng ta sẽ thấy các biến nào không được tuần tự hóa và cần được thực hiện tạm thời trong phần tiếp theo.

Biến nào bạn nên đánh dấu thoáng qua?
Vì chúng tôi biết mục đích của từ khóa tạm thời hoặc có biến thoáng qua nên có ý nghĩa để suy nghĩ về biến nào sẽ được đánh dấu là thoáng qua. Quy tắc của tôi là bất kỳ biến nào có giá trị có thể được tính toán từ các biến khác không yêu cầu phải được lưu. Ví dụ: nếu bạn có một trường được gọi là "sở thích" có giá trị có thể được bắt nguồn từ các trường khác, ví dụ: nguyên tắc, tỷ lệ, thời gian vv sau đó không cần phải serialize nó.
Một ví dụ khác là đếm từ, nếu bạn đang tiết kiệm bài viết thì không cần phải lưu số lượng từ, bởi vì nó có thể được tạo ra khi bài viết được deserialized. Một ví dụ khác của từ khóa thoáng qua là "Logger" vì hầu hết thời gian bạn có thể đăng nhập để đăng nhập vào Java nhưng bạn chắc chắn không muốn nó serialize đúng?


27
2018-05-26 12:15



'Câu đơn giản' của bạn chỉ đơn thuần là một thuật ngữ. Nó không giải thích gì cả. Bạn sẽ tốt hơn nếu không có nó. - user207421


A transient biến là một biến có thể không được tuần tự hóa.

Một ví dụ về khi điều này có thể hữu ích đến với tâm trí là, các biến chỉ có ý nghĩa trong ngữ cảnh của một cá thể đối tượng cụ thể và trở thành không hợp lệ khi bạn đã tuần tự hóa và deserialized đối tượng. Trong trường hợp đó, việc biến các biến đó trở nên hữu ích null thay vào đó để bạn có thể khởi tạo lại chúng với dữ liệu hữu ích khi cần.


21
2018-03-26 14:16





transient được sử dụng để chỉ ra rằng một trường lớp không cần phải được tuần tự hóa. Có lẽ ví dụ tốt nhất là Thread cánh đồng. Thường không có lý do gì để tuần tự hóa Thread, vì trạng thái của nó rất "chảy cụ thể".


13
2018-05-26 12:15



Đúng tôi nếu tôi sai, nhưng Thread không phải là serializable vì vậy nó sẽ được bỏ qua anyways? - TFennis
@TFennis: Nếu một lớp serializable A tham chiếu một lớp không serializable B (như Thread trong ví dụ của bạn), sau đó A phải đánh dấu tham chiếu là transient XOR phải ghi đè lên quá trình tuần tự hóa mặc định để làm điều gì đó hợp lý với B XOR giả định rằng chỉ các lớp con có thể tuần tự hóa của B thực sự được tham chiếu (vì vậy lớp con thực sự phải chăm sóc cho phụ huynh "xấu" của họ B) XOR chấp nhận rằng việc tuần tự hóa sẽ thất bại. Chỉ trong một trường hợp (được đánh dấu là tạm thời) B được tự động và âm thầm bỏ qua. - A.H.
@TFennis Không, nó sẽ gây ra một ngoại lệ. - user207421
@ A.H .: Tại sao XOR? Tôi nghĩ rằng mã đã kết hợp những thứ đó sẽ hoạt động và một số kết hợp có thể hữu ích (ví dụ: ghi đè quá trình tuần tự hóa mặc định có thể hữu ích ngay cả khi chỉ các lớp con có thể tuần tự hóa của B được tham chiếu và ngược lại). - supercat


Bởi vì không phải tất cả các biến đều có tính chất tuần tự hóa


10
2018-05-28 02:20



Vui lòng cung cấp thêm thông tin khi bạn đưa ra câu trả lời. - Gynnad


Các hệ thống tuần tự khác với hệ thống java bản địa cũng có thể sử dụng công cụ sửa đổi này. Hibernate, ví dụ, sẽ không tồn tại các trường được đánh dấu bằng @Tạm thời hoặc là tạm thờibổ nghĩa. Terracotta cũng tôn trọng công cụ sửa đổi này.

Tôi tin rằng ý nghĩa nghĩa bóng của modifier là "lĩnh vực này là dành cho chỉ sử dụng trong bộ nhớ. Không tồn tại hoặc di chuyển nó bên ngoài của VM cụ thể này trong bất kỳ cách nào. Nó không di động". tức là bạn không thể dựa vào giá trị của nó trong không gian bộ nhớ VM khác. Nhiều như bay hơi có nghĩa là bạn không thể dựa vào bộ nhớ và chủ đề ngữ nghĩa nhất định.


10
2017-12-22 08:20



tôi nghĩ vậy transient sẽ không phải là một từ khóa nếu nó được thiết kế tại thời điểm này. Có lẽ họ sẽ sử dụng chú thích. - Joachim Sauer


Tuần tự hóa là quá trình lưu trạng thái của đối tượng theo định dạng liên tục (chẳng hạn như luồng tệp hoặc cơ sở dữ liệu) và sau đó khôi phục chúng trở lại từ luồng (de-serialization). Trong Java, một đối tượng của một lớp được tuần tự hóa nếu lớp thực hiện giao diện java.io.Serializable. Đây là một giao diện điểm đánh dấu cho JVM biết rằng lớp đó đủ điều kiện để tuần tự hóa.

public class User implements Serializable {

    private static final long serialVersionUID = 1234L;

    private String username;
    private String email;
    private transient String password;
    private Date birthday;
    private int age;

    public User(String username, String email, String password, Date birthday,
            int age) {
        this.username = username;
        this.email = email;
        this.password = password;
        this.birthday = birthday;
        this.age = age;
    }

    public void printInfo() {
        System.out.println("username: " + username);
        System.out.println("email: " + email);
        System.out.println("password: " + password);
        System.out.println("birthday: " + birthday);
        System.out.println("age: " + age);
    }

    // getters and setters

}

Có ba điểm quan trọng trong lớp mô hình này: Nó phải thực hiện giao diện Serializable. Nếu không, chúng tôi sẽ nhận được một java.io.NotSerializableException khi cố gắng sắp xếp một đối tượng của lớp. Một hằng số có tên serialVersionUID được khai báo và gán một giá trị dài:

private static final long serialVersionUID = 1234L;

Đây là một hằng số thông thường cần được khai báo khi một lớp thực hiện giao diện Serializable. Phiên bản nối tiếp UID mạnh mẽ đảm bảo khả năng tương thích giữa các phiên bản serialized và de-serialized của các đối tượng của một lớp, bởi vì quá trình serialization và de-serialization có thể xảy ra trên các máy tính và hệ thống khác nhau. Mặc dù khai báo này là tùy chọn, nhưng luôn luôn nên khai báo serialVersionUID cho một lớp tuần tự.

Lưu ý rằng trường mật khẩu được đánh dấu là thoáng qua:

private transient String password;

Bởi vì chúng tôi không muốn lưu trữ mật khẩu khi tuần tự hóa đối tượng. Quy tắc là, khi một biến được đánh dấu là thoáng qua, đối tượng của nó sẽ không được tuần tự hóa trong quá trình tuần tự hóa.

Tạm thời biến là một biến có thể không được tuần tự hóa. Bạn sử dụng từ khóa tạm thời để chỉ ra cho máy ảo Java mà biến được chỉ định không phải là một phần của trạng thái liên tục của đối tượng.

Các công cụ sửa đổi truy cập được Java hỗ trợ là tĩnh, cuối cùng, trừu tượng, đồng bộ hóa, bản địa, dễ bay hơi, thoáng qua và strictfp.

Bảng sau đây cung cấp danh sách các đặc tả truy cập và các biến tố Java có thể được áp dụng cho các biến, các phương thức và các lớp.

SPECIFIER/MODIFIER  LOCAL VARIABLE  INSTANCEVARIABLE    METHOD   CLASS
public              NA              A                   A         A
protected           NA              A                   A         NA
default             A               A                   A         A
private             NA              A                   A         NA
final               A               A                   A         A
static              NA              A                   A         NA
synchronized        NA              NA                  A         NA
native              NA              NA                  A         NA
volatile            NA              A                   NA        NA
transient           NA              A                   NA        NA
strictfp            NA              NA                  A         A

9
2017-07-01 13:12



Tôi muốn nói khả năng hiển thị mặc định không áp dụng cho các biến cục bộ. - another