当前位置:   article > 正文

JavaSE - 常用Api_java se api

java se api

1. String

          1.1 概述

                  java.lang.String 字符串类

                  java 9 之前底层为字节数组(char[]),java 9 开始使用字节数组存储(byte[])

                  1. 字符串一旦确定,不能修改

                  2. 为了提高字符串的效率,java虚拟机使用了一种“缓存技术”,字符串常量池

                  3. 在以字面量形式创建一个字符串对象时,先看字符串常量池中是否已经存在相同的值,如果没有就创建一个, 如果常量池中已经有了,就直接调用该对象即可。所以很多时候字符串类型的比较,也可以使用==,因为他们内存地址都一样(仅限于字面量)

                  4. 以new的方式创建时,会在堆内存创建字符串,同时也会在常量池中创建该字符串的对象。

          1.2 基本使用
  1. public class String_00 {
  2. public static void main(String[] args) {
  3. // String字面量写法,只会在字符串常量池中创建一个对象
  4. String s1 = "123";
  5. String s2 = "123";
  6. String s3 = "1234";
  7. System.out.println(s1 == s2); //true
  8. System.out.println(s1.equals(s2)); // true
  9. System.out.println(s1.equals(s3)); // false
  10. // String创建对象写法,会在堆内存中创建不同对象,同时在常量池中创建对象
  11. // s4和s5会在堆内存中创建不同对象,同时在字符串常量池中创建一个字符串常量
  12. String s4 = new String("12345");
  13. String s5 = new String("12345");
  14. // s6指向常量池
  15. String s6 = "12345";
  16. System.out.println(s4 == s5); // false
  17. System.out.println(s4.equals(s5)); // true
  18. System.out.println(s4 == s6); // false
  19. System.out.println(s4.equals(s6)); // true
  20. // inter():将字符串添加到内部的字符串池中,并返回字符串池中的引用的方法
  21. System.out.println(s4.intern() == s5.intern());
  22. System.out.println(s4.intern() == s6.intern());
  23. }
  24. }
          1.3 构造方法
  1. public static void main(String[] args) {
  2. // 1.字面量
  3. String s1 = "abc";
  4. // 2.new对象
  5. String s2 = new String("abc");
  6. // 3.字节数组
  7. byte[] bytes = {97,98,99,100};
  8. // 下标从0开始,传入3个字符
  9. String s3 = new String(bytes,0,3);
  10. System.out.println(s3);
  11. // 全部传入
  12. String s4 = new String(bytes);
  13. System.out.println(s4);
  14. // 4.字符数组
  15. char[] chars = {'a','c','d','f'};
  16. // 下标从0开始,传入2个字符
  17. String s5 = new String(chars,0,2);
  18. System.out.println(s5);
  19. // 全部传入
  20. String s6 = new String(chars);
  21. System.out.println(s6);
  22. }
          1.4 常用方法
  1. public static void main(String[] args) {
  2. String str = "hello world";
  3. // 1. char charAt(int index) :获取字符串中对应索引的字符
  4. char c = str.charAt(0);
  5. System.out.println(c);
  6. // 2. boolean endWith(String str): 判断某个字符串是否以指定字符串结尾
  7. System.out.println(str.endsWith("ld"));
  8. // 3. byte[] getBytes():把该字符串转换为字节数组
  9. byte[] b = str.getBytes();
  10. // 4 char[] toCharArray() : 把字符串转换为字符数组
  11. char[] chars = str.toCharArray();
  12. // 5 int indexOf(String str) : 获取指定字符串在该字符串中的索引下标 , 如果不存在则返回-1
  13. // 从左到右的找,如果存在多个符合条件的,则返回第一个符合条件的下标
  14. System.out.println(str.indexOf("h"));
  15. // 传入3,表示从下标3开始往后找
  16. System.out.println(str.indexOf("m", 3));
  17. // 6 int lastIndexOf(String str) : 最后一次出现的索引,找不到返回-1
  18. // 从右往左找
  19. System.out.println(str.lastIndexOf("e"));
  20. // 7. int length():返回字符串长度
  21. System.out.println(str.length());
  22. str = "asdfghjkl deggrt ";
  23. System.out.println(str.length());
  24. // 8. String replace(String a,String b):替换,返回替换后的新字符串
  25. System.out.println(str.replace("g", "!"));
  26. // replaceAll:支持正则表达式
  27. System.out.println(str.replaceAll("g", "!"));
  28. // 9. String[] split(String str):以特定字符串进行分割,返回字符串数组,支持正则表达式
  29. str = "2024-01-15";
  30. String[] strs = str.split("-");
  31. for(int i = 0; i < strs.length; i++) {
  32. System.out.println(strs[i]);
  33. }
  34. // 10.String subString(int index):截取字符串,获取指定索引开始(包含指定索引)到结束的字符串
  35. str = "asdfghjkl awsdd";
  36. // 左闭右开jkl awsdd
  37. System.out.println(str.substring(6));
  38. // 截取某下标到某下标的字符串,左闭右开
  39. System.out.println(str.substring(6, 9));
  40. // 11.String toUpperCase():转为大写并返回
  41. System.out.println(str.toUpperCase());
  42. // 12.String toLowerCase():转为小写并返回
  43. str = "ADGHJK jiann LO";
  44. System.out.println(str.toLowerCase());
  45. // 13.String trim():删除两边(首尾)空格并返回
  46. str = " aws weff ";
  47. String str1 = " aws weff ";
  48. System.out.println(str.trim());
  49. System.out.println(str1);
  50. // 删除所有空格并返回,使用替换把所有空格替换为空
  51. System.out.println(str.replace(" ", ""));
  52. // 14.equals():比较两个字符串是否相同
  53. System.out.println("asd".equals("aaa"));
  54. // 15.equalsIgnore():不区分大小写比较两个字符串是否相同
  55. System.out.println("ABC ij".equalsIgnoreCase("ABC ij"));
  56. // 16.static String valueOf(Object obj):调用对象的toString方法,并对null值进行处理,避免空指针
  57. Object obj = null;
  58. System.out.println(String.valueOf(obj));
  59. }
          1.5 注意:

                字符串不能频繁的做拼接操作,因为字符串一旦确定不能修改,频繁的拼接字符串效率较低且不利于垃圾回收。

2. StringBuffer和StringBuilder

          2.1 概述

                  StringBuffer和StringBuilder是什么

                  底层都是char数组,只不过数组可变长,所以当我们需要进行频繁的字符串拼接时可以使用

                  原理:

                  预先在内存空间中申请一块空间,足够容纳更多字符,如果预留空间不足,会自动进行扩容,默认初始化长度为16.扩大容量为 length*2 + 2 , 源码是 ( (value.length << 1) + 2;)

                  StringBuffer 和 StringBuilder的区别:

                  StringBuffer : 线程安全,在多线程环境下不会出现问题,常用于类中。

                  StringBuilder : 线程不安全,在多线程环境下,可能出现问题,常用于方法中。

          2.2 基本使用
  1. public static void main(String[] args) {
  2. // 创建对象
  3. // StringBuilder sb = new StringBuilder("a");
  4. StringBuilder strBulider = new StringBuilder();
  5. // 尾部添加
  6. strBulider.append("a");
  7. strBulider.append("b").append("c");
  8. // 添加到指定位置
  9. strBulider.insert(2, "c");
  10. // 反转
  11. strBulider.reverse();
  12. // 添加元素个数
  13. System.out.println(strBulider.length());
  14. // 当前容量
  15. System.out.println(strBulider.capacity());
  16. // 转化为String类型
  17. String str = strBulider.toString();
  18. System.out.println(str);
  19. }

3. 包装类

          3.1 概述

          想要对基本数据类型进行更多操作,怎么办

          最方便的方法就是将其封装成对象,因为在对象描述中就可以定义更多的属性和行为 对该基本数据类型进行操作。我们不需要自己去对基本数据类型进行封装,JDK已经为我们封装好了

          1. 装箱就是自动将基本数据类型转换为包装器类型

          2. 拆箱就是自动将包装器类型转换为基本数据类型

          3.2 使用(八种包装类,都覆写了equals 和 toString 及 hashCode方法)
  1. public static void main(String[] args) {
  2. // 基本类型
  3. byte b1 = 10;
  4. short s1 = 4;
  5. int a1 = 11;
  6. long l1 = 123456L;
  7. float f1 = 1.23f;
  8. double d1 = 12.3;
  9. boolean flag1 = true;
  10. char ch = 'a';
  11. // 包装类类型
  12. Byte b2 = new Byte(b1);
  13. Byte b3 = new Byte(b1);
  14. System.out.println(b2.equals(b3));
  15. Short sh = new Short(s1);
  16. Integer a2 = new Integer(a1);
  17. Long l2 = new Long(l1);
  18. Float f2 = new Float(f1);
  19. Double d2 = new Double(d1);
  20. Boolean flag2 = new Boolean(flag1);
  21. Character c = new Character(ch);
  22. m1(b2);
  23. m1(b3);
  24. m1(sh);
  25. m1(a2);
  26. m1(l2);
  27. m1(f2);
  28. m1(d2);
  29. m1(flag2);
  30. m1(c);
  31. }
  32. public static void m1(Object obj) {
  33. System.out.println(obj);
  34. }
          3.3 Integer
                  3.3.1 基本使用
  1. public static void main(String[] args) {
  2. // 最大值
  3. System.out.println(Integer.MAX_VALUE);
  4. // 最小值
  5. System.out.println(Integer.MIN_VALUE);
  6. // 创建对象
  7. Integer i1 = new Integer(11);
  8. // 传入纯数字字符串
  9. Integer i2 = new Integer("12");
  10. // 必须纯数字,否则运行会报错
  11. // Integer i3 = new Integer("12ss");
  12. }
                  3.3.2 相互转换
  1. public class Integer_02 {
  2. // int --> Integer
  3. Integer i1 = Integer.valueOf(11);
  4. // Integer --> int
  5. int i2 = i1.intValue();
  6. // String --> Integer
  7. Integer i3 = Integer.valueOf("1234");
  8. // Integer --> String
  9. String s1 = i3.toString();
  10. // int --> String
  11. String s2 = 12 + "";
  12. // String --> int
  13. int i4 = Integer.parseInt("1234");
  14. }

                  3.3.3 常用方法
  1. public static void main(String[] args) {
  2. // 创建对象,可以把int 封装为 Integer类型
  3. Integer i1 = new Integer(11);
  4. // 通过intValue 把包装类 转换为 基本类型
  5. int i2 = i1.intValue();
  6. // 重要 : static int parseInt(String s ) : 把纯数字的字符串转换为int类型
  7. i2 = Integer.parseInt("1234");
  8. double d = Double.parseDouble("112.22");
  9. // static String toBinaryString(int value) : 转换为字符串类的二进制表示法
  10. System.out.println(Integer.toBinaryString(15));
  11. // 转十六进制
  12. System.out.println(Integer.toHexString(15));
  13. // 转八进制
  14. System.out.println(Integer.toOctalString(15));
  15. // 重要 static Integer valueOf(int value) : 把int类型转换为Integer类型
  16. Integer i4 = Integer.valueOf(1234);
  17. Integer i5 = Integer.valueOf("1234");
  18. }
                  3.3.4 自动装箱和自动拆箱

                          装箱 : 基本类型到引用类型

                          拆箱 : 引用类型到基本类型

                          1.5开始 引入自动装箱和自动拆箱

  1. public static void main(String[] args) {
  2. // 1.5之前装箱
  3. Integer i1 = new Integer(11);
  4. i1 = Integer.valueOf(11);
  5. // 1.5之后拆箱
  6. Integer i2 = 12;
  7. // 1.5之前的拆箱
  8. int i3 = i2.intValue();
  9. // 1.5及以后的拆箱
  10. int i4 = i2;
  11. // 此时 15为int类型,会先自动装箱为Integer类型,然后在向上转型发生多态
  12. m1(15);
  13. }
  14. public static void m1(Object obj) {
  15. System.out.println(obj);
  16. }
                  3.3.5 深入整形常量池

                  IntegerCache.cache 是整型常量池,是个保存了256个Integer对象的数组,分别是 -128~127,当我们进行自动装箱或手动调用Integer.valueOf()方法时,会先判断是否符合整型常量池

,如果符合范围,则直接在整形常量池中把提前创建好的对象引用,赋值给他即可,不用再次创建。

  1. public static void main(String[] args) {
  2. // 直接在堆内创建对象
  3. Integer a1 = new Integer(11);
  4. Integer a2 = new Integer(11);
  5. System.out.println(a1 == a2);
  6. System.out.println(a1.equals(a2));
  7. // 自动装箱, 会转型为 Integer.valueOf()
  8. // valueOf 中 进行了整形常量池从操作
  9. // 如果 值 -128~127之间,则不需要创建对象 , 否则 就在堆内存创建对象(new Integer())
  10. Integer a3 = 15;
  11. Integer a4 = 15;
  12. System.out.println(a3 == a4);
  13. Integer a5 = 555;// 等同于 i5 = new Integer(555)
  14. Integer a6 = 555;// 等同于 i5 = new Integer(555)
  15. System.out.println(a5 == a6);
  16. }

4. System

        4.1 概述

        System类代表系统,系统的很多属性和控制方法都放置在该类中。该类位于java.lang包, 由于该类的构造器是private的,所以无法创建该类对象,也就无法实例化该类。其内部的变量和方法都是静态的,所以可以很方便的调用。

         1. System类内部包含in,out,err三个静态变量,分别代表标准输入流,标准输出流和标准错误输出流

         2. System类提供的public static long currentTimeMillis(),

 用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。

        3. void exit(int atatus):该方法的作用是退出程序,参数为0为正常退出,

 非0代表异常退出,使用该方法可以在图形页面编程中实现程序的退出功能。

         4.2 常用方法
  1. public static void main(String[] args) {
  2. // out,err,in 都是System中提供的打印方法
  3. // out 标准输出,默认打印在控制台
  4. System.out.println("控制台打印");
  5. // in 标准输入,默认接受控制太输入
  6. Scanner scanner = new Scanner(System.in);
  7. System.out.println("请输入一个整数");
  8. int n = scanner.nextInt();
  9. // err 错误输出,打印颜色为红色,异步打印
  10. System.err.println("控制台错误形式的输出");
  11. // 获取当前系统对应的毫秒数,可用于统计时间
  12. // 从1970-1-1 8:00:00 到当前时间的毫秒数
  13. long startTime = System.currentTimeMillis();
  14. // 其它事务代码
  15. long endTime = System.currentTimeMillis();
  16. // 耗时
  17. System.out.println(endTime - startTime);
  18. // 建议垃圾回收
  19. System.gc();
  20. // 关闭JVM,0 表示正常退出,一般用于图形化界面
  21. System.exit(0);
  22. }

5. Date

        5.1 概述

              获取时间和时间操作

                java 8之前使用Date,java 8中新引入了LocalDateTime,java 8 之后的版本推荐使用LocalDateTime。

             Date和LocalDateTime的区别:

                 1. Date是java早期引入的日期时间类,位于java.util包中,LocalDateTime是java 8中新引入日期时间类,位于java.time包中。

                 2. Date是可变类,可以直接修改Date对象的值,而LocalDateTime是不可变类,一旦确定不能修改,如果要修改必须重新创建对象。

                 3. Date在表示日期和时间时会考虑系统时区,而LocalDateTime只表示日期和时间,不会考虑系统时区,如果需要考虑时区可以使用ZonedDateTime实现。

                 4. Date类精确到毫秒级,但设计存在问题,容易产生线程安全问题,而LocalDateTime类提供了更好的精确度,可以表示纳秒的时间。

                 5. Date类Api设计过于老旧,一些方法已经过时,LocalDateTime设计更现代化,直观易用。

        5.1 构造方法
  1. public class Date_01 {
  2. public static void main(String[] args) {
  3. // 注意导入的包为java.util.Date;
  4. // 使用Date获取当前系统时间
  5. Date date = new Date();
  6. // Date:Tue Jan 16 19:15:09 CST 2024
  7. System.out.println("Date:" + date);
  8. // 注意导入的包为ava.time.LocalDateTime;
  9. // 使用LocalDateTime获取当前系统时间
  10. LocalDateTime localDateTime = LocalDateTime.now();
  11. // localDateTime:2024-01-16T19:17:34.703
  12. System.out.println("localDateTime:" + localDateTime);
  13. // 创建指定日期和时间的Date对象(年的参数是指需设定的年份减去1900的结果,月的参数是从0开始计数的,所以0表示1月)
  14. // 当前构造方法以过时,不推荐使用
  15. Date specifyDate = new Date(124, 0, 16, 19, 23, 12);
  16. // specifyDate:Tue Jan 16 19:23:12 CST 2024
  17. System.out.println("specifyDate:" + specifyDate);
  18. // 创建指定日期时间的LocalDateTime对象
  19. LocalDateTime specifyLocalDateTime = LocalDateTime.of(2014, 1, 16, 19, 23, 12);
  20. // specifyLocalDateTime:2014-01-16T19:23:12
  21. System.out.println("specifyLocalDateTime:" + specifyLocalDateTime);
  22. // 修改Date对象的时间,Date对象是可变的
  23. date.setHours(12);// 方法已过时
  24. // Date:Tue Jan 16 12:32:32 CST 2024
  25. System.out.println("Date:" + date);
  26. // 修改LocalDateTime对象的时间,LocalDateTime是不可变的,需要创建新对象
  27. LocalDateTime reviseLocalDateTime = LocalDateTime.now().withHour(12).withMinute(24);
  28. // reviseLocalDateTime:2024-01-16T12:24:01.980
  29. System.out.println("reviseLocalDateTime:" + reviseLocalDateTime);
  30. }
  31. }
        5.2 格式化
  1. import java.text.ParseException;
  2. import java.text.SimpleDateFormat;
  3. import java.time.LocalDateTime;
  4. import java.time.format.DateTimeFormatter;
  5. import java.util.Date;
  6. // 格式化
  7. // y年 M月 d日 H时 m分 s秒 S毫秒
  8. public class Date_02 {
  9. public static void main(String[] args) throws Exception {
  10. // 将Date对象格式化为字符串
  11. // 创建一个Date类时间对象
  12. Date dateTime = new Date();
  13. // 创建一个SimpleDateFormat对象,指定日期时间的格式
  14. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS");
  15. // format方法:把时间对象按照对应的格式 进行转换,返回转换后的字符串
  16. String strTime = sdf.format(dateTime);
  17. System.out.println(strTime);
  18. // 将字符串解析为Date对象
  19. // 注:时间格式的字符串必须和SimpleDateFormat指定的格式一致.
  20. strTime = "2024-01-16 11:48:24:316";
  21. // parse方法:把时间格式的字符串转换为Date对象
  22. Date newDate = sdf.parse(strTime);
  23. System.out.println(newDate);
  24. // 将LocalDateTime对象格式化为字符串
  25. // 创建一个LocalDateTime类的时间对象
  26. LocalDateTime now = LocalDateTime.now();
  27. // 创建一个DateTimeFormatter对象,表示要使用的格式
  28. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SS");
  29. // 调用format()方法,将LocalDateTime对象格式化为字符串
  30. String str = now.format(formatter);
  31. System.out.println(str);
  32. // 将字符串解析为LocalDateTime对象
  33. // 创建一个字符串,表示日期和时间
  34. strTime = "2024-01-16 19:52:38:92";
  35. // 调用parse()方法,将字符串解析为LocalDateTime对象
  36. LocalDateTime localTime = LocalDateTime.parse(strTime,formatter);
  37. System.out.println(localTime);
  38. }
  39. }
        5.3 Calendar(获取当前系统日历)
  1. import java.util.Calendar;
  2. public class Calenar_01 {
  3. public static void main(String[] args) {
  4. // 获取当前系统日历
  5. Calendar c = Calendar.getInstance();
  6. // 获取当天是本周的第几天,周日为第一天
  7. int i = c.get(Calendar.DAY_OF_WEEK);
  8. // 获取年
  9. System.out.print(c.get(Calendar.YEAR) + "年");
  10. // 获取月,从0开始,0是一月
  11. System.out.print(c.get(Calendar.MONTH)+ 1 + "月");
  12. // 获取日
  13. System.out.print(c.get(Calendar.DAY_OF_MONTH) + "日" + " ");
  14. // 获取时
  15. System.out.print(c.get(Calendar.HOUR_OF_DAY) + "时");
  16. // 获取分
  17. System.out.print(c.get(Calendar.MINUTE)+ "分");
  18. // 获取秒
  19. System.out.print(c.get(Calendar.SECOND)+ "秒");
  20. }
  21. }

6. Random

        6.1 概述

              random: 从0开始生成随机数

        6.2 使用
  1. public class Random_01 {
  2. public static void main(String[] args) {
  3. // 创建生成器对象
  4. Random random = new Random();
  5. // 在int范围内随机生成一个数
  6. int i = random.nextInt();
  7. System.out.println(i);
  8. // 在10个数内随机生成一个,0~9,不包含10
  9. int result = random.nextInt(10);
  10. System.out.println(result);
  11. // 在10~20间随机生成一个数,包含10和20
  12. result = random.nextInt((20 - 10 + 1)) + 10;
  13. System.out.println(result);
  14. // 在100~150之间随机生成一个数,包含100和150
  15. result = random.nextInt((150 - 100 + 1)) + 100;
  16. System.out.println(result);
  17. // 生成a~z之间的字母
  18. char c = (char)((random.nextInt('z' - 'a' + 1)) + 'a');
  19. System.out.println(c);
  20. }
  21. }

7. BigInteger

        7.1 概述

                 1. Integer作为Java的包装类,能存储的最大整型值为2^31-1,Long类也是有限的,最大为2^61-1,如果要表示再大的整数,不管基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。

                 2. java.math包的BigInteger可以表示不可变的任意精度整数。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、 位操作以及一些其他操作。

        7.2 常用方法

              public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。

              BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger

              BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger

              BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger

              BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。

              BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。

              BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟(this % val) 的两个 BigInteger 的数组。

              BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。

         7.3 使用
  1. public class BigInteger_00 {
  2. public static void main(String[] args) {
  3. // 两种对象的创建
  4. BigInteger big = new BigInteger("12");
  5. BigDecimal bigNum = new BigDecimal(15);
  6. // 运算操作
  7. BigDecimal b1 = new BigDecimal(12);
  8. BigDecimal b2 = new BigDecimal(36);
  9. // 结果
  10. BigDecimal b3 = null;
  11. // 加
  12. b3 = b1.add(b2);
  13. System.out.println(b3);
  14. // 减
  15. b3 = b1.subtract(b2);
  16. System.out.println(b3);
  17. // 乘
  18. b3 = b1.multiply(b2);
  19. System.out.println(b3);
  20. // 除(BigDecimal要求除法运算结果必须是一个精确的十进制数,如果结果出现循环小数需要做精度处理)
  21. b3 = b1.divide(b2,2, RoundingMode.HALF_UP);
  22. System.out.println(b3);
  23. // 取余
  24. b3 = b1.remainder(b2);
  25. System.out.println(b3);
  26. }
  27. }
        7.4 阶乘(例子)
  1. import java.math.BigDecimal;
  2. public class Number_00 {
  3. public static void main(String[] args) {
  4. System.out.println(test(100));
  5. }
  6. // 100的阶乘
  7. public static BigDecimal test(int n) {
  8. BigDecimal result = new BigDecimal(1);
  9. for (int i = 1; i <= n; i++) {
  10. result = result.multiply(new BigDecimal(i));
  11. }
  12. return result;
  13. }
  14. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/802710
推荐阅读
相关标签
  

闽ICP备14008679号