怎么往integer型数组添加数据_你可能没那么了解Integer

简介

Integer?

Integer 是数据类型之一 Integer 一个整型数据用来存储整数,整数包括正整数,负整数和零。

Integer与int的区别?

Integer:基础类型int的包装类,缺省值为null,必须实例化后才能使用 int: java基础类型,缺省值为0,可直接使用

类UML图

96260cad3a3bf09eabc7bb7f8260498b.png
//类声明
public final class Integer extends Number implements Comparable 

从代码实现和UML图分析

  1. 类由final标示,不可被其他类继承
  2. 继承 Number 抽象类用于实现 intValue...等基础类型转换方法
  3. Number抽象类 实现了 Serializable 接口,所以Integer可被序列化
  4. 实现 Comparable 接口实现 compareTo 方法实现数值比较

解析

Integer类脑图

fa199b9e6f447037e193a1f31f54475e.png

如图,在分析Integer类我把该类分成若干个部分

  1. 变量部分:按性质细分为静态变量成员变量
  2. 方法部分:按功能细分为构造方法,基础运算方法,位运算方法,类型转换方法,以及其他未归类的普通方法.
  3. 内部类部分:integerCache缓存类

静态变量以及成员变量

    //成员变量(基本类型int的值)
    private final int value;
    //min_value ->-2147483647 -2的31次方
    @Native public static final int   MIN_VALUE = 0x80000000;
    //max_value ->2147483647 2的31次方
    @Native public static final int   MAX_VALUE = 0x7fffffff;
    //声明Integer类的原始类型为int
    public static final Class  TYPE = (Class)     Class.getPrimitiveClass("int");
    //用来表示二进制补码形式的int值的字节数,值为SIZE除于Byte.SIZE,结果为4
    public static final int BYTES = SIZE / Byte.SIZE;
    //方便取出int型数字对应字符串的长度
    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };
    //数字字母表,表示integer所有可能的数字,因为是多进制,所以含有字母
    final static char[] digits = {'0' , '1' , '2' , '3' , '4' , '5' ,'6' , '7' , '8' , '9' , 'a' , 'b' ,'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,'o' , 'p' , 'q' , 'r' , 's' , 't' ,'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };
    //方便取出0-99的数个位和十位的值,如39 DigitTens[39]=3,DigitOnes[39]=9
    final static char [] DigitTens = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0','1', '1', '1', '1', '1', '1', '1', '1', '1', '1','2', '2', '2', '2', '2', '2', '2', '2', '2', '2','3', '3', '3', '3', '3', '3', '3', '3', '3', '3','4', '4', '4', '4', '4', '4', '4', '4', '4', '4','5', '5', '5', '5', '5', '5', '5', '5', '5', '5','6', '6', '6', '6', '6', '6', '6', '6', '6', '6','7', '7', '7', '7', '7', '7', '7', '7', '7', '7','8', '8', '8', '8', '8', '8', '8', '8', '8', '8','9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
        } ;
    final static char [] DigitOnes = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        } ;
    //序列化序号
    @Native private static final long serialVersionUID = 1360826667806852920L;

方法

构造方法

定义:传入基本类型intString构造Integer对象

    //构造方法,初始化value为传入的值
    public Integer(int value) {
        this.value = value;
    }
    //构造方法,传入一个字符串类型的值,失败会抛出数值转换异常
    public Integer(String s) throws NumberFormatException {
        //值先转成int
        this.value = parseInt(s, 10);
    }
valueOf

定义:类型转换为Integer包装类

    //当取值为-127->128时,会取缓存里的数据
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    //传入String类型数值返回Integer的包装对象,失败返回数值转换异常
    public static Integer valueOf(String s) throws NumberFormatException {
        //转化为十进制的int值后传入valueOf(int i)
        return Integer.valueOf(parseInt(s, 10));
    }
    //传入String类型数值返回Integer的包装对象,radix值定义转换的Integer的进制数字,失败返回数值转换异常
    public static Integer valueOf(String s, int radix) throws NumberFormatException {
        return Integer.valueOf(parseInt(s,radix));
    }
toString系列

定义:转换成对应格式的String类型返回

    //返回String类型,非静态方法.内部直接调用toString(int i),i为成员变量value,返回String字符串
    public String toString() {
        return toString(value);
    }

    //如果是int的最小值,直接返回,防止在getChars方法中溢出.其他int值,计算出数字位数,调用getChars方法得到char[],最后通过String的构造方法返回String类型对象.
    public static String toString(int i) {
        //特殊处理,因为int的最小值会溢出
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        //获取这个数字的位数,如果是负数,取反去掉符号,然后位数加一
        int size = (i         char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }
    
    //转换为radix进制的字符串
    public static String toString(int i, int radix) {
        //如果输入的radix进制不是有效进制,默认十进制
        if (radix  Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        //如果是十进制,直接调用一个参数的toString
        if (radix == 10) {
            return toString(i);
        }

        //int型为32位,加上符号位,最长可以为33位,故先创建一个33位的char数组
        char buf[] = new char[33];
        boolean negative = (i         int charPos = 32;

        //判断是否是负数,如果不是则转为负数
        if (!negative) {
            i = -i;
        }

        //int型的最大值为2147483647,最小值为 -2147483648;
        //如果将负数转为正数,最小值在转时会溢出,故使用负数来进行运行
        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];

        if (negative) {
            buf[--charPos] = '-';
        }

        //根据buf数组、数组有效值位置charPos以及有效长度33-charPos创建一个string对象
        return new String(buf, charPos, (33 - charPos));
    }
    
    //转为对应的进制字符串,内部调用toUnsignedString0方法
    //转为二进制字符串
    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }
    //转为八进制字符串
    public static String toOctalString(int i) {
        return toUnsignedString0(i, 3);
    }
    //转为十六进制字符串
    public static String toHexString(int i) {
        return toUnsignedString0(i, 4);
    }
    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf, true);
    }
getInteger

定义:经常会被错误用做是获取Integer对象值.他的正确用法是获取系统变量转换为Integer.

    //获取变量名为nm的系统变量,值转为Integer
    public static Integer getInteger(String nm) {
        return getInteger(nm, null);
    }
    //获取变量名为nm的系统变量,值转为Integer,val为默认值
    public static Integer getInteger(String nm, int val) {
        Integer result = getInteger(nm, null);
        return (result == null) ? Integer.valueOf(val) : result;
    }
    //获取变量名为nm的系统变量,值转为Integer,val为默认值
    public static Integer getInteger(String nm, Integer val) {
        String v = null;
        try {
            v = System.getProperty(nm);
        } catch (IllegalArgumentException | NullPointerException e) {
        }
        if (v != null) {
            try {
                return Integer.decode(v);
            } catch (NumberFormatException e) {
            }
        }
        return val;
    }
    
parseInt

定义:将字符串参数解析为有符号的基本类型int

    //默认转换为int类型,转换基数为10(进制)
    public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }
    
    //转换为int的构造方法,radix表示基数
    public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        //为空直接抛出数值转换异常
        if (s == null) {
            throw new NumberFormatException("null");
        }
        //判断进制在2-36之间,保证是合理的进制值
        if (radix             throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }
        //最终输出值
        int result = 0;
        //是否为负数
        boolean negative = false;
        int i = 0, len = s.length();
        //临界值
        int limit = -Integer.MAX_VALUE;
        //溢出阈值
        int multmin;
        //需要追加的数值
        int digit;
        if (len > 0) {
            char firstChar = s.charAt(0);
            //先判断转换的字符串是否有正负符号
            if (firstChar '0') { // Possible leading "+" or "-"
                //开头的字母是特殊字符,如果不是正负操作符就直接抛出转换异常
                if (firstChar == '-') {
                    negative = true;
                    //负数需要改变临界值
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+')
                    throw NumberFormatException.forInputString(s);

                //只有一个操作符也是不可以的
                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                //有操作符的情况取位应该从第二位开始
                i++;
            }
            //limit负数为int最小值,正数为-int最大值,与进制基数相除计算临界值
            multmin = limit / radix;
            while (i                 // 通过char类型对应的ASCII码以及进制找到对应的进制int值
                /// https://tool.ip138.com/ascii_code/ ASCII对照表
                digit = Character.digit(s.charAt(i++),radix);
                //如果没有匹配到抛出异常
                if (digit                     throw NumberFormatException.forInputString(s);
                }
                //如果追加超过了溢出阈值抛出异常
                if (result                     throw NumberFormatException.forInputString(s);
                }
                //第一次循环,result为0,这里计算还是为0
                //第二次循环,result赋值为字符串的第 i 位与进制基数相乘
                //.........
                result *= radix;
                //result小于溢出阈值与追加值的和抛出转换异常
                if (result limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                //result等于result减去追加值
                result -= digit;
            }
        } else {
            //空字符返回类型转换异常
            throw NumberFormatException.forInputString(s);
        }
        //符号为正负.result添加对应符号
        return negative ? result : -result;
    }
parseUnsignedInt

定义:将字符串参数解析为无符号的整数

    //转换为无符号int值,默认基数10
        public static int parseUnsignedInt(String s) throws NumberFormatException {
            return parseUnsignedInt(s, 10);
    }
    
    //String转换为无符号int值
    public static int parseUnsignedInt(String s, int radix)
                throws NumberFormatException {
        //为空字符串返回数值转换异常
        if (s == null)  {
            throw new NumberFormatException("null");
        }

        int len = s.length();
        if (len > 0) {
            char firstChar = s.charAt(0);
            //无符号转换不支持负数
            if (firstChar == '-') {
                throw new
                    NumberFormatException(String.format("Illegal leading minus sign " +
                                                       "on unsigned string %s.", s));
            } else {
                //如果没有超过int最大值,就直接调用parseInt直接转换成int值
                if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
                    (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits
                    return parseInt(s, radix);
                } else {
                    //如果超过int最大值,需要进行无符号转换,
                    //因为超过了int的最大值,需要升级为long类型.
                    long ell = Long.parseLong(s, radix);
                    //与运算是当前位同1为1.没有超过0xffffffff00000000的部分都为0.直接进行int强制转换
                    if ((ell & 0xffff_ffff_0000_0000L) == 0) {
                        return (int) ell;
                    } else {
                        //界限为0xffffffff00000000:int最大值+int最小值的绝对值,超出表示不可以被转换
                        throw new
                            NumberFormatException(String.format("String value %s exceeds " +
                                                                "range of unsigned int.", s));
                    }
                }
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
    }
计算型方法
基础运算
    //得到hash值
    public int hashCode() {
        return Integer.hashCode(value);
    }
    //静态方法得到value的hash值
    public static int hashCode(int value) {
        return value;
    }
    //两数之和(此静态方法与Math.sum相同,在这里实现是为了方便流api Integer::sum )
    public static int sum(int a, int b) {
        return a + b;
    }
    //返回ab的最大值(此静态方法与Math.max相同)
    public static int max(int a, int b) {
        return Math.max(a, b);
    }
    //返回ab的最小值(此静态方法与Math.min相同)
    public static int min(int a, int b) {
        return Math.min(a, b);
    }
    //返回i的正负情况(正数为1 负数为-1 0为0)
    public static int signum(int i) {
        return (i >> 31) | (-i >>> 31);
    }
    //比较xy的大小,x小返回-1,x大返回1,相等返回0
    public static int compare(int x, int y) {
        return (x     }
    //比较integer中value变量与anotherInteger的值大小,内部调用compare方法
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
    //判断当前value和传入的obj是否相等
    public boolean equals(Object obj) {
        //判断是否Integer类型,不是则直接返回不相等,是则拆箱后比较
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }
    
    //无符号运算
    //将xy两个整数转换为无符号整数后计算他们相除的商
    public static int divideUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int)(toUnsignedLong(dividend) / toUnsignedLong(divisor));
    }
    //将xy两个整数转换为无符号整数后计算他们相除的余数
    public static int remainderUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int)(toUnsignedLong(dividend) % toUnsignedLong(divisor));
    }
    //比较xy大小,与compare一样,除了x>0,y<0的情况会返回-1,会把xy都加上MIN_VALUE的值,
    public static int compareUnsigned(int x, int y) {
        return compare(x + MIN_VALUE, y + MIN_VALUE);
    }
    
位运算
    //返回二进制下该数字bit位为1的个数
    public static int bitCount(int i) {
        //列出不同的三种实现bitCountJdk,bitCountNormal,bitCountQuite
        //https://segmentfault.com/a/1190000015763941 解释了这三种算法的原理过程
        return bitCountJdk(i);
    }

    static int bitCountJdk(int i){
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

    static int bitCountNormal(int i){
        //实现方式普通实现,时间复杂度为O(n),n为总bit数
        int count = 0;
        do {
            if (( i& 1) == 1) {
                count++;
            }
           i >>=1;
        } while (i > 0);
        return count;
    }

    static int bitCountQuite(int i){
        //优化实现,
        int count = 0;
        while (i > 0) {
            i = i & (i - 1);
            count++;
        }
        return count;
    }
    
    //数字反转(按位)
    public static int reverse(int i) {
        i = (i & 0x55555555) <>> 1) & 0x55555555;
        i = (i & 0x33333333) <>> 2) & 0x33333333;
        i = (i & 0x0f0f0f0f) <>> 4) & 0x0f0f0f0f;
        i = (i <            ((i >>> 8) & 0xff00) | (i >>> 24);
        return i;
    }
    
    //数字反转(按byte)
    public static int reverseBytes(int i) {
        return ((i >>> 24)           ) |
               ((i >>   8) &   0xFF00) |
               ((i <               ((i <    }
    
    // i的二进制左移distance位
    // rotateLeft(x,-y) = rotateRight(x,y)
    public static int rotateLeft(int i, int distance) {
        return (i <>> -distance);
    }
    
    // i的二进制右移distance位
    public static int rotateRight(int i, int distance) {
        return (i >>> distance) | (i <    }
    
    //把数值i转换成二进制数值从高位开始连续0的个数
    //如 110 二进制为 0000000000000000000000000000000000000000000000000001101110 返回 25
    public static int numberOfLeadingZeros(int i) {
        //如果数为0,则直接返回0
        if (i == 0)
            return 32;
        //先初始化0的个数为1
        int n = 1;
        //运用二分法,无符号右移16位(无符号右移:忽略符号位,空位都以0补齐)
        if (i >>> 16 == 0) {
            //如果右移后等于0,说明高位16都是0,则0的个数需要加16
            n += 16;
            //接着我们需要验证剩下的一半,32/2=16位,左移16位
            i <<= 16;
        }
        //剩下的16位我们需要重复二分法,把他等分成两份8位数据,32-16/2=24,所以此时需要无符号右移24位
        if (i >>> 24 == 0) {
            //如果右移后等于0,说明此时高位8都是0,则0的个数需要加8
            n +=  8;
            //接着我们再继续验证剩下的一半,16/2=8位,左移8位
            i <<=  8;
        }
        // ....以次类推
        if (i >>> 28 == 0) { n +=  4; i <<=  4; }
        if (i >>> 30 == 0) { n +=  2; i <<=  2; }
        // 所有情况都走完了,这时n已经代表了0的个数
        // 如果i>>>31为0,则最低位也是0,正好是n初始化为1的理由
        // 如果i>>>31为1,则最低位不为0,初始化n为1会导致多算1个0,n-1正好是0的个数
        n -= i >>> 31;
        return n;
    }
    
    //把数值i转换成二进制数值从低位开始连续0的个数
    public static int numberOfTrailingZeros(int i) {
        int y;
        if (i == 0) return 32;
        //同样采用二分法.依次判断
        int n = 31;
        //先将源数值左移 32/2=16位
        y = i <<16;
        //如果得到的值不为0,表示低位的16位不是0
        if (y != 0) {
            //因为n是连续0的个数,这里不为0所以减去16位
            n = n -16;
            //接下来需要看剩下的16位
            i = y;
        }
        //继续把剩下的16位,左移 16/2=8位
        //重复之前的判断.如果不为0,说明这八位不是连续的0,所以减去8位并把左移8位后的结果赋值给i
        y = i <if (y != 0) { n = n - 8; i = y; }
        // .... 二分法重复以上
        y = i <if (y != 0) { n = n - 4; i = y; }
        y = i <if (y != 0) { n = n - 2; i = y; }
        //负数的首位为1,则n需要减去一位
        return n - ((i <>> 31);
    }
    
    //把最高位设为1,其余位置设为0.
    //技巧:可算出比i小的最接近的2^n的值,因为负数有符号位.本身就为1.所以负数的结果都为 -100000000... 即int的最小值
    public static int highestOneBit(int i) {
        // HD, Figure 3-1
        //二进制i 与 右移一位后的i进行或运算 把高一位和高二位的值设为1
        i |= (i >>  1);
        //二进制i 与 右移一位后的i进行或运算 把高三位和高四位的值设为1
        i |= (i >>  2);
        // ....
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        //最后得到的i为1111111111....111
        //减去无符号位移一位的i 01111111111...1111
        //得到的值就是最高位为1,其余位为0.
        return i - (i >>> 1);
    }
    
    //从低位起,首次出现1的位置向后取值
    public static int lowestOneBit(int i) {
        // HD, Section 2-1
        // 负数的补码:符号位位1,其余位位该数绝对值的原码按位取反;然后整个数加1
        // 如 : i=10 , 二进制位1010 , -10的二进制补码为 1 0101 +1 =10110
        // 则他们的与结果为 01010 & 10110= 10
        return i & -i;
    }
基础类型转换方法
    //实现抽象Number类的基础转换方法
    //返回基本类型int
    public int intValue() {
        return value;
    }
    //返回基本类型long
    public long longValue() {
        return (long)value;
    }
    //返回基本类型float
    public float floatValue() {
        return (float)value;
    }
    //返回基本类型double
    public double doubleValue() {
        return (double)value;
    }
    //返回基本类型short
    public short shortValue() {
        return (short)value;
    }
    //返回基本类型byte
    public byte byteValue() {
        return (byte)value;
    }

内部类 IntegerCache

    //integer的缓存类,缓存-128->127的数据,猜测场景订单的交易数量,大多数都是100以内的价格,
    // 用了IntegerCache,就减少了new的时间也就提升了效率。同时JDK还提供cache中high值得可配置,方便对JVM进行优化
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            //初始化缓存的最高值 -218 +127
            int h = 127;
            //缓存的最高值可以通过配置灵活变动
            //-Djava.lang.Integer.IntegerCache.high=xxx
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            //初始化cache的长度为最大的high-low+1的值,默认为256
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k                 cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        //使用private使内部类无法实例化
        private IntegerCache() {}
    }

缓存内部类经典面试题.

    //引出经典面试题,所以integer比较时用equals比较
    Integer a = 127, b = 127, c = 129, d = 129;
    log.info("use integer cache ->{}", a == b);
    log.info("not use integer cache ->{}", c == d);
    
    //输出
    [main] INFO lang.TestInteger - use integer cache ->true
    [main] INFO lang.TestInteger - not use integer cache ->false
    
    //因为直接赋值Integer对象会调用valueOf(int i)方法,上面有介绍,这个方法在-127~128(默认)的情况下会直接取缓存.所以他们的值引用是相等的.
      但是当超过了`最大缓存值`,会调用构造方法new一个对象.导致他们的引用地址不相等.
    

后记

JDK是java程序员的基础,和我们的开发技能息息相关,Integer很多关于位的计算需要时间去慢慢消化,通过学习他们能够开阔代码的思路.接下来会跟大家一起探索JDK的奥秘.有不同见解也请留言,我们共同学习.此链接为github JDK源码阅读的地址,我会持续更新自己的想法和见解,readme里也介绍了如何自己去调试JDK的方法,欢迎star. 下一篇我会和大家一起探索String类的奇淫巧技

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值