字符串

》》不可变String

       @@ String 对象是不可变的。

       @@ String 类中每一个看起来会修改 String 值的方法,实际上都是创建了一个全新的

              String 对象,以包含修改后的字符串内容。而最初的 String 对象则丝毫未动。

       @@ 每当把 String 对象作为方法的参数时,都会复制一份引用,而该引用所指的对象

                其实一直待在单一的物理位置上,从未动过。

       @@ 例如:

               public String upcase( String s){

                      return   s.toUpperCase();

               }

             说明:上面的 upcase () 的返回值,其实只最终结果的引用。这足以说明,

              upcase ()  的引用已经指向了一个新的对象

       @@ 对于一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己的。

》》重载 ”+“ 与 StringBuilder

        @@ String 对象是不可改变的,你可以给一个String 对象加任意多个别名。因为 String

                对象具有只读特性,所以指向它的任何引用都不可能改变它的值,因此,也就不会

                对其他的引用有什么影响。

        @@ 用于 String 的 “+”与 “+=” 是 Java 中仅有的两个重载过的操作符,而 Java 并不允许

                程序员重载任何操作符。

         @@  操作符 “ + ” 可以用来连接 String 。

         @@  如果想看到 java 代码是如何工作的,可以用 JDK 自带的工具 javap 来反编译 java

                 代码

         @@ 需要重点注意的是:编译器会自动引入了  java.lang.StringBuilder 。虽然我们在

                源码里面并没有使用 StringBuilder 类,但是编译器却自作主张地使用了它,因为它

                更高效。

         @@ 编译器创建了一个 StringBuilder 对象,用以构造最终的 String ,并为每个字符串调用

               一次 StringBuilder 的 append() 方法。最后调用 toString() 生成结果。

         @@ 使用 StringBuilder 对象 可以优化字符串的处理性能。

         @@ 显式的创建 StringBuilder 对象允许你预先为其指定大小。如果你已经知道最终的字符串

               大概有多长,那预先指定 StringBuilder 的大小可以避免多次重新分配缓冲

         @@ 当你为一个类编写 toString() 方法时,如果字符串操作比较简单,那就可以信赖编译器,

               它会为你合理地构造最终的字符串结果。但是,如果你要在 toString() 方法中使用循环,

                那么最好自己创建一个 StringBuilder 对象,用它来构造最终的结果。

            例如:

               public Random rand = new Random(47);

               public String toString() {

                    StringBuilder   result = new StringBuilder ("[");

                    for( int i = 0 ; i < 25 ; i++ ){

                        result.append( rand.nextInt(100));

                        result.append(",");

                    }

                       result.append("]");

                    return result.toString();

               }

         @@ 如果拿不准该用哪种方式,随时可以用 javap 来分析你的程序。(通过反编译来找合适的思路)。

》》无意识的递归

         @@ Java 的每个类从根本上都是继承自 Object ,标准容器类也不例外。因此容器类都有 toString()

                 方法,并且覆写了该方法,使得它生成的 String 结果能够表达容器自身,以及容器所包含的对象。

                例如:

                   ArrayList.toString() 它会遍历 ArrayList 中包含的所有对象,调用每个元素上的 toString() 方法。

         @@ 如果想要 toString() 方法打印出对象的内存地址,应该调用的是:Object.toString() 方法

》》String 上的操作

         @@ 以下是一些 String 对象具备的一些基本方法:

              

                   从上面这个表中可以看出,当需要改变字符串的内容时,String 类的方法都会返回一个新的

              String 对象。同时,如果内容没有发生改变,String 方法只是返回指向原对象的引用而已。这样

              可以节约存储空间以及避免额外的开销。

》》格式化输出

     ## printf()

          @@ 使用特殊的占位符来表示数据将来的位置,而且它还将插入格式化字符串的参数,以逗号分隔,

                 排成一行。

           例如:

                printf(" Row1 : [%d  %f] \n" , x , y )

              说明: 上面这行代码在运行的时候,首先将 x 的值插入到 %d 的位置,然后将 y 的值插入到 %f

              的位置。%d , %f 这些占位符称作格式修饰符,它们不但说明了插入数据的位置,同时还说明了将

             插入什么类型的变量,以及如何对其格式化。这上面的例子中, %d 表示 x 是一个整数, %f 表示

             y 是一个浮点数(float 或者 double)

     ## System.out.format()

          @@  format() 方法可用于 PrintStream 或者 PrintWriter 对象,其中也包括 System.out 对象。

          @@  format() 与 printf() 是等价的。

               例如:

              printf(" Row1 : [%d  %f] \n" , x , y );

              format(" Row1 : [%d  %f] \n" , x , y ) ;

     ## Formatter 类

          @@ 在Java 中,所有新的格式化功能都由 java.util.Formatter 类处理。可以将 Formatter 看作一个

              翻译器,它将你的格式化字符串与数据翻译成需要的结果。当你创建 Formatter 对象的时候,

             需要向其构造器传递一些信息,告诉它最终的结果将向哪里输出。

         @@ new Formatter(System.out)

                表明输出将输出到 System.out

         @@ Formatter 的构造器经过重载可以接受多种输出目的地,不过最常用的还是 PrintStream

               OutputStream File

     ## 格式化说明符

         @@ 在插入数据时,如果想要控制空格与对齐,你需要更精细复杂的格式修饰符。以下是其抽象

               的语法:

               %[argument_index$] [flags] [width] [.precision] conversion

         @@ 最常见的应用是一个域的最小尺寸,这可以通过指定 width 来实现。

         @@ Formatter 对象通过在必要时添加空格,来确保一个域至少达到某个长度。

         @@ 在默认情况下,数据是右对齐,不过可以使用 “ - ” 标志来改变对齐方向。

         @@ 使用 precision 来指明最大尺寸

         @@ width 可以用于各种类型的数据转换,并且其行为方式一样。

         @@ precision 与 width 不同:

               ---- 不是所有的数据都能使用 precision , 而且,应用于不同类型的数据转换时,precision

                    的意义也不同

               ----  将 precision 应用于 String 时,它表示打印 String 时输出字符的最大数量。

               ----  将 precison 应用于浮点数时,它表示小数部分要显示出来的位数(默认是 6 位数),如果

                    小数位数过多则舍入,太少则在尾部补零。

               ---- 整数没有小数部分,所以 precision 无法应用于整数,如果你对整数应用 precision ,

                   则会触发异常。

     ## Formatter 转换

            @@ 下面表格中包含了最常用的类型转换:

                 

               补充:----- 将 b 应用于非布尔类型的对象时请格外小心。

                        ------ 还有许多不常用的类型转换与格式修饰符选项,可以在 JDK 文档中 Formatter

                               类部分找到

    ## String.format()

         @@ String.format() 是一个 static 方法,它接受与 Formatter.format () 方法一样的参数,但

               返回一个 String 对象。当你只需要使用 format() 方法一次的时候,String.format() 用起来

              很方便。

         @@ 其实在 String.format() 内部,它也是创建一个 Formatter 对象,然后将你传入的参数转给

              该 Formatter 。

         @@ 为了打开以及读入二进制文件,我们用到另一个工具 net.mindview.util.BinaryFile

》》正则表达式

      @@ 在Java 中,字符串操作还主要集中于 String 、 StringBuffer 和 StringTokenizer 类。与正则

            表达式相比较,它们只能提供相当简单的功能。

      @@ 正则表达式是一种强大而灵活的文本处理工具。

      @@ 使用正则表达式,我们能够以编程的方式,构造复杂的文本模式,并对输入的字符串进行搜索。

             一旦找到匹配这些模式的部分,你就能够随心所欲地对它们进行处理。

      @@ 正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题:匹配 、

             选择 、 编辑以及验证。

     ## 基础

       @@ 一般来说,正则表达式就是以某种方式来描述字符串。

       @@ 要找一个数字,它可能有一个负号在最前面,那你就写一个负号加上一个问号,就像下面:

                -?

       @@  如果想表示一位数字,那么正则表达式应该是  \\d  。

       @@  如果你想插入一个普通的反斜线,那么正则表达式应该是  \\\\

       @@  换行  , 正则表达式为 \n  (使用单反斜线)。

       @@  制表符 ,正则表达式为 \t (使用单反斜线) 。

       @@  要表示 “ 一个或多个之前的表达式 ” ,应该使用 +

       @@ 例如:

               System.out.println("-1234".matches("-?\\d+"));

               System.out.println("+911".matches("(-|\\+)?\\d+"));

         说明:a ) 、 (-|\\+)?

                          ---- 可能以一个加号或减号开头

                          ---- 在正则表达式式中,括号有着表达式分组的效果,而竖直线 | 则表示操作。

                          ---- (-|\\+)?  这个正则表达式表示字符串的起始字符可能是一个 - 或 + ,或二者皆没有

                             (因为后面跟着? 修饰符)。因为字符 + 在正则表达式中有特殊的意义,所以必须

                             使用 \\ 将其转义,使之成为表达式中的一个普通字符。

       @@ String 类还自带一个非常有用的正则表达式工具--------split() 方法其功能是“ 将字符串从正则

             表达式匹配的地方切开 ” 。

             例如:

                public static void main(String[] args){

                      split("  ");           // 按空格来划分字符串

                      split("\\W+");    

                      split("n\\W+");    // 字母 n 后面跟着一个或多个非单词字符

                }

             说明: 后面两个都用了  \W , 它的意思是非单词字符  (如果 W 小写, \w 则表示一个单词字符

      @@  String.split() 还有一个重载的版本,它允许你限制字符串分割的次数。

      @@  String 类自带的最后一个正则表达式工具是“ 替换 ” 。你可以只替换正则表达式第一个匹配的子串,

              或是替换所有匹配的地方。

              例如:

               staitc String s = Splitting.knights;

               public static void main(String[] args){

                    // 字母 f 开头,后面跟一个或多个字母(注意这里是 w 小写的),并且只能替换掉第一个匹配

                   的部分

                    print(  s.replaceFirst( "f\\w+" , 'located' ) ) ;

                   // 下面表达式要匹配的是三个单词中的任意一个,因为它们以竖直线分隔表示 “或” ,并且替换

                  所有匹配的部分

                    print(  s.replaceAll( " shrubbery | tree | herring  " , 'located' )  ) ;

               }

          @@ String 之外的正则表达式还有更强大的替换工具。例如,可以通过方法调用执行替换。而且,如果

                正则表达式不是只使用一次的话,非 String 对象的正则表达式明显具备更佳的性能。

     ## 创建正则表达式

          @@ 正则表达式的完整构造子列表,参考 JDK 文档 java.util.regex 包中的 Pattern 类

          @@  字符

               

         @@  字符类(学会使用字符类之后,正则表达式的威力才能真正显示出来)。下面是一些

                创建字符类的典型方式,以及一些预定义的类:

                  

          @@  逻辑操作符

    

      @@ 边界匹配符

      

  @@ 我们的目的不是编写最难理解的正则表达式,而是尽量编写能够完成任务的、最简单

               以及最必要的正则表达式。一旦真正开始使用正则表达式了,你就会发现,在编写新的

              表达式之前,你通常会参考代码中已经用到的正则表达式。

 ## 量词

       @@ 量词描述了一个模式吸收输入文本的方式

              贪婪型:量词总是贪婪的,除非有其他的选项被设置。贪婪表达式会为所有可能的模式

                          发现尽可能多的匹配。导致此问题的一个典型理由就是假定我们的模式仅能匹配

                          第一个可能的字符组,如果它是贪婪的,那么它就会继续往下匹配。         

              勉强型:用问号来指定,这个量词匹配满足模式所需的最少字符数。因此也称为懒惰的、

                          最少匹配的、非贪婪的、或不贪婪的。

              占有型:目前,这种类型的量词只有在 Java 语言中才可用(在其他语言中不可用),并且

                          也更高级,因此我们大概不会立刻用到它。当正则表达式被应用于字符串时,它会

                         产生相当多的状态,以便在匹配失败时可以回溯。而 “占有的 ” 量词并不保存这些中

                         间状态,因此它们可以防止回溯。它们常常用防止正则表达式失控,因此可以使正则

                         表达式执行起来更有效。

         @@ 

                       

                  补充:应该非常清楚地意识到,表达式 X 通常必须要用圆括号括起来,以便它能按照我们

                  期望的效果去执行。例如:

                  (abc)+

         @@  正则表达式是一种在 Java 之上新语言。

         @@  接口 CharSequence 从 CharBuffer 、 String 、 StringBuffer 、 StringBuilder 类之中抽象出

                 了字符序列的一般化定义。

                  因此,这些类都实现了该接口。多数正则表达式操作都接受  CharSequence  类型的参数

     ## Pattern 和 Matcher

         @@ 一般来说,比起功能有限的 String 类,我们更愿意构造功能强大的正则表达式对象。只需要

              导入 java.util.regex 包,然后用 static  Pattern.compile() 方法(生成一个 Pattern  对象)

              来编译你的正则表达式即可。

              它会根据你的 String 类型的正则表达式生成一个 Pattern 对象。

              把你想要检索的字符串传入 Pattern 对象的 matcher() 方法。matcher() 方法会生成一个 Matcher

              对象,它有很多功能可用(参考 java.util.regex.Matcher 的JDK 文档)

         @@  在 Unix / Linux 上,命令行中的正则表达式必须用引号括起来

         @@  Pattern 对象表示编译后的正则表达式

         @@  Pattern 类还提供了 static 方法:

                  static boolean  matches(String  regex  , CharSequence  input)

                 该方法用以检查  regex 是否匹配整个 CharSequence  类型的 input 参数 。

         @@   编译后的 Pattern 对象还提供了 split() 方法,它从匹配了 regex 的地方分割输入

                 字符串,返回分割后的子字符串 String 数组。

         @@  通过调用  Pattern.matcher() 方法,并传入一个字符串参数,我们得到一个 Matcher 对象。

                 使用 Matcher 上的方法,我们将能够判断各种不同类型的匹配是否成功:

                 boolean   matchers()               // 用来判断整个输入字符串是否匹配正则表达式模式

                 boolean   lookingAt()              // 用来判断该字符串(不必是整个字符串)的始部分是否

                                                                能够匹配模式

                 boolean   find()

                 boolean   find(int  start)

          @@ 例如:

                 public static void main(String[] args){

                    Matcher   m =  Pattern.compile("\\w+").matcher("Evening is full of the linnet's wings");

                    while(m.find()){

                        printnb(m.group() + "  ") ;

                     }

 

                    print();

                    int i  = 0 ;                    

                     while(m.find(i)){

                        printnb(m.group() + "  ") ;

                         i++;

                     }

                 }

         说明:(1)、\\w+ 将字符串划分为单词。

                   (2)、 find() 就像迭代器一样前向遍历输入字符串。

                   (3)、 find( i ) 接受一个整数作为参数,该整数表示字符串中字符的位置,并以其

                              作为搜索的起点。

                   (4) m.group()  ----》

                            ----- 组是括号划分的正则表达式,可以根据组的编号来引用某个组。组号为 0 表示

                                 整个表达式,组号为 1 表示被第一对括起的组,依次类推。例如:

                                 A ( B ( C ) ) D

                                 里面有三个组:组 0 是 ABCD , 组 1 是 BC , 组 2 是  C

             @@ Matcher 对象提供了一系列方法,用以获取与组相关的信息。

                    ------  public int  groupCount()  返回该匹配器的模式中的分组数目,第 0 组不包括在内。

                    ------  public  String group( ) 返回前一次匹配操作(例如 find( ) )的第 0 组(整个匹配)。

                    ------  public  String group( int i )  返回在前一次匹配操作期间指定的组号,如果匹配成功,

                                                                 但是指定的组没有匹配输入字符串的任何部分,则将会返回

                                                                  null

                   -------  public int start( int group ) 返回在前一次匹配操作中寻找到的组的起始索引

                   -------  public  int end( int group ) 返回在前一次匹配操作中寻找到的组的最后一个字符索引加一

                                                                 的值

             @@ 一定要显式地告知正则表达式注意输入序列中的换行符。这可以由序列开头的模式标记(?m)

                  来完成。

             @@  start() 与 end()

                   ----- 在匹配成功之后,start () 返回先前匹配的起始位置的索引,

                                                  end()  返回所匹配的最后字符的索引加一的值

                   ----- 在匹配失败之后(或先于一个正在进行的匹配操作去尝试),调用 start() 或 end() 将会产生

                         IIIegalStateException 。

             @@ 注意:

                   ----- find() 可以在输入的任意位置定位正则表达式

                   ----  lookingAt() 和 matchers() 只有在正则表达式与输入的最开始处开始匹配时才会成功。

                        《》 matches() 只有在整个输入都匹配正则表达式时才会成功

                        《》 lookingAt() 只要输入的第一部分匹配就会成功

             @@  Pattern 标记(模式标记)

                    -----  Pattern 类的 compile() 方法还有另外一个版本,它接受标记参数,以调整匹配的行为:

                          Pattern  Pattern.compile(String regex , int flag);

                          其中的 flag 来自以下 Pattern 类中的常量(如下)

                    ------

                         

                    说明:(1)、在这些标记中, Pattern.CASE_INSENSITIVE 、 Pattern.MULTILINE

                              以及 Pattern.COMMENTS (对声明或文档有用)特别有用。

                              (2)、你可以直接在正则表达式中使用其中的大多数标记,只需要将上表中括号

                               括起来的字符插入到正则表达式中,你希望它起作用的位置即可。

                              (3)、可以通过 “或 ”(|) 操作符组合多个标记功能。

                @@ group() 方法只返回已匹配的部分。

     ## split()

             @@ split() 方法将输入字符串断开成字符串对象数组,断开边界由下列正则表达式确定:

                    String[]  split(CharSequence  input)

                    String[]  split(CharSequence  input , int  limit)

                   这是一个快速而方便地方法,可以按照通用边界断开输入文本。

              @@ 例如:

                    String input = "This!!unusual use !! of exclamation !! options ";

                   Pattern.compile("!!").split(input);

                   Pattern.compile("!!").split(input , 3 );   // 这个方法可以限制将输入分割成字符串的数量

     ## 替换操作

             @@  正则表达式特别便于替换文本,它提供了许多方法:

             ------ replaceFirst(String  replacement ) 以参数字符串 replacement 替换掉第一个匹配成功的部分

             ------ replaceAll(String replacement ) 以参数字符串 replacement 替换掉所有匹配成功的部分

             -----  appendReplacement( StringBuffer  sbuf , String replacement ) 执行渐进式的替换

                   %% 不是像 replaceFirst() 和 replaceAll() 那样只替换第一个匹配或全部匹配

                   %% 允许你调用其他方法来生成或处理 replacement (replaceFirst() 和 replaceAll() 则只能使

                         用一个固定的字符串),使你能以编程的方式将目标分割成组,从而具备更强大的替换功能。

             -----  appendTail( StringBuffer sbuf ) , 在执行了一次或多次 appendReplacement () 之后,调用此方法

                   可以将输入字符串余下的部分复制到  sbuf 中。

            @@ TextFile 类( 该类在  net.mindview.util 工具包中)

              ------  static  read()  方法读入整个文件,将其内容作为  String 对象 返回。

            @@ replaceFirst() 和 replaceAll() 方法用来替换的只是普通的字符串,所以,如果你想对替换字符串

                  执行某些特殊的处理,这两个方法时无法胜任的。

            @@ 如果想执行某些特殊的处理,可以考虑使用 appendReplacement() 方法,该方法允许你在执行

                   替换的过程中,操作用来替换的字符串

            @@ appendReplacement() 方法允许你通过 $g 直接找到匹配的某个组,这里的 g 就是组号。然而,

                  它只能应付一些简单的处理。

     ## reset()

            @@ 通过 reset() 方法,可以将现有的 Matcher 对象应用于一个新的字符序列

            @@ 例如:

                    Matcher  m = Pattern.compile("[frb][aiu][gx]").matcher("fix the rug with bags") ;

                    m.reset("fix the rig with rags");    // 带参数的

             @@ 使用不带参数的 reset() 方法,可以将 Matcher 对象重新设置到当前字符序列的起始位置。

     ## 正则表达式与 Java I/O

             @@ 之前的内容讲的都是:将正则表达式应用于静态的字符串

             @@还可以将正则表达式应用在一个文件中进行搜索匹配。

》》扫描输入

    @@ 从文件或标准输入读取数据,一般的解决方法是:读入一行文本,对其进行分词。

             @@ 实现(读入一行文本)代码:

                    public  static BufferReader  input = new BufferReader( new StringReader( " ddssddsasfgda") ) ;

                    String name = input.readLine();     // 一次读取一行文本

                    System.out.println(name);

              说明:(1)、BufferReader 类来自 java.io 包

                        (2)、 StringReader 将 String 转化为可读的流对象,然后用这个对象来构造  BufferReader

                        (3)、readLine() 方法将一行输入转为 String 对象。如果每一行数据正好对应一个输入值,那

                                 这个方法也还可行。但是,如果两个输入值在同一行中,事情就不好办了,我们必须分解

                                 这个行,才能分别翻译所需要的输入值。

              @@ Scanner 类

                   ----- Scanner 的构造器可以接受任何类型的输入对象,包括 File  对象 、 InputStream 、String 、

                         Readable 对象 (是一个接口,表示“具有 read() 方法的某种东西 ” ,BufferReader  也归于这

                        类)

                  ------ 有了 Scanner ,所有的输入分词以及翻译的操作都隐藏在不同类型的 next() 方法中

                         %% 普通的 next() 方法返回下一个 String

                         %% 所有的基本类型(除 char 之外)都有对应的 next() 方法,包括 BigDecimal 和  BigInteger

                         %% 所有的 next() 方法,只有在找到一个完整的分词之后才会返回。

                         %% Scanner 还有相应的 hasNext() 方法,用以判断下一个输入分词是否所需的类型

                 ------- 因为,Scanner 有一个假设,在输入结束时会抛出 IOException ,所以 Scanner 会把

                         IOException 吞掉。不过,通过ioException() 方法,你可以找到最近发生的异常,因此,

                         你可以在必要时检查它。

     ## Scanner 定界符

                @@ 在默认情况下, Scanner 根据空白符对输入进行分词

                @@  可以用正则表达式指定自己所需要的定界符:

                         public staitc void main(String[] args){

                                   Scanner scanner = new Scanner("12, 42, 78, 99, 42");

                                   scanner.useDelimiter("\\s*,\\s*")    // 使用逗号(包括逗号前后任意的空白符)作为

                                                                                     定界符

                        }

                  说明:(1)、scanner.useDelimiter("\\s*,\\s*")  除了可以读取字符串,还可以用来读取逗号

                                    分隔的文件。

                            (2)、使用 useDelimiter( )  来设置定界符

                            (3)、 delimiter() 方法,用来返回当前正在作为定界符使用的 Pattern 对象

     ## 用正则表达式扫描

              @@ 除了能扫描基本数据类型之外,还可以使用自定义的正则表达式进行扫描,这在扫描复杂数据

                      的时候非常有用。

              @@ 例如:

                     public static void main(String[] args){

                          Scanner  scanner = new Scanner("sdfdgdssd");

                          String pattern = "\\d+[.]"     // 字符串里面是正则表达式

                          while(scanner.hasNext(pattern)){

                                scanner.next(pattern);

                                MatchResult  match = scanner.match();

                                String ip = match.group(1);

                                String date = match.group(2);

                                System.out.println(date, ip );

                           }

                     }

                   说明:(1)、当 next( ) 方法配合使用指定的正则表达式使用时,将找到下一个匹配该模式

                                    的输入部分

                             (2)、调用 match( ) 方法就可以获得匹配的结果

                             (3)、在配合使用正则表达式使用扫描时,有一点需要注意:它仅仅针对下一个输入

                                   分词进行匹配,如果你的正则表达式中含有定界符,那永远不可能匹配成功。

》》 StringTokenizer

       @@ 在 Java 引入正则表达式Scanner 类之前,分割字符串的唯一方法是使用  StringTokenizer 来

               分词。

》》总结   

       @@ 在对字符串操作的支持,要在细节上注意效率的问题,例如恰当地使用 StringBuilder 等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小达人Fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值