重学JavaSE 第19章 : Java9 ~ 21的新特性

文章目录


关于JDK版本

Java LTS版本目前: Java8, 11, 17, 21等版本

Java9新特性

在这里插入图片描述

jdk目录结构的改变

在这里插入图片描述

bin 目录包含命令行开发和调试工具,如javac,jar和javadoc。
include目录包含在编译本地代码时使用的C/C++头文件
lib 目录包含JDK工具的几个JAR和其他类型的文件。它有一个tools.jar文件,其中包含javac编译器的Java类
jre/bin 目录包含基本命令,如java命令。在Windows平台上,它包含系统的运行时动态链接库(DLL)。
jre/lib 目录包含用户可编辑的配置文件,如.properties和.policy文件。包含几个JAR。rt.jar文件包含运行时的Java类和资源文件。

在这里插入图片描述

没有名为jre的子目录
bin目录包含所有命令。在Windows平台上,它继续包含系统的运行时动态链接库。
conf目录包含用户可编辑的配置文件,例如以前位于jre\lib目录中的.properties和.policy文件
include目录包含要在以前编译本地代码时使用的C/C++头文件。它只存在于JDK中
jmods目录包含JMOD格式的平台模块。创建自定义运行时映像时需要它。它只存在于JDK中
legal目录包含法律声明
lib目录包含非Windows平台上的动态链接本地库。其子目录和文件不应由开发人员直接编辑或使用
  • 新版本jdk的下载与IDEA开发环境的设置

在这里插入图片描述

java9新特性:模块化系统

  • 用模块来管理各个package,通过声明某个package暴露,模块(module)的概念,其实就是package外再裹一层,不声明默认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏。

  • 实现目标

    • 模块化的主要目的在于减少内存的开销
    • 只需必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
    • 改进Java SE 平台,使其可以适应不同大小的计算设备
    • 改进其安全性,可维护性,提高性能
  • 模块将由通常的类和新的模块声明文件(module-info.java)组成。该文件是位于java代码结构的顶层,该模块描述符明确地定义了我们的模块需要什么依赖关系,以及哪些模块被外部使用。在exports子句中未提及的所有包默认情况下将封装在模块中,不能在外部使用。

  • 案例结构

  • Person类

package git;

@Data
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  • module-info.java——JDK9Test中
module JDK9Test {
     exports git;   //exports 包名--》将包暴露使用
}
  • module-info.java——day13中
module day13 {
    requires JDK9Test;  //requires 包名---》接收包
    requires junit;//若要调用JDK9以上版本的测试类,需要引入
    exports github;
}
  • ModuleTest类
import git.Person;

public class ModuleTest {
    public static void main(String[] args) {
        Person p = new Person("Jack",20);
        System.out.println(p);
    }
}

// Person{name='Jack', age=20}

java9新特性:Java的REPL工具:jshell

  • 产生背景

    像Python和Scala之类的语言早就有交互式编程环境REPL(read-evaluate-print-loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。

  • 设计理念

    • 即写即得、快速运行
  • 实现目标

    • Java 9 中终于拥有了REPL工具:jShell。让Java可以像脚本语言一样运行,从控制台启动jShell,利用jShell在没有创建类的情况下直接声明变量,计算表达式,执行语句。即开发时可以在命令行里直接运行Java的代码,而无需创建Java文件,无需跟人解释”public static void main(String[] args)”这句废话。
    • jShell也可以从文件中加载语句或者将语句保存到文件中。
    • jShell也可以是tab键进行自动补全和自动添加分号。

jShell 具体使用, 自行了解

java9新特性:接口中声明私有方法

  • Java8中规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是一个抽象类。
  • 在Java9中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为private的了此时方法将不会成为你对外暴露的API的一部分
public interface MyInterface {

    //如下的三个方法的权限修饰符都是public
    void methodAbstract();

    static void methodStatic(){
        System.out.println("这是接口中的静态方法");
    }

    default void methodDefault(){
        System.out.println("这是接口中的默认方法");
        methodPrivate();
    }

    //jdk 9中允许接口中定义私有的方法
    private void methodPrivate(){
        System.out.println("这是接口中的私有方法");
    }
}

public class MyInterfaceImpl implements MyInterface{

    @Override
    public void methodAbstract() {

    }

    @Override
    public void methodDefault() {
        System.out.println("实现类重写了接口中的默认方法");
    }

    public static void main(String[] args) {
        //接口中的静态方法只能由接口自己调用
        MyInterface.methodStatic();
        
        // 接口的实现类不能调用接口的静态方法
		// MyInterfaceImpl.methodStatic();

        MyInterfaceImpl impl = new MyInterfaceImpl();
        impl.methodDefault();
        
        // 接口的私有方法,不能在接口外部调用
        // impl.methodPrivate();
    }
}

java9新特性:钻石操作符<>的语法升级

  • 我们将能够与匿名实现类共同使用钻石操作符(diamondoperator)在Java8中如下的操作是会报错的
//java9特性5:钻石操作符的升级
@Test
public void test2(){
    //钻石操作符与匿名内部类在java 8中不能共存。在java9可以。
    Comparator<Object> com = new Comparator<>() { // java8中需要写 new Comparator<Object>() {
        @Override
        public int compare(Object o1, Object o2) {
            return 0;
        }
    };

    //jdk7中的新特性:类型推断
    ArrayList<String> list = new ArrayList<>();
}
  • 编译报错信息:Cannotuse“<>”with anonymous inner classes.

java9新特性:try结构的语法升级

import org.junit.Test;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;

public class Java9Test {

    // try操作的升级
    public static void main(String[] args) {
        //java 8之前的资源关闭的操作
//        InputStreamReader reader = null;
//        try {
//            reader = new InputStreamReader(System.in);
//            char[] cbuf = new char[20];
//            int len;
//            if((len = reader.read(cbuf) )!= -1){
//                String str = new String(cbuf,0,len);
//                System.out.println(str);
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            if(reader != null){
//                try {
//                    reader.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }

        //java 8中资源关闭操作: Java 8 中,可以实现资源的自动关闭
        //要求自动关闭的资源的实例化必须放在try的一对小括号中
//        try(InputStreamReader reader = new InputStreamReader(System.in)){
//            char[] cbuf = new char[20];
//            int len;
//            if((len = reader.read(cbuf) )!= -1){
//                String str = new String(cbuf,0,len);
//                System.out.println(str);
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        //java9中资源关闭操作:需要自动关闭的资源的实例化可以放在try的一对小括号外。
        //此时的资源属性是常量,声明为final的,不可修改
        InputStreamReader reader = new InputStreamReader(System.in);
        try (reader) {
            char[] cbuf = new char[20];
            int len;
            if((len = reader.read(cbuf) )!= -1){
                String str = new String(cbuf,0,len);
                System.out.println(str);
            }
//            reader = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

java9新特性:String底层存储结构的变更

  • String再也不用char[]来存储啦,改成了byte[]加上编码标记节约了一些空间

    public final class String
            implements java.io.Serializable, Comparable<String>, CharSequence {
        @Stableprivate 
        final byte[] value;
    }
    
  • 那StringBuffer和StringBuilder呢?

    也改为byte[]数组

java9新特性:集合工厂方法创建只读集合

  • 创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合
    • 构造,分配,添加元素之后, 就不能对该不可变集合进行CRUD操作,
    • 否则抛出异常 java.lang.UnsupportedOperationException
import org.junit.Test;

import java.util.*;

public class Java9Test2 {

    //java9新特性八:集合工厂方法:创建只读集合
    //java8中的写法:
    @Test
    public void test() {
        List<String> namesList = new ArrayList<>();
        namesList.add("Joe");
        namesList.add("Bob");
        namesList.add("Bill");
        //返回的namesList是一个只读的集合
        namesList = Collections.unmodifiableList(namesList);
        namesList.add("Franck"); // 抛出异常

        System.out.println(namesList);
    }

    @Test
    public void  test2(){
        List<String> list = Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
        Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
        // 如下操作不适用于jdk 8 及之前版本,适用于jdk 9
        Map<String, Integer> map = Collections.unmodifiableMap(new HashMap<>() {
            {
                put("a", 1);
                put("b", 2);
                put("c", 3);
            }
        });
        map.forEach((k, v) -> System.out.println(k + ":" + v));
    }

    @Test
    public void test3() {
        //此时得到的集合list也是一个只读集合。
        List<Integer> list = Arrays.asList(1, 7, 9, 3, 2);
        //报异常
        list.add(6);
    }

    @Test
    public void test4() {
        List<Integer> list1 = List.of(1, 2, 3, 4, 5);
        //不能添加
//        list1.add(6);
        System.out.println(list1);

        Set<Integer> set1 = Set.of(23, 3, 54, 65, 43, 76, 87, 34, 46);
        //不能添加
//        set1.add(4);
        System.out.println(set1);

        Map<String, Integer> map1 = Map.of("Josh", 23, "Jack", 54, "Franck", 12);
        //不能添加
        //map1.put("George",34);

        System.out.println(map1);

        Map<String, Integer> map2 = Map.ofEntries(Map.entry("Josh", 34), Map.entry("Jim", 21));
//        map2.put("George",34);
        System.out.println(map2);
    }
}

java9新特性:InputStream中的transferTo()方法

InputStream 终于有了一个非常有用的方法:transferTo,可以用来将数据直接传输到OutputStream,这是在处理原始数据流时非常常见的一种用法,如下示例。

import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Java9Test2 {

    //java9新特性九:InputStream的新方法:tranferTo()
    @Test
    public void test5() {
        ClassLoader cl = this.getClass().getClassLoader();
        try (InputStream is = cl.getResourceAsStream("hello.txt");
             OutputStream os = new FileOutputStream("src\\hello1.txt")) {
            is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

java9新特性:StreamAPI新增的4个方法

  • 在Java 9 中,Stream API 变得更好,Stream 接口中添加了4 个新的方法:takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个Predicate (判断条件)来指定什么时候结束迭代
  • 除了对Stream 本身的扩展,Optional 和Stream 之间的结合也得到了改进。现在可以通过Optional 的新方法stream() 将一个Optional 对象转换为一个(可能是空的) Stream 对象。
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;


public class Java9Test3 {

    //java9新特性十:Stream API的加强
    @Test
    public void test(){
        // takeWhile - 取满足条件的元素直到第一个不满足的元素
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> takeWhileResult = numbers.stream()
            .takeWhile(n -> n < 5)
            .collect(Collectors.toList());
        System.out.println("takeWhile(n < 5): " + takeWhileResult);
        
        // dropWhile - 丢弃满足条件的元素直到第一个不满足的元素
        List<Integer> dropWhileResult = numbers.stream()
            .dropWhile(n -> n < 5)
            .collect(Collectors.toList());
        System.out.println("dropWhile(n < 5): " + dropWhileResult);
		// takeWhile(n < 5): [1, 2, 3, 4]
		// dropWhile(n < 5): [5, 6, 7, 8, 9, 10]
		
    @Test
    public void test2(){
        //of()参数中的多个元素,可以包含null值
        Stream<Integer> stream1 = Stream.of(1, 2, 3,null);
        stream1.forEach(System.out::println); // 1, 2 , 3 , null
        
        //of()参数不能存储单个null值。否则,报空指针异常
//        Stream<Object> stream2 = Stream.of(null);
//        stream2.forEach(System.out::println);

        Integer i = 10;
        i = null;
        //ofNullable():形参变量是可以为null值的单个元素
        Stream<Integer> stream3 = Stream.ofNullable(i);
        long count = stream3.count();
        System.out.println(count); // 0
    }

    @Test
    public void test3(){
		// 从0开始, 无限递增1, 限制limit为10
        Stream.iterate(0,x -> x + 1).limit(10).forEach(System.out::println);

        //java9中新增的重载的方法
		// 从0开始, 每次递增1, 但递增的结果要<100
        Stream.iterate(0,x -> x < 100,x -> x + 1).forEach(System.out::println);
    }
}

java9新特性:Optional的新方法stream()

 //java9新特性十一:Optional提供了新的方法stream()
@Test
public void test4(){
    List<String> list = new ArrayList<>();
    list.add("Tom");
    list.add("Jerry");
    list.add("Tim");

    Optional<List<String>> optional = Optional.ofNullable(list);
    Stream<List<String>> stream = optional.stream();
//        long count = stream.count();
//        System.out.println(count);
    stream.flatMap(x -> x.stream()).forEach(System.out::println);
}

在这里插入图片描述

Java 10 的新特性

java10新特性: 局部变量类型推断

在这里插入图片描述

Java 11 的新特性

java11新特性:String新增的方法

描述举例
判断字符串是否为空白" ".isBlank(); // true
去除首尾空白" Javastack ".strip(); // “Javastack”
去除尾部空格" Javastack “.stripTrailing(); // " Javastack”
去除首部空格" Javastack ".stripLeading(); // "Javastack "
复制字符串“Java”.repeat(3);// “JavaJavaJava”
行数统计“A\nB\nC”.lines().count(); // 3
import org.junit.Test;

public class JDK11Test {
    
    //java 11新特性一:String中新增的方法
    @Test
    public void test(){
//        isBlank():判断字符串是否为空白
        System.out.println("  \t  \t  \n  ".isBlank());
//        strip():去除首尾空白
        System.out.println("++++" + "  \t abc \t  \n  ".strip() + "++++");
        System.out.println("++++" + "  \t abc \t  \n  ".trim() + "++++");
//        stripTrailing():去除尾部空格
        System.out.println("++++" + "  \t abc \t  \n  ".stripTrailing() + "++++");
//        stripLeading():去除首部空格
        System.out.println("++++" + "  \t abc \t  \n  ".stripLeading() + "++++");
//        repeat(int count):复制字符串
        String str1 = "abc";
        String str2 = str1.repeat(5);
        System.out.println(str2);

//        lines().count():行数统计
        String str3 = "abc\nEFG\nH";
        System.out.println(str3.lines().count());
    }
}

java11新特性:Optional新增的方法

Optional也增加了几个非常酷的方法,现在可以很方便的将一个Optional转换成一个Stream,或者当一个空Optional时给它一个替代的。

新增方法描述新增的版本
boolean isEmpty()判断value是否为空JDK 11
ifPresentOrElse(Consumer<? superT>action,RunnableemptyAction)value非空,执行参数1功能;如果value为空,执行参数2功能JDK 9
Optionalor(Supplier<? extendsOptional<? extendsT>>supplier)value非空,返回对应的Optional;value为空,返回形参封装的OptionalJDK 9
Streamstream()value非空,返回仅包含此value的Stream;否则,返回一个空的StreamJDK 9
TorElseThrow()value非空,返回value;否则抛异常NoSuchElementExceptionJDK 10
import org.junit.Test;

import java.util.Optional;


public class JDK11Test {

    //java11新特性二:Optional新增的方法
    @Test
    public void test2(){
        var op = Optional.empty();
        System.out.println(op.isPresent());//判断内部的value是否存在
        System.out.println(op.isEmpty());//判断内部的value是否为空

        op = Optional.of("abc");
        //orElseThrow():value非空,返回value;否则抛异常NoSuchElementException
        var obj = op.orElseThrow();
        System.out.println(obj);

        Optional<String> op1 = Optional.of("hello");
//        op = Optional.empty();
        //or:value非空,返回对应的Optional;value为空,返回形参封装的Optional
        Optional<Object> op2 = op.or(() -> op1);
        System.out.println(op2);
    }
}

java11新特性:局部变量类型推断的升级 (了解)

在var上添加注解的语法格式,在jdk10中是不能实现的。在JDK11中加入了这样的语法。

import org.junit.Test;

import java.util.function.Consumer;

public class JDK11Test {

    //java11新特性三:局部变量类型推断的升级
    @Test
    public void test3(){
        //错误的形式: 必须要有类型, 可以加上var
//        Consumer<String> con1 = (@Deprecated t) -> System.out.println(t.toUpperCase());
        // 正确的形式:
        // 使用var的好处是在使用lambda表达式时给参数加上注解。
        Consumer<String> con2 = (@Deprecated var t) -> System.out.println(t.toUpperCase());
    }
}

java11新特性:HttpClient

  • HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年,HTTP2才成为标准。

在这里插入图片描述

  • HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。HTTP/1.1依赖于请求/响应周期。HTTP/2允许服务器“push”数据:它可以发送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网页至关重要的数据。
  • 这是Java9开始引入的一个处理HTTP请求的的HTTPClientAPI,该API支持同步和异步,而在Java11中已经为正式可用状态,你可以在java.net包中找到这个API。
  • 它将替代仅适用于blocking模式的HttpURLConnection(HttpURLConnection是在HTTP1.0的时代创建的,并使用了协议无关的方法),并提供对WebSocket和HTTP/2的支持。
  • day13——module-info.java类
module day13 {
    requires JDK9Test;  //requires 包名---》接收包
    requires junit;//若要调用JDK9以上版本的测试类,需要引入
    exports github;
    exports github2;
    exports github3;
    requires java.net.http;
}
  • 测试类
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

public class JDK11Test {

    //java11新特性四:HttpClient替换原有的HttpURLConnection。
    @Test
    public void test4(){
        try {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
            HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
            HttpResponse<String> response = client.send(request, responseBodyHandler);
            String body = response.body();
            System.out.println(body);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test5(){
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
        HttpResponse.BodyHandler<String> responseBodyHandler = HttpResponse.BodyHandlers.ofString();
        CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, responseBodyHandler);
        sendAsync.thenApply(t -> t.body()).thenAccept(System.out::println);
        //HttpResponse<String> response = sendAsync.get();
        //String body = response.body();
        //System.out.println(body);
    }
}

java11新特性:简化编译运行程序 Java命令

看下面的代码。
    //编译
    javac Javastack.java
    //运行
    java Javastack

在我们的认知里面,要运行一个Java源代码必须先编译,再运行,两步执行动作。而在未来的Java11版本中,通过一个java命令就直接搞定了,如以下所示:

java test.java文件即可, 包含了之前的javac, java命令

一个命令编译运行源代码的注意点:

  • 执行源文件中的第一个类, 第一个类必须包含主方法。
  • 并且不可以使用其它源文件中的自定义类, 本文件中的自定义类是可以使用的。

Java语言高级-java11新特性:其它新特性

ZGC (垃圾回收器)

  • GC是java主要优势之一。然而,当GC停顿太长,就会开始影响应用的响应时间。消除或者减少GC停顿时长,java将对更广泛的应用场景是一个更有吸引力的平台。此外,现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存,并且无需长时间的GC暂停时间。
  • ZGC,AScalableLow-LatencyGarbageCollector(Experimental) ZGC,这应该是JDK11最为瞩目的特性,没有之一。但是后面带了Experimental,说明这还不建议用到生产环境。
  • ZGC是一个并发,基于region,压缩型的垃圾收集器,只有root扫描阶段会STW(stoptheworld),因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。
  • 优势:
    • GC暂停时间不会超过10ms
    • 既能处理几百兆的小堆,也能处理几个T的大堆(OMG)
    • 和G1相比,应用吞吐能力不会下降超过15%
    • 为未来的GC功能和利用colord指针以及Loadbarriers优化奠定基础
    • 初始只支持64位系统
  • ZGC的设计目标是:支持TB级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于15%。将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存),或压缩堆。

其他的新特性

  • Unicode 10
  • Deprecate the Pack200 Tools and API
  • 新的Epsilon垃圾收集器
  • 完全支持Linux容器(包括Docker)
  • 支持G1上的并行完全垃圾收集
  • 最新的HTTPS安全协议TLS 1.3
  • Java Flight Recorder

Java 12 的新特性

java12的新特性: 升级的switch语句

在这里插入图片描述

Java 13 的新特性

java13的新特性: 升级的switch语句 (可作为返回值)

在这里插入图片描述

在这里插入图片描述

java13的新特性: 文本块的变化

在这里插入图片描述

Java 14 的新特性

java14的新特性: instanceof模式匹配

在这里插入图片描述

java14的新特性: 友好的空指针(NullPointerException)提示

在这里插入图片描述

java14的新特性: 文本块增加新功能

在这里插入图片描述

java14的新特性: Record (鸡肋,没有Lombok强大)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Java 15 的新特性

java15新特性: Sealed Classes 密封类

在这里插入图片描述

Java 17 的新特性

java17新特性: switch语法变化 (支持instanceof模式匹配)

在这里插入图片描述

Java 19 的新特性

java 19的新特性: 虚拟线程

Java线程之虚拟线程VirtualThread

Java 21 的新特性

java 21的新特性: 虚拟线程正式版本

Java线程之虚拟线程VirtualThread

java 21的新特性: Java线程之作用域值ScopedValue

Java线程之作用域值ScopedValue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

white camel

感谢支持~

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

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

打赏作者

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

抵扣说明:

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

余额充值