标签:创建 cal 分配 时间格式 abs package ret birt art
1 package cn.temptation; 2 3 public class Sample01 { 4 public static void main(String[] args) { 5 /* 6 * 类 Math:包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。 7 * 8 * Math类的常用字段: 9 * static double E :比任何其他值都更接近 e(即自然对数的底数)的 double 值。 10 * static double PI :比任何其他值都更接近 pi(即圆的周长与直径之比)的 double 值。 11 * 12 * Math类的常用成员方法: 13 * 1、static int abs(int a) :返回 int 值的绝对值。 14 * 2、static double ceil(double a) :返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。 15 * 3、static double floor(double a) :返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。 16 * 4、static int max(int a, int b) :返回两个 int 值中较大的一个。 17 * 5、static int min(int a, int b) :返回两个 int 值中较小的一个。 18 * 6、static double pow(double a, double b) :返回第一个参数的第二个参数次幂的值。 19 * 7、static double random() :返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 20 * 8、static long round(double a) :返回最接近参数的 long。 21 * 9、static double sqrt(double a) :返回正确舍入的 double 值的正平方根。 22 * 23 */ 24 System.out.println(Math.E); // 2.718281828459045 25 System.out.println(Math.PI); // 3.141592653589793 26 27 System.out.println(Math.abs(-2)); // 2 28 29 System.out.println(Math.ceil(12.34)); // 13.0 30 System.out.println(Math.ceil(12.56)); // 13.0 31 32 System.out.println(Math.floor(12.34)); // 12.0 33 System.out.println(Math.floor(12.56)); // 12.0 34 35 System.out.println(Math.max(2, 3)); // 3 36 System.out.println(Math.min(2, 3)); // 2 37 38 System.out.println(Math.pow(2, 3)); // 8.0 39 40 System.out.println(Math.random()); // 0.6111530715212237 41 42 System.out.println(Math.round(12.34)); // 12 43 System.out.println(Math.round(12.56)); // 13 44 45 // 需求:获取指定范围内的随机数 46 System.out.println(getRandom(50, 100)); 47 } 48 49 /** 50 * 获取指定范围内的随机数 51 * @param start 起始值 52 * @param end 终止值 53 * @return 指定范围内的随机数 54 */ 55 public static int getRandom(int start, int end) { 56 return (int)(Math.random() * (end - start)) + start; 57 } 58 }
1 package cn.temptation; 2 3 import java.util.Random; 4 5 public class Sample02 { 6 public static void main(String[] args) { 7 /* 8 * 类 Random:此类的实例用于生成伪随机数流。此类使用 48 位的种子,使用线性同余公式 (linear congruential form) 对其进行了修改。 9 * 10 * Random类的构造函数: 11 * Random() :创建一个新的随机数生成器。 12 * Random(long seed) :使用单个 long 种子创建一个新的随机数生成器。 13 * 14 * Random类的常用成员方法: 15 * 1、int nextInt() :返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。 16 * 2、int nextInt(int n) :返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。 17 * 参数:n - 要返回的随机数的范围。必须为正数。 18 * 返回:下一个伪随机数,在此随机数生成器序列中 0(包括)和 n(不包括)之间均匀分布的 int 值。 19 * 3、void setSeed(long seed) :使用单个 long 种子设置此随机数生成器的种子。 20 */ 21 Random random1 = new Random(); 22 System.out.println(random1.nextInt()); 23 24 Random random2 = new Random(123); 25 System.out.println(random2.nextInt()); // -1188957731 26 27 Random random3 = new Random(); 28 System.out.println(random3.nextInt(5)); 29 30 Random random4 = new Random(); 31 random4.setSeed(123); 32 System.out.println(random4.nextInt()); // -1188957731 33 } 34 }
1 package cn.temptation; 2 3 import java.util.Arrays; 4 5 public class Sample03 { 6 public static void main(String[] args) { 7 /* 8 * 类 System:包含一些有用的类字段和方法。它不能被实例化。 9 * 10 * System类的常用成员方法: 11 * 1、static void exit(int status) :终止当前正在运行的 Java 虚拟机。 12 * 2、static long currentTimeMillis() :返回以毫秒为单位的当前时间。 13 * 返回:当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)。 14 * 3、static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) :从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。 15 */ 16 // JVM的正常关闭 17 // System.exit(0); 18 System.out.println("--------------------------------"); 19 20 // 返回以毫秒为单位的当前时间。(距离协调世界时 1970 年 1 月 1 日午夜) 21 System.out.println(System.currentTimeMillis()); 22 23 // 需求:分别统计使用字符串拼接耗时 和 使用字符串缓冲区拼接耗时 24 // 以拼接字符串"java"和字符串"is simple" 25 26 long start1 = System.currentTimeMillis(); 27 System.out.println(start1); 28 29 String info = "java"; 30 for (int i = 1; i <= 10000; i++) { 31 info += "is simple"; 32 } 33 34 long end1 = System.currentTimeMillis(); 35 System.out.println(end1); 36 37 System.out.println("字符串拼接耗时为:" + (end1 - start1)); 38 39 long start2 = System.currentTimeMillis(); 40 System.out.println(start2); 41 42 StringBuffer sb = new StringBuffer("java"); 43 for (int i = 1; i <= 10000; i++) { 44 sb.append("is simple"); 45 } 46 47 long end2 = System.currentTimeMillis(); 48 System.out.println(end2); 49 50 System.out.println("字符串缓冲区拼接耗时为:" + (end2 - start2)); 51 52 System.out.println("--------------------------------"); 53 54 int[] arr1 = { 1, 2, 3, 4, 5 }; 55 int[] arr2 = { 6, 7, 8, 9, 10 }; 56 System.out.println(Arrays.toString(arr1)); // [1, 2, 3, 4, 5] 57 System.out.println(Arrays.toString(arr2)); // [6, 7, 8, 9, 10] 58 59 System.arraycopy(arr1, 1, arr2, 2, 2); 60 61 System.out.println(Arrays.toString(arr1)); // [1, 2, 3, 4, 5] 62 System.out.println(Arrays.toString(arr2)); // [6, 7, 2, 3, 10] 63 } 64 }
1 package cn.temptation; 2 3 import java.math.BigInteger; 4 5 public class Sample04 { 6 public static void main(String[] args) { 7 /* 8 * 类 BigInteger:不可变的任意精度的整数。可以让超出Integer范围的整数进行运算 9 * 10 * BigInteger类的常用构造函数: 11 * BigInteger(String val) :将 BigInteger 的十进制字符串表示形式转换为 BigInteger。 12 * 13 */ 14 System.out.println("Integer包装类的最大值为:" + Integer.MAX_VALUE); // Integer包装类的最大值为:2147483647 15 16 Integer i = new Integer(2147483647); 17 System.out.println(i); // 2147483647 18 19 // 语法错误:The literal 2147483648 of type int is out of range 20 // Integer j = new Integer(2147483648); 21 // System.out.println(j); 22 23 BigInteger j = new BigInteger("2147483648"); 24 System.out.println(j); // 2147483648 25 } 26 }
1 package cn.temptation; 2 3 import java.math.BigInteger; 4 5 public class Sample05 { 6 public static void main(String[] args) { 7 /* 8 * BigInteger类的常用成员方法: 9 * 1、BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger。 10 * 2、BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger。 11 * 3、BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger。 12 * 4、BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。 13 * 5、BigInteger[] divideAndRemainder(BigInteger val) :返回包含 (this / val) 后跟 (this % val) 的两个 BigInteger 的数组。 14 */ 15 BigInteger i = new BigInteger("2"); 16 BigInteger j = new BigInteger("3"); 17 18 System.out.println("add:" + i.add(j)); // add:5 19 System.out.println("subtract:" + i.subtract(j)); // subtract:-1 20 System.out.println("multiply:" + i.multiply(j)); // multiply:6 21 System.out.println("divide:" + i.divide(j)); // divide:0 22 23 BigInteger[] arr = i.divideAndRemainder(j); 24 System.out.println("商:" + arr[0]); // 商:0 25 System.out.println("余数:" + arr[1]); // 余数:2 26 } 27 }
1 package cn.temptation; 2 3 import java.math.BigDecimal; 4 5 public class Sample06 { 6 public static void main(String[] args) { 7 // System.out.println(0.09 + 0.01); // 0.09999999999999999 8 // System.out.println(1.0 - 0.314); // 0.6859999999999999 9 // System.out.println(1.0414 * 100); // 104.14000000000001 10 // System.out.println(1.301 / 100); // 0.013009999999999999 11 12 // 由上可以看到,在计算时,直接使用double类型或float类型很容易发生了精度丢失的问题 13 // 针对浮点数精度丢失的问题,Java提供了 BigDecimal类型 14 15 /* 16 * 类 BigDecimal:不可变的、任意精度的有符号十进制数。 17 * 18 * BigDecimal类的构造函数: 19 * BigDecimal(double val) :将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。 20 * BigDecimal(String val) :将 BigDecimal 的字符串表示形式转换为 BigDecimal。 21 * 22 * BigDecimal类的成员方法: 23 * 1、BigDecimal add(BigDecimal augend) :返回一个 BigDecimal,其值为 (this + augend),其标度为 max(this.scale(), augend.scale())。 24 * 2、BigDecimal subtract(BigDecimal subtrahend) :返回一个 BigDecimal,其值为 (this - subtrahend),其标度为 max(this.scale(), subtrahend.scale())。 25 * 3、BigDecimal multiply(BigDecimal multiplicand) :返回一个 BigDecimal,其值为 (this × multiplicand),其标度为 (this.scale() + multiplicand.scale())。 26 * 4、 BigDecimal divide(BigDecimal divisor) :返回一个 BigDecimal,其值为 (this / divisor),其首选标度为 (this.scale() - divisor.scale());
如果无法表示准确的商值(因为它有无穷的十进制扩展),则抛出 ArithmeticException。 27 * 5、BigDecimal divide(BigDecimal divisor, int roundingMode) :返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。 28 */ 29 // BigDecimal i = new BigDecimal(0.09); 30 // System.out.println(i); // 0.0899999999999999966693309261245303787291049957275390625 31 // BigDecimal j = new BigDecimal(0.01); 32 // System.out.println(j); // 0.01000000000000000020816681711721685132943093776702880859375 33 // 34 // System.out.println(i.add(j)); // 0.09999999999999999687749774324174723005853593349456787109375 35 36 BigDecimal i = new BigDecimal("0.09"); 37 System.out.println(i); // 0.09 38 BigDecimal j = new BigDecimal("0.01"); 39 System.out.println(j); // 0.01 40 41 System.out.println(i.add(j)); // 0.10 42 System.out.println("------------------------------------------"); 43 44 BigDecimal m = new BigDecimal("1.0"); 45 System.out.println(m); // 1.0 46 BigDecimal n = new BigDecimal("0.314"); 47 System.out.println(n); // 0.314 48 49 System.out.println(m.subtract(n)); // 0.686 50 System.out.println("------------------------------------------"); 51 52 BigDecimal x = new BigDecimal("1.0414"); 53 System.out.println(x); // 1.0414 54 BigDecimal y = new BigDecimal("100"); 55 System.out.println(y); // 100 56 57 System.out.println(x.multiply(y)); // 104.1400 58 System.out.println("------------------------------------------"); 59 60 BigDecimal a = new BigDecimal("1.301"); 61 System.out.println(a); // 1.301 62 BigDecimal b = new BigDecimal("100"); 63 System.out.println(b); // 100 64 65 System.out.println(a.divide(b)); // 0.01301 66 System.out.println("------------------------------------------"); 67 68 System.out.println(a.divide(b, BigDecimal.ROUND_HALF_UP)); // 0.013 四舍五入 69 } 70 }
1 package cn.temptation; 2 3 import java.util.Date; 4 5 public class Sample07 { 6 public static void main(String[] args) { 7 /* 8 * 类 Date:表示特定的瞬间,精确到毫秒。 9 * 10 * Date类的常用构造函数: 11 * Date() :分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。 12 * Date(long date) :分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。 13 * 14 * Date类的常用成员方法: 15 * 1、long getTime() :返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 16 * 2、void setTime(long time) :设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。 17 * 18 */ 19 // 表示当前日期和时间 20 Date date1 = new Date(); 21 System.out.println(date1); // Mon Mar 20 14:04:19 CST 2017 22 23 // 表示当前日期和时间 24 Date date2 = new Date(System.currentTimeMillis()); 25 System.out.println(date2); // Mon Mar 20 14:04:19 CST 2017 26 27 Date date3 = new Date(); 28 System.out.println(date3.getTime()); // 1489990111712 29 System.out.println(System.currentTimeMillis()); // 1489990111712 30 31 date3.setTime(1000); 32 System.out.println(date3); // Thu Jan 01 08:00:01 CST 1970 33 // 注意:CST 中国所在时区,东八区 GMT 格林尼治时间 标准时间 34 } 35 }
1 package cn.temptation; 2 3 import java.text.ParseException; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 7 public class Sample08 { 8 public static void main(String[] args) { 9 /* 10 * 类 DateFormat:日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。 11 * 日期/时间格式化子类(如 SimpleDateFormat)允许进行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和标准化。 12 * 将日期表示为 Date 对象,或者表示为从 GMT(格林尼治标准时间)1970 年 1 月 1 日 00:00:00 这一刻开始的毫秒数。 13 * 14 * 类 SimpleDateFormat:一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。 15 * 16 * SimpleDateFormat类的构造函数: 17 * SimpleDateFormat() :用默认的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。 18 * SimpleDateFormat(String pattern) :用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。 19 * 20 * 21 * DateFormat类的常用成员方法: 22 * 1、String format(Date date) :将一个 Date 格式化为日期/时间字符串。 23 * 2、Date parse(String source) :从给定字符串的开始解析文本,以生成一个日期。 24 */ 25 // 创建日期对象 26 Date date1 = new Date(); 27 // 创建日期/时间格式化对象 28 SimpleDateFormat sdf1 = new SimpleDateFormat(); 29 30 String str1 = sdf1.format(date1); 31 System.out.println(str1); // 17-3-20 下午2:16 32 33 System.out.println("--------------------------------"); 34 35 // 创建日期对象 36 Date date2 = new Date(); 37 // 创建日期/时间格式化对象 38 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); 39 40 String str2 = sdf2.format(date2); 41 System.out.println(str2); // 2017年03月20日 14:19:54 42 43 System.out.println("--------------------------------"); 44 45 String str3 = "2013-02-14 12:12:12"; 46 // SimpleDateFormat构造函数中的模式Pattern需要和字符串中日期时间的格式一致才能转换 47 SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 48 49 // 字符串转换为日期和时间 50 Date date3 = new Date(); 51 try { 52 date3 = sdf3.parse(str3); // Thu Feb 14 12:12:12 CST 2013 53 } catch (ParseException e) { 54 e.printStackTrace(); 55 } 56 System.out.println(date3); 57 } 58 }
1 package cn.temptation; 2 3 import java.util.Date; 4 5 public class Sample09 { 6 public static void main(String[] args) { 7 Date date1 = new Date(); 8 String str1 = DateUtil.dateToString(date1, "yyyy-MM-dd HH:mm:ss"); 9 System.out.println(str1); // 2017-03-20 14:32:40 10 11 Date date2 = DateUtil.stringToDate("2017-03-20", "yyyy-MM-dd"); 12 System.out.println(date2); // Mon Mar 20 00:00:00 CST 2017 13 } 14 }
1 package cn.temptation; 2 3 import java.text.ParseException; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 7 /** 8 * 日期工具类 9 */ 10 public class DateUtil { 11 // 构造函数 12 public DateUtil() { 13 14 } 15 16 // 成员方法 17 /** 18 * 日期转字符串 19 * @param date 日期对象 20 * @param pattern 显示模式 21 * @return 字符串 22 */ 23 public static String dateToString(Date date, String pattern) { 24 SimpleDateFormat sdf = new SimpleDateFormat(pattern); 25 return sdf.format(date); 26 } 27 28 /** 29 * 字符串转日期 30 * @param str 字符串 31 * @param pattern 显示模式 32 * @return 日期对象 33 */ 34 public static Date stringToDate(String str, String pattern) { 35 SimpleDateFormat sdf = new SimpleDateFormat(pattern); 36 37 Date result = new Date(); 38 try { 39 result = sdf.parse(str); 40 } catch (ParseException e) { 41 e.printStackTrace(); 42 } 43 44 return result; 45 } 46 }
1 package cn.temptation; 2 3 import java.text.ParseException; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 import java.util.Scanner; 7 8 public class Sample10 { 9 public static void main(String[] args) throws ParseException { 10 // 需求:通过键盘录入生日(格式为:yyyy-MM-dd),计算来到这个世界多少天了? 11 12 // 思路: 13 // 1、接收键盘录入的生日字符串,需要做格式检查 14 // 2、生日字符串转换为日期 15 // 3、日期转换成毫秒 16 // 4、转换为天数:(当前日期时间的毫秒数 - 生日日期时间的毫秒数) / 1000 / 60 / 60 / 24 17 18 // 1、接收键盘录入的生日字符串,需要做格式检查 19 String birthday = ""; 20 boolean flag = true; 21 22 System.out.println("输入生日日期:"); 23 Scanner input = new Scanner(System.in); 24 if (input.hasNextLine()) { 25 birthday = input.nextLine(); 26 // 检查格式是否为yyyy-MM-dd,考虑使用正则表达式(最简单的正则,只判断是不是数字) 27 String regex = "[0-9]{4}-[0-9]{2}-[0-9]{2}"; 28 flag = birthday.matches(regex); 29 System.out.println(flag ? "是生日日期" : "不是生日日期"); 30 } else { 31 System.out.println("输入错误!"); 32 } 33 input.close(); 34 35 if (flag) { // 日期格式正确,才进行计算 36 // 2、生日字符串转换为日期 37 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 38 Date date = sdf.parse(birthday); 39 40 // 3、日期转换成毫秒 41 long birthdayTime = date.getTime(); 42 43 // 4、转换为天数:(当前日期时间的毫秒数 - 生日日期时间的毫秒数) / 1000 / 60 / 60 / 24 44 System.out.println("来到这个世界" + (System.currentTimeMillis() - birthdayTime) / 1000 / 60 / 60 / 24 + "天"); 45 } 46 } 47 }
1 package cn.temptation; 2 3 import java.util.Calendar; 4 5 public class Sample11 { 6 public static void main(String[] args) { 7 /* 8 * 类 Calendar:是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法, 9 * 并为操作日历字段(例如获得下星期的日期)提供了一些方法。 10 * 瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。 11 * 12 * Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。 13 * Calendar 的 getInstance 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化 14 * 15 * 类 GregorianCalendar:GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。 16 * 17 * Calendar类的常用成员方法: 18 * 1、static Calendar getInstance() :使用默认时区和语言环境获得一个日历。 19 * 2、int get(int field) :返回给定日历字段的值。 20 * 3、void set(int year, int month, int date) :设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值。 21 * 4、abstract void add(int field, int amount) :根据日历的规则,为给定的日历字段添加或减去指定的时间量。 22 */ 23 Calendar rightnow = Calendar.getInstance(); 24 System.out.println(rightnow); // java.util.GregorianCalendar 25 26 // 获取年 27 int year = rightnow.get(Calendar.YEAR); 28 System.out.println("年份为:" + year); // 2017 29 // 获取月 30 int month = rightnow.get(Calendar.MONTH); // 在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0;最后一个月取决于一年中的月份数。 31 System.out.println("月份为:" + month); // 2 32 // 获取日 33 int date = rightnow.get(Calendar.DATE); 34 System.out.println("日为:" + date); // 20 35 36 System.out.println("--------------------------------------"); 37 38 Calendar calendar1 = Calendar.getInstance(); 39 calendar1.set(2013, 2, 14); 40 System.out.println(calendar1.get(Calendar.YEAR) + "年" + calendar1.get(Calendar.MONTH) + "月" + calendar1.get(Calendar.DATE) + "日"); // 2013年2月14日 41 42 Calendar calendar2 = Calendar.getInstance(); 43 calendar2.add(Calendar.YEAR, -4); 44 System.out.println(calendar2.get(Calendar.YEAR)); // 2013 45 } 46 }
1 package cn.temptation; 2 3 import java.util.Calendar; 4 import java.util.Scanner; 5 6 public class Sample12 { 7 public static void main(String[] args) { 8 // 需求:根据录入的年份,获取该年的2月份有多少天? 9 10 // 思路: 11 // 1、获取键盘录入的年份 12 // 2、通过年份在Calendar对象中设置为输入年份的3月1日 13 // 3、从3月1日倒退1天 14 // 4、倒退后,查看位于2月的第多少天 15 16 // 1、获取键盘录入的年份 17 int year = 0; 18 System.out.println("输入年份:"); 19 Scanner input = new Scanner(System.in); 20 if (input.hasNextInt()) { 21 year = input.nextInt(); 22 } else { 23 System.out.println("输入错误!"); 24 return; 25 } 26 input.close(); 27 28 Calendar calendar = Calendar.getInstance(); 29 // 2、通过年份在Calendar对象中设置为输入年份的3月1日 30 calendar.set(year, 2, 1); // 注意:月份设置为2,表示的是3月 31 32 // 3、从3月1日倒退1天 33 calendar.add(calendar.DAY_OF_MONTH, -1); 34 35 // 4、倒退后,查看位于2月的第多少天 36 int dayOfMonth = calendar.get(calendar.DAY_OF_MONTH); 37 38 System.out.println(year + "年中的二月有:" + dayOfMonth + "天"); 39 } 40 }
标签:创建 cal 分配 时间格式 abs package ret birt art
原文地址:http://www.cnblogs.com/iflytek/p/6606714.html