Câu trả lời:
Các transient
từ khóa trong Java được sử dụng để chỉ ra rằng một lĩnh vực không phải là một phần của serialization (có nghĩa là lưu lại, như vào một tập tin) quá trình.
Từ Đặc tả ngôn ngữ Java , Phiê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
để chỉ ra rằng chúng không phải là một phần của trạng thái bền bỉ 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 theo chương trình, thay vì trạng thái được duy trì thông qua tuần tự hóa.
Đây là một GalleryImage
lớp có chứa một hình ảnh và một hình thu nhỏ xuất phát 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
hình ảnh thu nhỏ được tạo bằng cách gọi generateThumbnail
phương thức.
Các thumbnailImage
lĩnh vực được đánh dấu như transient
, vì vậy chỉ bản gốc image
được đăng chứ không phải là sự bền bỉ cả ảnh gốc và hình ảnh thu nhỏ. Điều này có nghĩa là sẽ cần ít bộ nhớ 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 không thể 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 khử lưu huỳnh, 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 mà tại đó xảy ra tuần tự hóa. Ở đây, hình thu nhỏ cần được tạo, do đó readObject
phương thức được ghi đè để hình thu nhỏ sẽ được tạo bằng cách gọi generateThumbnail
phương thức.
Để biết thêm thông tin, Khám phá bí mật của bài viết API tuần tự hóa Java (vốn có sẵn trên Mạng của nhà phát triển Sun) có một 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 chặn việc tuần tự hóa các trường nhất định.
Trước khi hiểu transient
từ khóa, người ta phải hiểu khái niệm tuần tự hóa. Nếu người đọc biết về tuần tự hóa, xin vui lòng bỏ qua điểm đầu tiên.
Tuần tự hóa là quá trình làm cho trạng thái của đối tượng liên tục. Đ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 được sử dụng để duy trì (ví dụ: lưu trữ byte trong tệp) hoặc truyền (ví dụ gửi byte qua mạng). Theo cùng một cách, chúng ta có thể sử dụng quá trình khử lưu huỳnh để đưa trạng thái của đối tượng trở lại từ byte. Đây là một trong những khái niệm quan trọng trong lập trình Java vì 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 truyền qua mạng phải được chuyển đổi thành byte. Với 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.
transient
từ khóa và mục đích của nó là gì?Theo mặc định, tất cả các biến của đối tượng được chuyển đổi sang trạng thái liên tục. Trong một số trường hợp, bạn có thể muốn tránh tồn tại một số biến vì bạn không có nhu cầu duy trì các biến đó. Vì vậy, bạn có thể khai báo các biến đó là transient
. Nếu biến được khai báo là transient
, thì nó sẽ không được duy trì. Đó 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
, vì vậy nó sẽ không được lưu trữ trong bộ lưu trữ liên tục.
NameFormatter
ổ đĩa được sử dụng toString()
. Hoặc bất cứ điều gì khác liên quan đến cấu hình, hoặc xem, hoặc logic kinh doanh, ... trái ngược với dữ liệu.
Để cho phép bạn xác định các biến mà bạn không muốn tuần tự hóa.
Trong một đối tượng, bạn có thể có thông tin mà bạn không muốn tuần tự hóa / tồn tại (có lẽ là một tham chiếu đến đối tượng nhà máy mẹ) hoặc có lẽ nó không có ý nghĩa để tuần tự hóa. Đá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.
Đóng góp nhỏ của tôi:
Một lĩnh vực thoáng qua là gì?
Về cơ bản, bất kỳ trường nào được sửa đổi với transient
từ khóa là một trường thoáng qua.
Tại sao các trường tạm thời cần thiết trong Java?
Các transient
từ khóa cung cấp cho bạn một số kiểm soát quá trình tuần tự và cho phép bạn loại trừ một số tài sản đối tượng từ quá trình này. Quá trình tuần tự hóa được sử dụng để duy trì các đối tượng Java, chủ yếu là để các trạng thái của chúng có thể được bảo tồn trong khi chúng được chuyển hoặc không hoạt động. Đôi khi, 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.
Những lĩnh vực bạn nên đánh dấu thoáng qua?
Bây giờ chúng tôi biết mục đích củatransient
từ khóa và trường tạm thời, điều quan trọng là phải biết trường nào cần đánh dấu thoáng qua. Các trường tĩnh không được tuần tự hóa, do đó, từ khóa tương ứng cũng sẽ thực hiện thủ thuật. Nhưng điều này có thể làm hỏng thiết kế lớp học của bạn; đây là nơi mà ), thì không cần phải tuần tự hóa nó.
Một ví dụ tốt là với số lượng từ bài viết. Nếu bạn đang lưu toàn bộ một bài viết, thực sự không cần phải lưu số từ, bởi vì nó có thể được tính khi bài viết được "giải trừ". Hoặc suy nghĩ về logger;transient
từ khóa đến để giải cứu. Tôi cố gắng không cho phép các trường có giá trị có thể được lấy từ các trường khác được nối tiếp, vì vậy tôi đánh dấu chúng là tạm thời. Nếu bạn có một trường được gọi là interest
có giá trị có thể được tính từ các trường khác ( principal
, rate
&time
Logger
các trường hợp hầu như không bao giờ cần phải được tuần tự hóa, vì vậy chúng có thể được thực hiện tạm thời.
transient
transient
Một transient
biến là một biến có thể không được nối tiếp.
Một ví dụ về điều này có thể hữu ích trong tâm trí là, các biến chỉ có ý nghĩa trong ngữ cảnh của một đối tượng cụ thể và trở nên không hợp lệ khi bạn đã tuần tự hóa và giải tuần tự hóa đối tượng. Trong trường hợp đó, thật hữu ích khi có các biến đó trở thành null
để bạn có thể khởi tạo lại chúng với dữ liệu hữu ích khi cần.
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à một Thread
lĩnh vực. Thường không có lý do để tuần tự hóa một Thread
, vì trạng thái của nó là rất 'cụ thể dòng chảy'.
A
tham chiếu một lớp không tuần tự hóa B
(như Thread
trong ví dụ của bạn), thì A
phải đánh dấu tham chiếu là transient
XOR phải ghi đè 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 tuần tự hóa B
thực sự được tham chiếu (vì vậy lớp con thực tế phải chăm sóc cho cha mẹ "xấu" của họ B
) XOR chấp nhận rằng việc xê-ri hóa sẽ thất bại. Chỉ có một trường hợp (được đánh dấu là thoáng qua) B
được tự động và âm thầm bỏ qua.
Các hệ thống tuần tự hóa khác với java gốc cũng có thể sử dụng công cụ sửa đổi này. Chẳng hạn, Hibernate sẽ không duy trì các trường được đánh dấu bằng @Transient hoặc công cụ sửa đổi tạm thời . Terracotta cũng tôn trọng sửa đổi này.
Tôi tin rằng ý nghĩa tượng trưng của công cụ sửa đổi là "trường này chỉ dành cho sử dụng trong bộ nhớ. Đừng kiên trì hoặc di chuyển nó ra ngoài VM cụ thể này theo 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. Giống như dễ bay hơi có nghĩa là bạn không thể dựa vào ngữ nghĩa bộ nhớ và chủ đề nhất định.
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. Họ có thể sử dụng một chú thích.
Bởi vì không phải tất cả các biến đều có tính chất tuần tự
Trước khi tôi trả lời câu hỏi này, tôi phải giải thích cho bạn SERIALIZATION , bởi vì nếu bạn hiểu ý nghĩa hóa trong máy tính khoa học, bạn có thể dễ dàng hiểu từ khóa này.
Tuần tự hóa
Khi một đối tượng được truyền qua mạng / được lưu trên phương tiện vật lý (tệp, ...), đối tượng phải được "tuần tự hóa". Tuần tự hóa chuyển đổi chuỗi đối tượng trạng thái byte. Các byte này được gửi trên mạng / được lưu và đối tượng được tạo lại từ các byte này.
Thí dụ
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Bây giờ NẾU BẠN MUỐN KHÔNG CHUYỂN ĐỔI / SAVED trường của đối tượng này SO , bạn có thể sử dụng từ khóa transient
private transient attr2;
Điều đó là cần thiết khi bạn không muốn chia sẻ một số dữ liệu nhạy cảm đi kèm với tuần tự hóa.
Thread
(tín dụng cho @AH chẳng hạn), trong trường hợp đó bạn sẽ đánh dấu nó là tạm thời. Tuy nhiên, một luồng không phải là dữ liệu nhạy cảm trong chính nó, nó chỉ không có ý nghĩa logic để tuần tự hóa nó (và nó không được tuần tự hóa).
Theo google nghĩa thoáng qua == chỉ tồn tại trong một thời gian ngắn; vô thường.
Bây giờ nếu bạn muốn làm bất cứ điều gì thoáng qua trong java, hãy sử dụng từ khóa thoáng qua.
Q: sử dụng tạm thời ở đâu?
Trả lời: Nói chung trong java, chúng ta có thể lưu dữ liệu vào các tệp bằng cách lấy chúng trong các biến và ghi các biến đó vào tệp, quá trình này được gọi là Tuần tự hóa. Bây giờ nếu chúng ta muốn tránh dữ liệu biến được ghi vào tệp, chúng ta sẽ biến biến đó thành tạm thời.
transient int result=10;
Lưu ý: các biến tạm thời không thể là cục bộ.
Nói một cách đơn giản, từ khóa java tạm thời bảo vệ các trường khỏi được Nối tiếp như là các phần không phải là trường tạm thời của chúng.
Trong đoạn mã này, lớp trừu tượng BaseJob của chúng tôi triển khai giao diện Nối tiếp, chúng tôi mở rộng từ BaseJob nhưng chúng tôi không cần tuần tự hóa các nguồn dữ liệu từ xa và cục bộ; chỉ tuần tự hóa các trường organName và isSynced.
public abstract class BaseJob implements Serializable{
public void ShouldRetryRun(){}
}
public class SyncOrganizationJob extends BaseJob {
public String organizationName;
public Boolean isSynced
@Inject transient RemoteDataSource remoteDataSource;
@Inject transient LocalDaoSource localDataSource;
public SyncOrganizationJob(String organizationName) {
super(new
Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist());
this.organizationName = organizationName;
this.isSynced=isSynced;
}
}
Mã ví dụ đơn giản hóa cho từ khóa thoáng qua.
import java.io.*;
class NameStore implements Serializable {
private String firstName, lastName;
private transient String fullName;
public NameStore (String fName, String lName){
this.firstName = fName;
this.lastName = lName;
buildFullName();
}
private void buildFullName() {
// assume building fullName is compuational/memory intensive!
this.fullName = this.firstName + " " + this.lastName;
}
public String toString(){
return "First Name : " + this.firstName
+ "\nLast Name : " + this.lastName
+ "\nFull Name : " + this.fullName;
}
private void readObject(ObjectInputStream inputStream)
throws IOException, ClassNotFoundException
{
inputStream.defaultReadObject();
buildFullName();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("ns"));
o.writeObject(new NameStore("Steve", "Jobs"));
o.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
NameStore ns = (NameStore)in.readObject();
System.out.println(ns);
}
}
Một trường được khai báo với công cụ sửa đổi nhất thời, nó sẽ không tham gia vào quá trình tuần tự hóa. Khi một đối tượng được tuần tự hóa (được lưu trong bất kỳ trạng thái nào), các giá trị của các trường tạm thời của nó bị bỏ qua trong biểu diễn nối tiếp, trong khi trường không phải là các trường tạm thời sẽ tham gia vào quá trình tuần tự hóa. Đó là mục đích chính của từ khóa thoáng qua.
@DoNotSerialize
?