【Java】积累

安装

官方jdk8
adoptOpenjdk

手动编译运行

javac 编译多文件
运行jar包时读取jar里面的文件
MANIFEST.MF文件详解

Java SE

on java 8

可见性

关键字protected指明:
就类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何位于同一个包内的类来说,它确是可以访问的.
非常精辟的一句话,对于使用这个类的地方,这个类里protected修饰的东西是不可见的;但是对于子类或者同包内的地方,这个protected是可见的。

面向对象

Java如何对一个对象进行深拷贝?
clone方法对于基本数据类型的拷贝是深拷贝,对于引用变量则是浅拷贝。

User copyUser = user.clone();
//对copyUser的基本数据类型的更改不会影响user
//未经处理的情况下,copyUser中引用变量和user的对应引用变量指向的是相同的对象

文档中说 If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified. 意思对于基本数据类型和不变的引用对象,对于clone返回的对象就不用手动进行调整。因为基本数据类型是深拷贝。


Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序

Java避免创建不必要的对象

继承

在继承中重写方法时抛出异常的问题
Java中为什么子类重写父类方法时抛出的异常不能大于父类异常

  • 子类重写父类方法要抛出与父类一致的异常,或者不抛出异常
  • 子类重写父类方法所抛出的异常不能超过父类的范畴

泛型继承的几种写法
JAVA继承中的构造函数
【Java杂烩】在继承关系下构造函数执行时的顺序
就是说子类构造方法执行的时候,会先执行父类的构造方法;如果没有手动告诉子类需要执行的父类构造方法,那么默认执行的是父类的无参构造方法。所以,从这个角度看,构造方法并不能继承。

泛型

java - 遍历Long的列表会导致java.lang.ClassCastException

List raw = new ArrayList();
raw.add ("some string");
YourFormClass form = new YourFormClass ();
form.setIdProviders (raw);
...
List<Long> idProviders = form.getIdProviders();
for(Long idProvider: idProviders) { // here an attempt is made to cast a String 
                                    // to a Long leading to ClassCastException
    ....
}

Java泛型 自限定类型(Self-Bound Types)详解
在onjava8里对应古怪的泛型这一章节;这个博客总结的也很好,自限定泛型,就是将泛型类里本身的泛型类型限定为本身。就像enum里一样,将每个成员变量的类型限定为自己本身;

反射

java的动态代理机制详解(内容有瑕疵,23楼指正)
InvocationHandler中invoke方法中的第一个参数proxy的用途
【Java】动态代理实例讲解
Java反射调用静态方法
反射中Class.forName()和ClassLoader.loadClass()的区别
java获取泛型信息
Class的getInterfaces与getGenericInterface区别
Java中Type接口与Class类的区别联系
Java获取类或接口上的泛型类型T方法

深入分析 Java 方法反射的实现原理

迭代

Java迭代 : Iterator和Iterable接口
Iterator、Iterable接口的使用及详解

简单说,如果当前一个A对象维护了一个B数组,那么A类如果要实现迭代,其要实现Iterator<B>接口,next方法返回的是一个B类对象,或者实现Iterable<B>接口,iterator方法返回的也应该是一个Iterator<B>对象

引用

理解Java的强引用、软引用、弱引用和虚引用
深入理解Java弱引用
弱引用就是如果没有强引用,gc的时候就要将弱引用也要回收掉 ;例如a=new WeakReference[String](s),那么这个a代表着s的弱引用,当s不存在强引用指向它的时候,gc的时候就会将这个s回收掉(就是说此时打印s会得到null)。但注意,回收的是s而不是a,因为a本身实际上是一个强引用,是一个WeakReference类的强引用。

并发

JAVA多线程安全之构造函数

volatile

Java并发编程:volatile关键字解析
volatile不能保证原子性,是因为++操作势必会用到计算,用到寄存器,当cpu从数据读取进寄存器后,那么其他线程对这个数据的操作就不会通知到了。
volatile 的用法及原理

管程与cas

漫画:什么是 CAS 机制?
java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)
Difference between WAIT and BLOCKED thread states
Java并发包源码学习系列:详解Condition条件队列、signal和await

乐观与悲观
使用wait和notify
Thread之三:Thread Join()的用法

你竟然用Integer作为synchronized的锁对象?

java 中的锁 – 偏向锁、轻量级锁、自旋锁、重量级锁
轻量级锁的获取过程的第5步,需要再次判断对象的Mark Word是否指向当前线程的栈帧,猜测这可能是由于synchronized的可重入属性。所以需要重新判断一下;
Java6及以上版本对synchronized的优化
可偏向但未偏向的状态 指的应该是目前锁状态是偏向的,即最后三位为101,但线程id里填写的是0,说明此时可以偏向,但是没有偏向;
偏向锁,轻量级锁与重量级锁的区别与膨胀
重量级锁的加锁和解锁都与底层内核有关,java为了减少这种操作,设计出了轻量级锁与偏向锁,这两种锁都可以减少对于底层操作系统的依赖。
偏向锁无法主动释放,锁状态一直是那个可偏向的状态,并且mark word里记录着偏向的线程id,只能等有竞争情况发生的时候,如果存的线程id挂了,可以重新偏向,否则stop the world升级轻量级锁;
轻量级锁是用来解决竞争不那么激烈(文中说是线程数小于3)的情况,获取轻量级锁的过程就是拷贝mark word到线程的栈上,并cas对象的mark word;如果线程A拿着轻量级锁,那么线程B尝试获取锁的时候,去检查锁的mark word发现是轻量级锁,那么下一步就是判断线程A和线程B是不是同一个线程(通过读取栈帧)如果相同,如果相同说明是重入,放行;如果发现是不是同一个线程,那么线程B会自旋等待锁;如果这时候又来了一个新的线程,这就会导致轻量级锁升级为重量级锁(毕竟总不能全部竞争线程都在那自旋着吧);

轻量级锁加锁时候的cas,我猜测是这样,一定是事先读取了mark word,然后发现是轻量级锁,然后创建lock record最后尝试修改当前的object mark word,而这个修改操作就涉及了cas;轻量级锁解锁的时候的cas mark word记录的地址的内容和displaced mark word是否一致,如果一致就回写回锁的word mark释放锁;如果不一致则说明锁升级了、释放锁之后还得做唤醒操作;

java偏向锁,轻量级锁与重量级锁为什么会相互膨胀? - 知乎用户的回答 - 知乎
偏向锁:只有一个线程会访问这段代码;可以避免内核态和用户态切换;
轻量级锁:不同的线程会交替访问这些代码;最多允许两个线程同时访问,未获得锁的线程先自旋;可以避免内核态和用户态切换;
重量级锁:竞争激烈,没办法了,无法避免内核态和用户态切换;

What’s a monitor in Java?
synchronized关键字的实现方式,可以通过javap反编译看出,实际上是在同步代码前后记上monitorentermonitorexit,所以说其依赖了监视器来实现锁;而这个监视器,就是之前看到的通过竞争队列、entry队列、owner、等待集合这种管程模型来实现的。

Thread

守护线程setDaemon详解
ThreadLocal是什么
死磕Java源码之ThreadLocal实现分析
ThreadLocal弱引用与内存泄漏分析

每一个thread都持有了一个ThreadLocalMap,因此当Thread被清楚了,这个map也会被回收掉;而这个map里存了一堆entry,这个entry是一个WeakReference<TheadLocal>,因此如果ThreadLocal没有强引用了,而又由于弱引用,这个map的存在也不会干扰ThreadLocal的回收;但是这个entry对于value变量并不是弱引用,是强引用,这可能引起内存泄露。

ThreadLocal的设计优点在哪
方案1:将map存于ThreadLocal里,Thread做key
方案2:将map存于Thread里,ThreadLocal做key

方案2的优势:thread天然封闭,线程独享,无安全问题,效率高;
方案1的弊端:对threadlocal的使用往往就是起个线程干活,拿来threadLocal用用,用完就扔了,如果线程ABC里的AB已经结束工作了,但由于线程C还在干活,那么A和B就还得存在于map里,而总不能说把线程AB记为弱引用吧,我们都用线程池,即使标记了弱引用,也没法回收,map里的还是会有这么一对kv对。(当然,方案1也有这个弊端,threadlocal被gc干掉了,但是其对应的value还存在着,为了弥补这个弊端,threadlocal本身有失效key的清理的功能,用方案1的话,即不能设置弱引用,判断thread是否被使用中有很困难,何必这么搞呢。)
Thread.interrupt()到底做了啥?
面试官:都说阻塞 I/O 模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?

容器

CopyOnWriteArrayList 使用入门及源码详解
反面教材-先简单说一说Java中的CopyOnWriteArrayList
上面博客是一个反面教材,因为即使将ArrayList换成了CopyOnWriteArrayList的时候,看起来可能是不报错了,但是在并发里,不报错不一定代表着正确;代码之中,先启动了10个线程去遍历list,但是这10个线程使用的却是同一个迭代器,那么就有可能发生,某两个迭代器都走到了最后一个元素,然后都认为列表还有一个元素,于是都调用了next方法,那么如果有一个线程先调用了next,那么另一个线程调用next方法就会报错;在sout之前sleep一下就可以简单的看出错误;
这段代码里,使用copyOnWriteArrayList的思路是没错的,每次生成的迭代器都是list的一份拷贝的迭代器。

对比源码分析 ConcurrentHashMap 是如何成为一个线程安全的 HashMap
ConcurrentHashMap - 常用的get与put方法
concurrenthashmap 源码分析(二) - initTable() 方法
ConcurrentHashMap1.8 - 扩容详解
图解 ConCurrentHashMap ——从源码层面,弄清楚它是怎么控制并发的

ArrayBlockingQueue和LinkedBlockingQueue的区别

Executor

Java - ExecutorService shutdown系列方法 的理解
Java多线程(十四) Java8 newWorkStealingPool 线程池
ExecutorService – Waiting for Threads to Finish
shutdown and awaitTermination which first call have any difference?
意思就是说shutdown是立即返回的,而awaitTermination会阻塞当前线程,注意,这个方法的注释里写了,实在shutdown调用之后执行awaitTermination才有效;

ExecutorService 的理解与使用
一文秒懂 Java ExecutorService

Future

从阿里不推荐使用Executors到CompletableFuture的使用

What is the difference between thenApply and thenApplyAsync of Java CompletableFuture?
回答1和回答2都很好
CompletableFuture | thenApply vs thenCompose
thenCompose的function返回了一个CompletableStage,并且compose会将这个stage的结果作为持有的对象继续往下传递。有点类似于flatMap,flatMap就是方法返回一个array,然后flatMap将array里的数据拆开作为结果往后传递。

关于Future.cancel(false)

Java CompletableFuture 详解
Future和CompletableFuture的区别
Java8的CompletableFuture进阶之道

fork/join

Java的Fork/Join任务,你写对了吗?
看了invokeAll的源码,发现如果传入了10个task,那么会对后面9个执行fork,而对第一个task执行doInvoke,而doInvoke实际上做的就是执行compute,只不过除了compute,还会将运行状态标志位设置为成功,从而对这个task调用join也能返回结果;

序列化

Java将对象保存到文件中/从文件中读取对象

断言

【Java】断言 assert

枚举

深入理解Java枚举类型(enum)
简单理解的话,就把枚举看做一个带有常量的普通类就好了;所有枚举类型都是Enum的子类

注解

Java的自定义注解及通过反射获取注解

函数式编程

方法的lambda表达式中的this是外部对象,匿名对象里的this指的是这个匿名对象

public class Demo {
    public void consume(MyInterface myInterface) {
        myInterface.abstractShow();
    }
    void run() {
        int i = 10;
        this.consume(new MyInterface() {
            @Override
            public void abstractShow() {
                System.out.println("this is an anonymous object ");
                System.out.println(this);
            }
        });
        this.consume(() -> {
            System.out.println("this is an Demo object");
            System.out.println(this);
        });
    }
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.run();
    }
}

How do I convert a Java 8 IntStream to a List?

容器

迭代器

Java8中Spliterator详解
java 8 stream中的Spliterator简介
谈谈fail-fast与fail-safe是什么以及工作机制

hashMap

HashMap源码注解 之 静态工具方法hash()、tableSizeFor()(四)
HashMap中的hash函数
Java8 HashMap之tableSizeFor
HashMap源码解读——逐句分析resize方法的实现
Java用自定义的类作为HashMap的key值
hash指定的是存储位置,第二步equals决定的是到底是不是同一个key,如果hash相同,equals不同,那就会hash冲突,解决的方法就类似于拉链法,同一个hash地址里存一个链表,然后每次来一个key,如果打到了这个hash上,就会在链表上循环,直到找到equals的key(或者未找到就新加一个)

IO

文件

Java IO流详解(三)——RandomAccessFile

Java中InputStream和String之间的转换方法

NIO从入门到踹门

网络

使用NetworkInterface解决InetAddress.getLocalHost().getHostAddress()获取ip为127.0.0.1问题
Java中通过NetworkInterface获取主机地址和物理地址等

getResource

getResource和getResourceAsStream
Java中getResourceAsStream的用法

其他

java 复合赋值运算顺序非纯粹的从右到左

时间

关于时间,日期,星期,月份的算法(Java中Calendar的使用方法)
DecimalFormat使用心得
Java计算时间差、日期差总结
多线程状态下调用SimpleDateFormat.format()抛出 ArrayIndexOutOfBoundsException 异常
java节点流和处理流的区别

unsafe

说说Java的Unsafe类

Java 8特性 - Collectors toMap

Java高级

JavaBean

java中javaBean与Bean的深入理解
【Java基础】属性编辑器PropertyEditor
spring容器的DI功能核心之一

IO

Java阻塞IO与非阻塞IO
java NIO(三)之阻塞与非阻塞
NIO编程(同步阻塞与同步非阻塞详解)
如何学习Java的NIO?
评论区精选:
即便是noblocking了,服务端还是需要通过while循环不断从selector中判断其中是否有已经满足事件要求的通道。调用while()的主函数(例子中就是main函数了)依旧会被一直阻塞着,吃着cpu资源。从现有的方式看起来,selector只是起到监听多路io的作用(在我看来只是换了种模式),但从提升性能的角度看,貌似并没有啥优点。不知道我这样理解是否有问题?

性能提升大了去了. 在一次请求处理中: recv接受客户端请求数据->handle业务逻辑->send响应数据的生命周期里, 可能阻塞的地方–也就是线程利用不充分的地方是 recv 和 send . I/O多路复用其实是将I/O 操作从业务线程中抽取出来, 业务线程可以专职做业务逻辑. I/O 操作让一个或指定个数的线程去处理就好了.
其实理解更进一步的是(参考一些资料): 发送kernel buffer给对端,从对端读取数据到 kernel buffer, 都是网络设备在做的事情. 简单理解内核只要有几个固定线程循环检测指定的 fd 是否ready 就好了.
而阻塞的确也是阻塞,但是不阻塞业务线程, 几百个业务线程可以服务成千上万个 socket, 这是决定系统伸缩性的地方.

简单理解一下:原本的阻塞IO在一次请求处理之中,整个流程是阻塞的,send响应数据不完成,这个handle业务逻辑的不会被释放掉去做其他的任务只能等待;

而这种多路复用IO是业务处理完了把数据交给用于IO的线程,然后这个业务线程可以去做其他的任务了不必等待,数据的IO只是被少量的IO线程控制。

Java NIO1:浅谈I/O模型
上面几个博客里的实例代码都差不多,我看了很久才稍微能看懂一点点
传统的阻塞IO:假如现在有两个客户端连接服务器,服务器为每个连接创建一个线程用于读取数据,该线程是阻塞的,没数据的话就会一直等待,
java的NIO使用的是多路复用IO,即不需要像阻塞IO那样,他只构建几个用于IO的线程;例如有两个客户端需要读取数据,通过利用选择器接受客户端的请求,然后使用数量不多的IO线程进行读取;

Java NIO(4): 阻塞与非阻塞
Java 实现 HTTP 请求的三种方式

EJB

EJB到底是什么,真的那么神秘吗??

debug

调试的小知识:单步执行命令stepinto/stepout/stepover的区别

JNDI

JNDI的原理和应用
JNDI基础
hat is JNDI? What is its basic use? When is it used?

SPI

Difference between SPI and API?
以回答为例,Driver类就是spi,然后mysql厂商根据标准实现了这个spi,像是插件一样应用着这个spi;而connection是spi也是api,因为厂商实现了connection,并且也直接提供给使用者使用了。
jndi+SPI和API
Java常用机制 - SPI机制详解

数据库

建立链接

jdbc连接mysq之serverTimezone设定
5.x版本的jdbc连接mysql用法
8.x版本的jdbc连接mysql注意事项
JDBC8.011连接数据库 3个小改动
Java操作数据库方式(六)DataSource详解
DataSource数据源简单理解
JDBC学习2:为什么要写Class.forName(“XXX”)?

常用api

PreparedStatement执行sql的主要方式有:1.execute:可以执行任何sql;2.executeQuery:不能执行DML语言(如insert和update);3.executeUpdate:只能执行DML或者DDL语言
mysql的jdbc中fetchsize支持的问题
JDBC 读取大量数据时的 ResultSet resultSetType 设置TYPE_FORWARD_ONLY
ResultSet 的Type属性 TYPE_FORWARD_ONLY, TYPE_SCROLL_I
jdbc ResultSetType 说明


执行完update方法后,希望获取主键值,可以使用getGeneratedKeys方法,但是需要You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate(), Statement.executeLargeUpdate() or Connection.prepareStatement(),如下

PreparedStatement s=c.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
s.executeUpdate();
ResultSet rs = s.getGeneratedKeys();

CallableStatement的用法

JVM

编译

深入理解Java即时编译器(JIT)-上篇 - Mr羽墨青衫的文章 - 知乎

内存

Java堆和栈看这篇就够
从i++, ++i理解局部变量表和操作数栈
Java中堆内存(heap)和栈内存(stack)的区别

Java8内存模型—永久代(PermGen)和元空间(Metaspace)
java8以后字符串常量池的位置,以及元空间的探秘,使用VisualVM进行实战验证
JVM内存分配担保机制
Java 中方法区与常量池
JVM知识梳理之二_JVM的常量池

垃圾回收

三色标记原理,我给应聘者问懵了…
JVM GC:OopMap、CardTable、RememberedSet
困扰了你大半辈子的STW,今天总算可以毕业了
Java虚拟机如何快速找到GC Roots?又是如何中断线程?
写得挺好的,就比如一个对象或者一个栈里,有一块数据是32位的,我们不知道他是个整数,还是一个引用,OopMap就是用来记录这个的。因为当GC的时候,需要知道谁是引用,GC只会关注引用。
而OopMap可能会变,可能增加可能减少,例如方法调用完毕,从栈里弹出方法,那么这个方法参数、局部变量就不在栈里了,那么OopMap自然也要跟着改变。

CMS并发清理阶段为什么是安全的
GC日志查看和分析
什么时候触发GC
【证】:那些可作为GC Roots的对象
JVM(十二)记忆集和卡表

JVM基础(十):吞吐量和延迟
吞吐量:一段时间内,能同时处理多少事情;
延迟:处理一件事情要多久。
在jvm的场景里,两者是相反的,一次完美的gc如果需要10秒,那么如果将其拆分成5次gc,那么总耗时可能大大超过10秒
因为高吞吐代表着一段时间内,更多的时间要处理就必然需要每次gc做的尽可能完善,才能保证gc的次数少一些,但反之,由于gc做的尽可能完善,这会导致每次gc的延迟会提升;而如果要求延迟低,那么就得要求每次gc做的尽量快一些,但这就会导致每次gc做的不够完善,这会导致gc的次数变多,从而降低了吞吐量;

类加载

JVM学习笔记(七)类加载机制-类加载的时机、过程
被动引用例子三里说编译器常量不会触发类初始化,这个说的不全面,static final String a="312";不会初始化类,但static final String a=new String("312");就会,个人猜测是新建了引用类型对象,需要初始化这个类才能新建
实例详解 JVM 类加载机制
两道面试题,带你解析Java类加载机制

接口初始化规则

方法执行

Java静态绑定与动态绑定
java字节码里方法调用包括invokestatic invokespecial 这是静态调用,也就是说编译的时候就知道是哪个类方法,而invokeinterface和invokevirtual,就得等到执行的时候,根据对象的方法表,具体确定是由谁来执行
Java 桥接方法(Bridge Method)

jvm如何实现反射
Java反射优化之方法句柄
反射的本地实现里,作用的流程是调用java方法->调用navtive的c++方法->像java一样调用方法去invokexxxx方式执行方法,而方法句柄直接指向的是该方法执行的那一块字节码,不关注java是怎么调用的,就楞执行,更加底层;

Invokedynamic 和 MethodHandle的缘由
invokedynamic的出现是为了希望java能够一定程度上支持动态类型语言的特性,即不管输入的类型是个啥,我就调用这个对象的xxx方法,就好了;就比如赛马比赛里,不用关心输入的是不是马,只要能跑,我就让他开始跑就行而不去关心他是不是马。

参数

JVM(Java虚拟机)参数优化大全和案例实战
Java GC日志查看与分析

并发

JVM工具

JHSDB

JVM 如何使用jhsdb 调试 (Mac环境 JDK1.8 )
解读HSDB
《深入理解Java虚拟机》:JVM高级特性与最佳实践(第3 版)4.3.1 JHSDB:基于服务性代理的调试工具 (笔记随录) 搜索对象
liuzhengyang/hsdis

Jave Web

域对象

三大域对象详情解析
JAVA四大域对象总结
ServletContext介绍及用法

配置

一个web项目web.xml的配置中<context-param>配置作用

Java配置

windows 中 到底是用的哪个java.exe??? 删除了PATH变量的Java设置还是可以运行java.exe windows/system32

IDE相关

idea

idea打包java可执行jar包

extract就是把依赖包打入一个jar里 copy to output directory…就是把依赖包拆出来分别作为单独的jar放在输出路径里

JavaDoc生成API详解
javadoc注释规范

Intellij IDEA 添加jar包的三种方式

说白了,推荐把要导入的jar放在一个文件夹里,然后再project structure里的global libray或者library里添加一个专门的库,这个库添加的时候如果选中的是文件夹,那就把这个文件夹里的所有jar都添加进来,不包括子文件夹里的,如果只是想添加部分的,那就选中几个jar包就可以了
这样方便依赖库的管理,如果是以文件夹的形式添加的,那当新添加jar的时候,只需要把新的jar丢进文件夹里就可以了

【IntelliJ IDEA】设置自动导入Maven依赖
IntelliJ IDEA 编译后的class文件路径在哪?
解决 Intellij IDEA Cannot Resolve Symbol ‘XXX’ 问题的四板斧
IDEA类和方法注释模板设置(非常详细)
idea 方法注释模板自定义并多个参数换行
IDEA优化配置(6)— 炫酷的主题字体颜色设置(基于Intellij IDEA 2018)
Color Themes
idea主题
Intellij IDEA中file size exceeds configured limit解决
IDEA代码以及注释格式化,行宽设置,以及自动换行
有时候会影响xml文件也自动换行,记得在codeStyle里把wrap text给取消掉
gradle+idea 快速上手
Idea工具类文件大小限制导致无法解释该类问题

debug

java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
使用idea的异常时捕获然后打断点的功能

eclipse

eclipse中设置JVM内存
eclipse的配置详解和代码的格式详解Ctrl+Shift+F格式化内容设置

Eclipse中如何快速查看jar包中的class源码
最常用的15大Eclipse开发快捷键技巧

工具

java反编译器
Mac Big Sur 升级后 JD-GUI 无法打开的问题修复

jstack

Java程序员必备:jstack命令解析
java命令–jstack 工具
jstack线程分析

并发(九):检查死锁与Locked ownable synchronizers
Java线程栈中的锁信息

编译运行

javac source and target options

介绍Java -D 命令行参数

示例

自己用Java编写的连接池
entity、bo、vo、po、dto、pojo如何理解和区分

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值