Java核心技术卷1——数据类型

1.简单的Java程序

  • 类名 驼峰命名
  • Java语言规范中main必须声明为public,main方法必须要有一个外壳类,main方法必须是静态的。若main方法退出正常,Java应用程序的退出代码为0,如果希望在终止程序时返回其他代码,需要调用System.exit方法。

2.注释

/** */ 可以自动生成文档

3.数据类型

  1. Java是强类型语言,必须为每一个变量声明一种类型。
  2. Java有一个能精确表示任意精度的算数包,通常称为大数值(big number)是一个Java对象。

3.1.整形

类型长度范围
long8(-2^ 64)–(2^64-1)
int4(-2^ 32)–(2^32-1)
short2(-2^ 16)–(2^16-1)
byte1(-2^ 8)–(2^8-1)
  • java中数据长度是固定的,不需要担心移植问题;但是c和c++中,数据类型的大小和平台有关。
  • Java没有任何无符号的int、long、byte、short类型。
  • 无符号的数据类型,即最高位不是符号位,正数用源码储存,负数用补码储存。
  • 长整型数有后缀Ll
  • 十六进制有前缀0x0X;八进制有前缀0,八进制数容易混淆,建议不用;加前缀0b0B表示二进制。
  • 可以在数字字面量间加_,只为易读,编译器会去除这些下划线。

3.2.浮点类型

类型长度
float4字节,取值有效位数6-7
double8字节。有效位数15位
  • double精度是float的两倍,大部分应用程序使用double类型
  • float有后缀Ff,无后缀的默认double类型,当然也可以加后缀D或者d表示double。
  • 表示溢出和错误的三个特殊浮点数:正无穷大(Double.POSITIVE_INFINITY)、负无穷大(Double.NEGATIVE_INFINITY)、NaN(不是一个数,0/0或者负数的平方根的结果就是NaN)(Double.NaN)
    • x==Double.NaN是错的
    • Double.isNaN(x)可以判断x是不是一个数值。
  • 数值计算不允许有误差的时候使用BIgDecimal类,浮点数用二进制表示,二进制无法准确表示1/10,十进制无法准确表示1/3.

3.3.Char

  • char原本表示单个字符,但目前有些Unicode需要用两个char值。
  • char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 );大小范围 是0—65535 ;char是一个16位二进制(16进制范围\u0000-\Uffff)的Unicode字符,JAVA用char来表示一个字符 。
  • \u转义序列后接4位16进制数,将十六进制数转换位相应的字符。Unicode转义序列会在解析代码前(编码前)得到处理。\u转义序列可以在引号之外使用,其他转义序列只能在引号的字符面量或者字符串中。
  • 其他转义序列
表示含义
\n换行符
\t横向制表符
\\反斜线
\’单引号
\"双引号
\r回车符
\b退格符
\a报警(响铃)符
\v纵向制表符
\?问号
\f进纸符

3.4.Unicode和Char

  • 码点(code point):一个编码表中的某个字符对应的代码值。
    • Unicode中码点用十六进制书写,并加前缀U+,码点分17个代码级别(code plane)
    • 第一个代码级别称为基本的多语言级别(basic multilingual plane),码点从U+0000-UFFFF,其中包括经典的Unicode代码;其余16个代码级别码点从U+10000-U+10FFFF,包括一些辅助字符(supplementary character)
    • UTF-6编码采用不同长度的编码表示所有的Unicode码点。
      • 在基本的多语言级别中,每个字符用十六位表示,通常被称为代码单元(code unit)
      • 辅助字符采用一对连续的代码单元进行编码,这样的编码值落入基本的多语言级别中空闲的2048字节内,通常被称为替代区域(surrogate area),第一单元在U+D800-U+DBFF的1024个中,第二单元在其后的1024个中.
      • Java中的Char类型描述了UTF-16编码中的一个代码单元。
      • 强烈建议不要在程序中使用char类型,除非使用处理UTF-16代码单元。

3.5.Boolean类型

  • 布尔和整数不能相互转换。
if(x = 0)     //java中不能编译,但是C++中可以,所以C++ 中要注意x==0与x=0;

4.变量

  • Java中每个变量都有类型。
  • 又字母开头,字母和数字构成的序列(这里的字母和数字包括某种语言中表示字母和数字的任何Unicode字符)(可以有_,不推荐$
  • 不推荐在一行中声明多个变量,逐一声明提高代码的可读性。许多程序员将变量名命名为类型名,也喜欢在类型名前加前缀a作为变量名。

4.1.初始化变量

  • 声明变量后必须显示地用赋值语句初始化
  • 在类中定义的成员变量如果你没有初始化java会自动帮你初始化,如果是数字会自动初始化成0,字符会初始化成'o',对象引用会初始化成null.
  • 变量的声明尽可能地靠近第一次使用的地方,是一种良好的编程风格。
  • Java不区分定义与声明,C和C++区分

4.2.常量

  • 用关键词final指示常量,表示这个变量只能被赋值一次,一旦赋值后便不能再改。
  • 习惯常量名都大写
  • 可以用static final设置一个类常量。
  • const是Java的保留关键字

5.运算符

  • 参与/运算的两个数都是整数时,表示整数除法,否则表示浮点数除法。
  • 整数除法会截断小数部分。整数除法余符号和被除数保持一致;关于商,表达式a/b的商会向0取整,即负数向上取整,正数向下取整,类似于正负数的四舍五入。
  • 运算的精度和浮点溢出、以及strictfp关键字参考核心技术1运算符部分。

5.1.数学函数与常量

  • Math类中包含了各种数学函数。
  • 静态方法处理的不是对象,非静态方法处理的是引用他的对象
  • 导入Math包(静态导入?还未学习到(2020.06.22))之后就不用再用Math.调用math中的函数了。
  • 提供了PI和e的近似值:Math.PI 和Math.E。
  • 自由发布的Math库(fdlibm)?

5.2.数值之间的转换

  • 合法转换(实箭头表示无信息丢失、虚箭头表示可能有精度损失)
byte
short
int
char
long
double
float
  • 在进行二元操作时,要先将两个操作数转换为同一种操作,然后再进行计算。
  • 有double转double,否则有下面哪个转哪个float>long>int

5.3.强制类型转换(cast)

  • 强制类型转换会截断小数部分将浮点转换为整数
  • 可以用Math.round()四舍五入对浮点数转换,但是round函数返回的是long型。
  • 当转换后超出目标类型的表示范围后,结果会截断成一个完全不同的值。

5.4.结合赋值和运算符

  • 二元运算符一般把运算符放在赋值符号左面x += 4
  • 运算符的结果会强制的转换为赋值号左侧变量相同的类型

5.5.自增自减运算符

  • 前缀形式的自增自减--i ++i先完成加1;后缀形式的先使用后完成加1.
  • 建议不要在表达式中使用++

5.6.关系和Boolean运算符

  • ==检测相等,!=检查不相等
  • $$ ||按照短路逻辑求值,第一操作数能确定值后就不再计算第二操作数。
  • 三元操作符f? x:yf表示的结果ture时返回:前面的,否则后面的。

5.7.位运算符

&and
|or
^xor
~not

  • &与|用在布尔值上时也会得到一个布尔值,但是不会再采用短路方式来求解。
  • 位运算可以掩掉其它位,而只只保留其中一位。
  • <<>>移位运算符不做细述。

5.8.括号与运算符级别

  • Java中不使用逗号运算符,但是在for语句的第一和第三部分中使用逗号分隔表达式列表。
    Java运算符优先级

5.9.枚举类型

enum K {a,b,c,d};
K ak = K.a;
  • 枚举类型的变量之只能储存这个类型声明中的某个枚举值或者null

6.字符串

String详解

  • Java字符串就是UNicode字符序列,Java没有内置的字符串类型,在标准Java库中提供了一个预定义类,叫String,每个由双引号括起来的字符串都是String类的一个实例。
  • String 继承于CharSequence。
  • CharSequence是一个接口,它只包括length(), charAt(int index), subSequence(int start, int end)这几个API接口。除了String实现了CharSequence之外,StringBuffer和StringBuilder也实现了CharSequence接口。
    需要说明的是,CharSequence就是字符序列,String, StringBuilder和StringBuffer本质上都是通过字符数组实现的!

6.1子串

  • substring(a,b) 方法的第二个参数是不想复制的第一个位置
  • substring 方法的优点是方便计算子串长b-a
String a = "abcdefg";
String b = a.substring(0,3); //实际子串是0、1、2;
//结果
b="abc"

6.2拼接

  • +号拼接
  • 字符串与非字符串拼接时,后者被转成字符串
  • Java对象都可以被转成字符串
  • 如果需要把多个字符串放在一起,用一个定界符分割
    • 使用静态方法join:
      String all = String.join("-/-", "a", "b", "c", "d");   //静态方法用类名调用。
      //结果
      all = "a-/-b-/-c-/-d"
      

6.3不可变字符串

  • String类没有提供用于修改字符串的方法,所以Java文档中将String类对象称为不可变字符串,所以Java中修改一个字符串要新建一个字符串或新建一个字符串变量引向不同的地方。
  • String str = "abcdr"中, "abcdr"永远包含a,b,c,d,r,的代码单元序列,不能修改其中任何一个。
  • 想象字符串存放在公共储存池中,字符串变量指向存储池中相应位置。
  • Java中字符串不是字符型数组
    String [] astr = "abcdefg"; 
    
    • 会报错,Java字符串不是字符型数组
    String [] bstr = {"abc","def"}
    • 正确,bstr是一个Java字符串数组
  • 不变字符串优点:
    • 编译器可以让字符串共享
  • 当引向一个字符串的变量引向另一个字符串,Java会自动的垃圾回收。

6.4检测字符串是否相

//区分大小写
s.equals(t); 
//不区分大小写
s.equalsIgnoreCase(t); 
//检测两个字符串是否在同一个位置上(想象是否在储存池的同一个位置)
if(s == "hello"); 
  • 但是储存池中可能有完全一样的字符串,且只有字符串常量是共享的,+substring操作产生的结果并不共享,所以不确定字符串==的结果,一定不要使用

6.5空串和Null串

  • 空串指""
  • Null串表示没有任何对象与该变量关联。
  • 判断空串和Null串
    //空串
    str.length() == 0;
    str.equals("");
    //Null串
    str == null;
    
    • 判断既不是空串也不是null时先检查不为null,在一个null值上调用方法,会出现一个错误。

6.6码点与代码单元

  • 代码单元(一个char值为一个代码单元)
  • length()方法返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。
  • charAt(k)方法返回位置k的代码单元,k~(0,str.length()-1)之间。
  • 码点
  • codePointCount(a,b)方法返回长度为(b-a)的代码单元中的码点数。没有配成对的代用字符计入代码点。
  • codePointAt(int index)返回从给定位置开始的码点。
  • int offsetByCodePints(int startIndex, int cpIndex)返回从头代码点开始位移cp个代码点后 的码点索引
    个人理解
  • 尽量避免使用char,太底层了。
  • int [] codePoints().toArray();会生成一个int值的流,每个int对应一个码点,,可以将他转换为数组(toArray())。反过来可以将码点数组转换成字符串,String str = new String(codePints,0,codepoints.length());
  • 其他API
int compareTo(String other);//按字典顺序,若位于other前,返回负数,否则,返回正数,相等,返回0.
new String(int [] codepints, int offset, int count);//用codepoint中的offset开始的count个码点构造一个字符串。
boolean equals(Object other);字符串相等返回ture。
boolean startsWith(String prefix);
boolean endsWith(String prefix);//是否以prefix开头或结尾。

//一些匹配方法。
		String a = "ffaehffffffffehffffffffffffffffffcdehhffff";
		String bString = "eh";
		int b = a.indexOf(bString);			//3(与bStr匹配的第一个子串的位置。
		int c = a.indexOf(bString,4);		//13(从4之后检查匹配的第一个子串的位置。
		int d = a.indexOf(102);				//0(检查码点相同的第一个代码点的位置。
		int e = a.indexOf(102, 4);			//5(检查4之后第一个匹配的代码点的位置。
		int f = a.lastIndexOf(bString);		//35
		int g = a.lastIndexOf(bString,1);	//-1
		int h = a.lastIndexOf(102);			//41
		int j = a.lastIndexOf(102, 1);		//1
		//以上”位置“均是相对与整个字符串首位置的相对位置。
		
//返回一个新字符串,用新字符代替所有旧字符,,可以用String或StringBuilder为对象作为CharSequence的参数。		
String replace(CharSequence oldString,CharSequence newString);

//大小写变换
String toLowerCase();
String toUpperCase();

//删除头部和尾部的空格,返回新的字符串
String tirm();

6.9构建字符串

  • 由较短的字符串频繁连接成的字符串,例如键盘输入字母,每次连接都会产生新的字符串,浪费时间浪费空间,所以使用StringBuilder类。
  • StringBuffer效率稍低,但是允许多线程的方式执行删除或添加字符的操作。如果所有字符在单线程中操作,应用StringBuilder。
  • API
    StringBuilder aBuilder = new StringBuilder(); //构造空的字符串构建器
    int N = aBuilder.length();//返回构建器的代码单元数量
    aBuilder.append("abc");//追加字符串并返回this
    aBuilder.append('A');//追加代码单元并返回this
    aBuilder.appendCodePoint(102);//追加码点,转换成对应的一个或者两个代码单元并返回this
    aBuilder.setCharAt(2,'z');//将2处的代码单元设置为后面的
    aBuilder.insert(2, "kkkkkkkk");//在2之后插入字符串
    aBuilder.insert(2, 'x');//插入字符
    aBuilder.delete(3,4);//删除3到4-1之间的(b-a)个代码单元
    String aString = aBuilder.toString();//返回与构建器中内容一致的字符串。
    //结果
    abc
    abcA
    abcAf
    abzAf
    abkkkkkkkkzAf
    abxkkkkkkkkzAf
    abxkkkkkkkzAf
    

7.输入输出

7.1.读取输入

  • Java.util.Scanner
    String nextLine();//读下一行
    boolean hasNext();//是否还有其他单词。
    boolean hasNextInt();//是否有下个整数序列。
    
  • Java.lang.System
    static Console console();//如果有可能进行交互操作,通过控制台窗口为交互的用户返回一个Console对象,否则返回null。
    
  • Java.io.Console
    • 因为输入可见,所以Scanner类不适用于读取密码。
    • Java SE6特别引入Console类,
    static char [] readPassword(String promit,Object ...args);
    static String readLine(sstring promit,Object ...args);
    //显示字符串promit并读取用户输入,直到输入结束。
    Console cons = System.console();
    String username = cons.readLine("enter name:");
    Char [] password = cons.readPassword("enter password:");
    
    • 为安全起见,返回的密码放在char数组中,而不是字符串,对密码处理后,应该马上用一个填充值覆盖数组元素。
    • console对象处理不如scanner方便。每次只能读一行。
      eclipse中
      控制针异常
    • 如果Java程序要与windows下的cmd或者Linux下的Terminal交互,就可以使用这个Java Console类代劳。Java要与Console进行交互,不总是能得到可用的Java Console类的。一个JVM是否有可用的Console,依赖于底层平台和JVM如何被调用。如果JVM是在交互式命令行(比如Windows的cmd)中启动的,并且输入输出没有重定向到另外的地方,那么就可以得到一个可用的Console实例。 但当使用Eclipse等IDE运行以上代码时Console中将会为null。 表示Java程序无法获得Console实例,是因为JVM不是在命令行中被调用的,或者输入输出被重定向了。在Eclipse诸如类似的IDE工具中运行Console类。如果没有对Console实例判空操作,结果使用了该实例会抛出java.lang.NullPointerException异常。
      cmd实验密码输入

7.2.格式化输出

  • print(x); //将以x对应的数据类型所允许的最大非零数字位数打印输出x;
  • printf(); //打印格式化数值。
  • 静态方法String.format(格式化字符串)创建一个格式化的字符串,而不打印输出。
  • 可以用s转换符格式化任意的对象,对于任意实现了Formattable接口的对象,都将调用formatTo方法,否则调用toString方法,将任意对象转换成字符串。
  • 每个%字符开始的格式说明符都用相应的参数替换。
    printf的转换符
    标志
  • 格式化输出时间与日期,使用java.time包的方法,以t开始,以其他时间转换符结束。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 格式说明符的语法图:在这里插入图片描述
  • 索引值从1开始。

7.3.文件输入与输出

  • 对文件读取,用File对象构造一个Scanner对象。文件地址是java虚拟机的相对位置,可以用file = System.getProperty("file.txt");找到路径位置。(没有例子不是很懂)
Scanner in = new Scanner(Path.get("gile.txt"),"UTF-8");//path.get返回path。
Scanner in = new Scanner(File file,"UTF-8");
Scanner in = new Scanner("file.txt");会将参数作为包含字符的数据。
  • 如果文件名包含反斜杠,再反斜杠前再加一个反斜杠。
  • 如果省略后面的字符编码参数,Java会使用运行这个Java程序的默认编码,在不同机器上可能有不同的结果。
  • 对文件写入,需要构建一个Print Writer对象,如果文件不存在,会新建文件。
  • 可以像输入到System.out一样使用print、printf等命令。
PrintWriter out = new PrintWriter("file.txt","UTF-8");
  • 用一个不存在的文件构造Scanner或者用一个不能被创建的文件名构造PrintWriter会发成异常,应改告诉编译器,在main方法中使用throws IOException语句标记
  • 用命令行启动程序时,可以利用Shell重定向语法将任意文件关联到System.in和System.out;
public static void main(String[] args) throws IOException {
//test5  文件的输入输出
		//因为文件结构中有“\”,所以用两个“\\”转义。
		Scanner in = new Scanner(Paths.get("D:\\JAVAeclipse\\eclipse-workspace\\SelfStudy\\src\\edu\\note\\learnbycode\\test5out.txt"),"UTF-8");
		Scanner inScanner = new Scanner(new File("D:\\JAVAeclipse\\eclipse-workspace\\SelfStudy\\src\\edu\\note\\learnbycode\\test5out.txt"));
		String aString = in.nextLine();
		System.out.println(aString);
		
		PrintWriter outPrintWriter = new PrintWriter("D:\\JAVAeclipse\\eclipse-workspace\\SelfStudy\\src\\edu\\note\\learnbycode\\test5out.txt");
		outPrintWriter.println(a);
		outPrintWriter.close();//不关闭文件中不会出现写入的字符串。
}

8.控制流程

  • java没有go to语句,但是可以用break语句跳出内层循环
  • Java不允许在嵌套的块中重定义一个变量
  • else与最近的if组成一组。
  • while循环先检查条件。
  • do y while(x);先执行一边代码。
  • 在循环中检测两个浮点数相等时要小心,有些浮点数(0.1)不能精确地用二进制表示,由于舍入的误差,最后得不到精确值而无法结束循环。

8.1.多重选择:switch语句

  • switch语句会从与选项值匹配的case处开始一直执行到遇到break语句或直到switch语句结束
  • 如果没有匹配的case,就执行default子句。
  • case标签可以是char\byte\short\int 的常量表达式、可以是枚举常量,也可以是字符串字面量。
  • case语句结尾没有break会接着判断其他case,可能会有两个相同的case,这种经常引发错误,不推荐使用switch。

8.2.中断控制流程语句

  • Java支持带标签的break语句。标签必须放在想要跳出的最外层循环之前,并且紧跟一个冒号当希望使用goto语句的时候,就可以使用带标签的break语句,但不提倡。
  • continue语句会中断正常的控制流程,将控制转移到最内层循环的首部。

9.大数值

  • 如果基本的整数和浮点数不能满足需求,可以使用java.math中的两个类:BigInteger和BigDecimal,可以处理任意长度数字序列的数值。
  • BIgInteger类实现了任意精度的整数运算。
  • BigDecimal类实现了任意精度的浮点数运算。
  • 静态方法valueOf可以将普通数值转换成大数值。
  • 不能使用熟悉的算术运算符处理大数值,需要用add和multiply方法。
BigIngeter a = BigIngeter.valueOf(100);
//和、差、积、商、余数
a=a.add(a);
a = a.subtract(a);
a = a.multiply(a);
a = a.divide(a);
BigDecimal divide(other RoundingMOde mode)//说明舍入方式。
a = a.mod(a);
//比较
int b = a.compareTo(a); 

10.数组

  • 数组是一种数据结构。
  • 创建一个数组时,数字数组初始化为0,Boolean初始化为false,对象数组初始化为null。
  • 数组一旦创建,就不能改变大小,如果需要经常扩展数组大小,应该使用另外一种数据结构-数组列表(array list)。
  • array.length获取数组的长度,当访问长度之外的元素,会发生array index out of bounds的异常而终止。

10.1.for each循环

  • 依次处理数组中每个元素而不必为下标分心
  • for(variable : collection) statement;
  • variable:定义一个变量暂时储存集合中的每一个元素,
  • collection: 必须是一个数组或者实现了Iterable接口的类对象(例如array list)
  • Arrays类的toString方法返回一个包含数组元素的字符串。这些元素被放在括号内,并用逗号隔离。
	int [] ff = new int [5];
	for (int i : ff) {
	System.out.println(i);//依次打印ff中的元素。
		}
	String fff = Arrays.toString(ff);

10.2.数组初始化及匿名数组

  • 可以不用new就创建新数组并初始化
  • 数组长度允许为0。
int [] a = {1,2,3,4,5};
  • 也可以初始化一个匿名数组,使用这种语法形式可以在不创建新变量的情况下重新初始化一个数组。
int [] b = new int [4];
b = {1,2,3,4};//错误,数组常量只能在初始化时使用。
int [] b = new int [4]{1,2,3,4};//错误,给出初始化之后就不能定义维度

int [] c = {1,2,3,4};
b = c ;
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(c));
new int [] {2,3,4,5};//错误,左侧必须是变量
d = new int [] {2,3,4,5};//错误,左侧必须是可以解析的变量。
b = new int [] {2,3,4,5};
System.out.println(Arrays.toString(b));

test

10.3.数组拷贝

  • Java允许数组变量拷贝a = b给另外一个数组变量,实际上时两个变量引用同一个数组。
  • 如果需要将数组的所有值拷贝到一个新数组,需要使用Arrays.copyOf()方法.可以改变第二个参数改变新数组的长度,(通常用该方法改变数组长度)多余的元素赋值默认,新数组短的话只拷贝前面的部分。
    int [] a = Arrays.copyOf(b,b.length);
    
  • Java中[]运算符被预定义为检查数组边界,而且没有指针运算,不能通过a+1来得到数组的下一个元素。

10.4.命令行参数

  • 每个java程序都有一个含有参数String arg[]的main方法,表明main方法接受一个字符串数组,也就是命令行参数。
  • 命令行命令java test a b c中,test是程序名,不在arg[]中。

10.5.数组排序

  • 对数值型数组排序,可以使用Arrays类中的 sort方法Arrays.sort(a),这个排序方法使用的是优化过的快速排序算法。
  • java.util.Arrays
    static string toString(type[] a);
    static type copyOf(typr [] a,int length);
    static type copyOfRange(typr [] a,int start,int end);
    //返回与a类型相同的一个数组,其长度为length或者end-start,包含start而不包含end。
    
    static void sort(type a[]);
    static int binarySearch(typr[] a,type v);
    static int binarySearch(typr[] a,int start, int end, type v);
    //二分搜索算法查找值v,如果查找成功,返回对应的下坐标,否则返回负数值r,-r-1是保持a有序v插入的位置。
    
    static void fill(type[] a,type v);//数组所有元素设置为v。
    static boolean equals(type[] a,type[] b);a与b大小相等,且对应位置分别相等。
    

10.6.多维数组

  • for each 循环不能自动处理二维数组的每一个元素,访问二维数组的每一个,可以嵌套两个for each。
  • Arrays的deepToString(a)方法可以返回一个含有所有元素的字符串,格式为[[1,2,3],[2,3,4],[3,4,5]]

10.7.不规则数组

  • Java实际上不存在多维数组,多维数组实际上是先分配一个行数长度的一维数组,每个元素又引向一个一维数组。
  • 要创建一个不规则数组,要先分配一个具有所含行数的数组
int [] [] a = new int[10][];
//可以直接对每个数组定义长度
a[3] = new int [18]; 
a[4] = new int [19];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值