Serializable的介绍

java Serializable 介绍 Java的Serializable接口是用于对象序列化的标记接口。它允许JVM将对象状态转换为字节流,实现持久化存储、网络传输和深拷贝等功能。核心机制是通过反射获取非transient/static字段生成二进制流。主要应用场景包括RPC调用、会话管理、消息队列等。优点是开箱即用、支持对象图,但存在性能低、安全性差等缺点。高阶技巧包括使用serialVersionUID控制版本、transient忽略敏感字段、自定义序列化逻辑等。若不实现该接口,将无法使用Java原生序列化功能。建议在纯Java环境使用Se 阅读详情
一、Serializable接口
java的“对象序列化”能将一个实现了Serilizable接口的对象转换成一组byte,日后要用这个对象的时候,能把这些byte数据恢复出来,并据此重构那个对象。在跨网络环境下也是如此,序列化具有跨平台性。
之所以加入对象序列化是要用它来实现两个重要功能:java远程方法调用(RMI,Remote Method Invocation)能像调用自己机器上的对象那样去调用其他机器上的对象。当向远程对象传递消息的时候,就需要通过对象序列化来传送参数和返回值。对javaBean来说,Bean的状态信息通常是在设计时配置的,这些状态信息必须保存起来,供程序启动时用。对象序列化就是负责这些工作的。
要序列化对象,必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。用writeObject()方法把对象写入OutputStream。读的时候,把InputStream嵌到ObjectInputStream里,然后再调用readObject()方法,得到一个Object的引用,根据需要进行类型转换。
对象序列化不仅能保存对象的副本,还会把它引用的对象也保存起来,然后再继续跟踪那些对象的引用。涵盖的范围不仅包括对象的成员数据,而且包含数组里的引用。(这个是自动进行的,不需要我们编写代码)
序列化能实现轻量级的persistence。(persisitence是指,对象的生命周期不是由程序是否运行决定,在程序的两次调用之间对象仍然还活着)通过将序列化处理的对象写入磁盘,等到程序再次运行的时候再把它读出来,可以达到persistence的效果,之所以是“轻量级”是因为不能用像“persistent”这样的关键词来直接定义一个对象,然后让系统处理所有的细节。相反,必须明确进行序列化和解序列化(desierialize)。
二、相关说明与案例(一):
java有个特点就是序列化,简单地来说就是可以将这个类存储在物理空间(当然还是以文件的形式存在),那么当你从本地还原这个文件时,你可以将它转换为它本身。这可以极大地方便网络上的一些操作,但同时,因为涉及到安全问题,所以并不希望把类里面所有的东西都能存储(因为那样,别人可以通过序列化知道类里面的内容),那么我们就可以用上transient这个关键字,它的意思是临时的,即不会随类一起序列化到本地,所以当还原后,这个关键字定义的变量也就不再存在。
通常,我们写的程序都要求特定信息能持久存在或保存到磁盘上,以供一个程序使用或用在同一个程序的另一次运行上.这种持久性可以通过几种方式来实现,包括写到数据库中或是利用JAVA为对象序列化提供的支持.不管我们选用什么方法,类实例的持久性都是通过保存类的域的状态来完成的,保存这些状态,以便以后可以对它们进行访问或使用它们来创建相同的实例.然而,有可能并不是所有的域都需要被保存起来.当一个实例被持久化时,其内部的一些域却不需要持久化,则可以用trainsient修饰符告诉编译器指定的域不需要被持久保存.
首先,让我们看一些Java serialization的代码:
public class LoggingInfo implements java.io.Serializable
{
private Date loggingDate = new Date();
private String uid;
private transient String pwd;

LoggingInfo(String user, String password)
{
uid = user;
pwd = password;
}
public String toString()
{
String password=null;
if(pwd == null)
{
password = "NOT SET";
}
else
{
password = pwd;
}
return "logon info: n " + "user: " + uid +
"n logging date : " + loggingDate.toString() +
"n password: " + password;
}
}
现在我们创建一个这个类的实例,并且串行化(serialize)它 ,然后将这个串行化对象写如磁盘。

LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS");
System.out.println(logInfo.toString());
try
{
ObjectOutputStream o = new ObjectOutputStream(
new FileOutputStream("logInfo.out"));
o.writeObject(logInfo);
o.close();
}
catch(Exception e) {//deal with exception}
To read the object back, we can write

try
{
ObjectInputStream in =new ObjectInputStream(
new FileInputStream("logInfo.out"));
LoggingInfo logInfo = (LoggingInfo)in.readObject();
System.out.println(logInfo.toString());
}
catch(Exception e) {//deal with exception}
如果我们运行这段代码,我们会注意到从磁盘中读回(read——back (de-serializing))的对象打印password为"NOT SET"。这是当我们定义pwd域为transient时,所期望的正确结果。
现在,让我们来看一下粗心对待transient域可能引起的潜在问题。假设我们修改了类定义,提供给transient域一个默认值,
代码如下:

public class GuestLoggingInfo implements java.io.Serializable
{
private Date loggingDate = new Date();
private String uid;
private transient String pwd;

GuestLoggingInfo()
{
uid = "guest";
pwd = "guest";
}
public String toString()
{
//same as above
}
}
现在,如果我们穿行化GuestLoggingInfo的一个实例,将它写入磁盘,并且再将它从磁盘中读出,我们仍然看到读回的对象打印password 为 "NOT SET"。
当从磁盘中读出某个类的实例时,实际上并不会执行这个类的构造函数,
而是载入了一个该类对象的持久化状态,并将这个状态赋值给该类的另一个对象。
例:
Which three concerning the use of the java.io.Serializable interface are
true? (Choose three.)
A. Objects from classes that use aggregation cannot be serialized.
B. Art object serialized on one JVM can be successfully deserialized on
a different JVM.
C. The values in fields with the volatile modifier will NOT survive
serialization and deserialization.
D. The values in fields with the transient modifier will NOT survive
serialization and deserialization.
E. It is legal to serialize an object of a type that has a supertype that
does NOT implement java.io.Serializable.
Answer: BDE
 
三、相关说明与案例(二):
在JAVA中,一个大的应用程序需要保存很多对象的时候,由于虚拟机内存有限,(资源宝贵啊 )有时不可能所有有用的对象都放到内存中,因此,需要将不常用的对象暂时持久化的文件中,当需要这个对象时,再从文件把对象恢复到内存中,这就是所谓对象的序列化和反序列化。本文讲实现如何将对象序列化到文件,然后再从文件反序列化到对象,你会发现其实特别简单
先看一下对象的序列化和反序列化的关键是什么
1,首先被序列化的对象必须实现 java.io.Serializable 接口,其实这个接口没定义任何方法
2,序列化时,需要用到对象输出流ObjectOutputStream ,然后通过文件输出流构造 ObjectOutputStream 对象调用writeObject写入到文件(或者是writeIntwriteShort等写入基本数据类型)
3,反之,反序列化时用到对象输入流ObjectIntputStream, 然后通过文件输出流构造 ObjectIntputStream对象调用readObject加载到内存,注意,是返回万能Object类型(或者是readIntreadShort等读入基本数据类型)
4,注意:序列化时transient变量(这个关键字的作用就是告知JAVA我不可以被序列化)和静态变量不会被序列化(关于静态变量不会序列化保留意见,本实例先不用静态变量)
5,顺序问题,如果你先序列化对象A后序列化B,那么在反序列化的时候一定记着JAVA规定先读到的对象是先被反序列化的对象,不要先接收对象B,那样会报错,所以反序列化时要还是先反序列化A再B
好了,现在我们做一个实例,我们现在要序列化一个会员对象到文件里,然后再把它读出来
先创建会员类
Java代码
 
 
1. import java.io.*;
2. import java.util.*;
3.
4. //一定要实现Serializable接口才能被序列化
5. public class UserInfo implements Serializable {
6. public String userName;
7. public String userPass;
8. //注意,userAge变量前面的transient
9. public transient int userAge;
10.
11. public UserInfo(){
12. }
13.
14. public UserInfo(String username,String userpass,int userage){
15. this.userName=username;
16. this.userPass=userpass;
17. this.userAge=userage;
18. }
19.
20. public String toString(){
21. return "用户名: "+this.userName+";密码:"+this.userPass+
22. ";年龄:"+this.userAge;
23. }
24. }
import java.io.*;
import java.util.*;
 
//一定要实现Serializable接口才能被序列化
public class UserInfo implements Serializable {
public String userName;
public String userPass;
//注意,userAge变量前面的transient
public transient int userAge;
 
public UserInfo(){
}
 
public UserInfo(String username,String userpass,int userage){
this.userName=username;
this.userPass=userpass;
this.userAge=userage;
}
 
public String toString(){
return "用户名: "+this.userName+";密码:"+this.userPass+
";年龄:"+this.userAge;
}
}
接着我们开始写如何序列化和反序列化,初学认真看哦
Java代码
 
 
1. import java.io.*;
2. import java.util.*;
3. public class Test {
4.
5. //序列化对象到文件
6. public static void serialize(String fileName){
7. try
8. {
9. //创建一个对象输出流,讲对象输出到文件
10. ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));
11.
12. out.writeObject("序列化日期是:"); //序列化一个字符串到文件
13.
14. out.writeObject(new Date()); //序列化一个当前日期对象到文件
15.
16. UserInfo user=new UserInfo("renyanwei","888888",20);
17. out.writeObject(user); //序列化一个会员对象
18.
19. out.close();
20. }
21. catch (Exception x)
22. {
23. System.out.println(x.toString());
24. }
25.
26. }
27. //从文件反序列化到对象
28. public static void deserialize(String fileName){
29. try
30. {
31. //创建一个对象输入流,从文件读取对象
32. ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));
33.
34. //注意读对象时必须按照序列化对象顺序读,否则会出错
35. //读取字符串
36. String today=(String)(in.readObject());
37. System.out.println(today);
38.
39. //读取日期对象
40. Date date=(Date)(in.readObject());
41. System.out.println(date.toString());
42.
43. //读取UserInfo对象并调用它的toString()方法
44. UserInfo user=(UserInfo)(in.readObject());
45. System.out.println(user.toString());
46.
47. in.close();
48. }
49. catch (Exception x)
50. {
51. System.out.println(x.toString());
52. }
53.
54. }
55.
56. public static void main(String[] args) {
57. serialize("D:test.txt");
58. System.out.println("序列化完毕");
59.
60. deserialize("D:test.txt");
61. System.out.println("反序列化完毕");
62. }
63.
64. }
import java.io.*;
import java.util.*;
public class Test {
 
//序列化对象到文件
public static void serialize(String fileName){
try
{
//创建一个对象输出流,讲对象输出到文件
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));
 
out.writeObject("序列化日期是:"); //序列化一个字符串到文件
 
out.writeObject(new Date()); //序列化一个当前日期对象到文件
 
UserInfo user=new UserInfo("renyanwei","888888",20);
out.writeObject(user); //序列化一个会员对象
 
out.close();
}
catch (Exception x)
{
System.out.println(x.toString());
}
 
}
//从文件反序列化到对象
public static void deserialize(String fileName){
try
{
//创建一个对象输入流,从文件读取对象
ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));
 
//注意读对象时必须按照序列化对象顺序读,否则会出错
//读取字符串
String today=(String)(in.readObject());
System.out.println(today);
 
//读取日期对象
Date date=(Date)(in.readObject());
System.out.println(date.toString());
 
//读取UserInfo对象并调用它的toString()方法
UserInfo user=(UserInfo)(in.readObject());
System.out.println(user.toString());
 
in.close();
}
catch (Exception x)
{
System.out.println(x.toString());
}
 
}
 
public static void main(String[] args) {
serialize("D:test.txt");
System.out.println("序列化完毕");
 
deserialize("D:test.txt");
System.out.println("反序列化完毕");
}
 
}
运行结果:

序列化完毕
今天是:
Thu Oct 23 18:31:11 CST 2008
用户名: renyanwei;密码:888888;年龄:0
反序列化完毕
我们看代码总结一下,serialize方法实现了对象的序列化功能,讲对象序列化到文件,使用了文件的输出流ObjectOutputStream 的writerObject方法一次写入一个对象,对象在文件中按写入顺序存储。
deserialize方法实现反序列化,从文件将对象反序列化到内存,使用了ObjectIntputStream 的readObject方法,因为序列化对象是按照写入顺序存储的,所以在反序列化时必须按照写入顺序读取
大家看了结果就应该知道了,标明transient的实例变量是没被序列化进去的
其实序列化的意义不止如此,不但可以将对象放到文件流,还可以放到网络流里,比如我们做的Socket程序,你不但可以发送给对方一行消息,还可以发送过去一个对象,我估计QQ就不止是把我们的消息发送到对方,应该是一个对象,里面包含了发送者的信息什么的。
1. import java.io.*;
2. public class Foo implements Serializable {
3. public int x, y;
4. public Foo( int x, int y) { this.x = x; this.y = y; }
5.
6. private void writeObject( ObjectOutputStream s)
7. throws IOException {
8. s.writeInt(x); s.writeInt(y)
9. }
10.
11. private void readObject( ObjectInputStream s)
12. throws IOException, ClassNotFoundException {
13.
14. // insert code here
15.
16. }
17. }
Which code, inserted at line 14, will allow this class to correctly
serialize and deserialize?
A. s.defaultReadObject();
B. this = s.defaultReadObject();
C. y = s.readInt(); x = s.readInt();
D. x = s.readInt(); y = s.readInt();
Answer: D
 
Given:
12. import java.io.*;
13. public class Forest implements Serializable {
14. private Tree tree = new Tree();
15. public static void main(String [] args) {
16. Forest f= new Forest();
17. try {
18. FileOutputStream fs = new FileOutputStream(”Forest.ser”);
19. ObjectOutputStream os = new ObjectOutputStream(fs);
20. os.writeObject(f); os.close();
21. } catch (Exception ex) { ex.printStackTrace(); }
22. } }
23.
24. class Tree { }
What is the result?
A. Compilation fails.
B. An exception is thrown at runtime.
C. An instance of Forest is serialized.
D. A instance of Forest and an instance of Tree are both serialized.
Answer: B
java.io.NotSerializableException: Tree
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at Forest.main(Forest.java:20
 
如果把Tree也实现序列化接口implements Serializable就OK了
把14. private Tree tree = new Tree();改成private Tree tree;也行。
 
如果一个可序列化类有多个父类(包括直接或间接父类),则该类的所有父类要么是可序列化的,要么有无参数的构造器——否则会反序列化时抛出InvalidClassException异常。
当程序创建子类实例时,系统会隐式地为它的所有父类都创建实例(并建立和此子类实例的关联)!当我们反序列化某个子类的实例时,反序列化机制需要恢复其关联的父类实例,恢复这些父类实例有两种方式:
A.使用反序列化机制。
B.使用父类无参数的构造器。
在上面两种方式中,反序列化机制优先采用第一种机制。如果某个父类既不可序列化(没有implements Serializable),即不能使用第一种机制;也没有提供无参数的构造器,则不可采用第二种机制,则反序列化该子类实例将抛出异常。
 
Assuming that the serializeBanana2() and the deserializeBanana2()
methods will correctly use Java serialization and given:
13. import java.io.*;
14. class Food {Food() { System.out.print(”1”); } }
15. class Fruit extends Food implements Serializable {
16. Fruit() { System.out.print(”2”); } }
17. public class Banana2 extends Fruit { int size = 42;
18. public static void main(String [] args) {
19. Banana2 b = new Banana2();
20. b.serializeBanana2(b); // assume correct serialization
21. b = b.deserializeBanana2(b); // assume correct
22. System.out.println(” restored “+ b.size + “ “); }
23. // more Banana2 methods
24. }
What is the result?
A. Compilation fails.
B. 1 restored 42
C. 12 restored 42
D. 121 restored 42
E. 1212 restored 42
F. An exception is thrown at runtime.
D
Class not found so assuming code is running on a pre-Java 9 JVM 问题描述: idea进行springboot开发时,进行日志输出模式修改,之前没有对日志的级别进行设置,启动的时候也没有发现有什么问题。当把日志级别调整到debug时,启动springboot项目问题出现了,我当时用的jdk是1.8 Class not found so assuming code is running on a pre-Java 9 JVM 翻译: 找不到类,所以假设代码运行在java 9之前的jvm上 完整的异常信息: 2020-06-21 17:44:19.102 DEB 阅读详情

相关推荐

异常 Serializable接口无法实现 类不能被序列化

java.io.NotSerializableException: demo9.Student at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) at demo9...

the_next_one_is_you的博客 3343

java 区分 method isaccessible_关于java Serializable接口的问题

展开全部是工具自己生32313133353236313431303231363533e59b9ee7ad9431333262363731成的,你可以不去管他。Serializable接口本身什么方法都没有。/*** Serializability of a class is enabled by the class implementing the* java.io.Serializable in...

weixin_35853363的博客 205

Java17的踩坑点

模块化,模块系统将 Java 分成了若干个可以独立部署和运行的模块,使得 Java 应用可以更快地启动并更好地利用硬件资源。但在 java 模块化之后,有些内部类不能被访问了,在运行时报错。比如我在使用 DTS 的 sdk 时候,报如下错误,导致不能启动。如果是在 idea 启动程序,在 vm options 添加参数。解决方法,在运行程序的命令加上参数。如果是命令行启动程序,

decaffeinated的博客 1039

Java序列化魔术方法及其示例使用

In a previous article Everything You Need to Know About Java Serialization, we discussed how serializability of a class is enabled by implementing the Serializable interface. If our class doe...

专业的开发者“讨论” 551

java中Serializable接口的介绍

Serializable接口是Java中的一个标记接口,用于实现Java类的序列化操作。序列化是将对象的状态信息转换为可以存储或传输的形式的过程,而反序列化则是从存储或传输的形式中提取对象的状态信息并恢复为原始对象的过程。首先,类的所有域必须是可序列化的,或者使用transient关键字标记不可序列化的域。不可序列化的域在对象序列化时会被忽略。总的来说,Serializable接口为Java对象提供了一种方便的数据持久化和网络传输机制,但开发者在使用时也需要注意其潜在的安全问题和性能问题。

蜗牛Clear的博客 411

Android Serializable介绍

介绍:从字面意思来看,Serializable被翻译为序列化。序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。java中,对象由属相和方法组成,序列化只处理属性不处理方法。为什么要序列化?对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。譬如通过网络传输,或者把一个对象保存成一个文件的时候,要实现序列化接口 。需

geckhan的博客 396

序列化-Serializable和Parcelable的简单介绍

文章目录序列化的本质Serializable序列化过程反序列化过程ExternalizableParcelable 序列化的本质 序列化是一种用来处理对象流的机制。序列化是为了解决在对对象流进行读写操作时所引发的问题。 序列化:将java对象转换成字节序列的过程,字节码可以保存到数据库、内存、文件等,也可用于网络传输 反序列化:将字节序列恢复为java对象的过程。 序列化实现的方式有很多方案,在java中是使用的JDK内置的Serializable接口来实现序列化,而Android SDK中增加Parcel

csdnxia的博客 656

Serializable、synchronized、transient、volatile的用法与介绍

在看链表的时候,看到transient关键词:然后就去百度了一下,发现相关的有四个,这边通过个人的理解,简单概括了一下。Serializable:序列化(串行化),反序列化(并行化)在java中得数据要被序列化成字节流,才嫩和在磁盘io和网络io中传输,需要继承Serializable接口。Serializable接口类似于一个声明,没有具体的方法,只是表明使用了序列化协议。transient:1...

Deegue 1475

Serializable简单介绍

Serializable简单介绍

TRK_YX的博客 4777

详细介绍Serializable的使用和注意事项

引言 本篇文章目的在于注意使用Serializable过程中的注意事项 开启Serializable Serializable是Java提供的一套标准的序列化接口,是一个空接口,为对象提供序列化和反序列化操作.使用也是相当的简单,只要实现接口即可. 使用Serializable实现序列化非常简单,

MrQ 3489

Serializable和Parcelable的简单介绍

  Serializable和Pacelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用Parcelable或者SerializableSerializable接口   ...

weixin_33958366的博客 83

[Flutter]Json序列化json_serializable使用属性全介绍

json_serializable参数介绍

曹世鑫的杂谈 3576

IPC通信基础介绍Serializable和Parcelable详解

IPC通信基础介绍Serializable和Parcelable详解 都是用来序列化的,什么时候用到序列化呢? 1、把对象持久化到存储设备上,保存对象的字节序列到本地文件中。 2、通过网络传输给其他客户端。 3、通过Intent和Binder传输数据。 Serializable接口   serializable是java提供的一个序列化接口,它是一个空接口,使用特别简单,只需

菜鸟闯天下的专栏 776

Serializable 介绍

今天咱们简单介绍一些serializable。 1、序列化是干什么的?   简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。 2、什么情况下需要序列化?     a)当你想把的内存中的对象状态...

weixin_34129696的博客 89

ArrayList中标记性接口介绍----Serializable、Cloneable、RandomAccess

文章目录0. 前言1. Serializable序列化接口2. Cloneable克隆标记性接口: 用于克隆3. 传统方法拷贝4. 浅拷贝与深拷贝5. RandomAccess标记接口:支持快速的随机访问 0. 前言 通过这篇文章你可以了解Serializable、Cloneable、RandomAccess这些标记性接口的作用。 你可以了解到什么是浅拷贝、什么是深拷贝。 什么是随机访问、什么是顺序访问 1. Serializable序列化接口 序列化接口没有方法或字段,仅仅用于标识可串行化的语义。

搏·梦的博客 357

IPC基础概念介绍第一篇(Serializable接口)

IPC主要包括Serializable接口,Parcelable接口以及Binder。1.Serializable是java所提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化操作。使用Serializable来实现序列化相当简单,只需要在类中申明如下指定一个表示符即可实现默认序列化过程。private static final long serialVersionUID=871

yaohui_的博客 2065

Serializable java序列化介绍

Bean Serializable Interface的接口让BEAN可以串行化,将其变成一个可保存为以后使用的二进制流。当一个BEAN被系列化到磁盘上或者其他任何地方,其状态被保存起来,其中的属性值也不会改变。在BEAN的规范中,JSP并没有要求BEAN实现Serializable接口。但是,如果您希望自己控制您所创建的组件的serialization进程,或者您想serialize

yiihsia的学习阵地 1474

Java 序列化Serializable接口介绍

Java中的序列化是指将对象转换为字节序列,以便在网络上传输或者保存到文件系统中。反序列化则是将字节序列重新转换为对象。Java提供了内置的序列化机制,使得开发人员可以轻松地实现对象的序列化和反序列化。

qq_27390023的博客 351
上一篇: 在struts中如何去掉在页面显示的ul li
下一篇: MSDE2000和SQL Server的区别
追_梦
博客等级 码龄15年 11粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值