1.String   
     1.概述
         java.lang.String: 是字符串类,底层就是一个final修饰的char数组,所以String很多特性就是数组的特性
         注:Java.lang是核心包,不需要导包
         比如 一旦确定长度,不能更改
         1.字符串一旦创建,这个字符串对象不能再更改,但变量的内容可以更换。
         2.为了提升字符串的访问和存储效率,java虚拟机采用了一种缓存机制,把字符串都保存在了字符串常量池中
         3.在程序执行过程中,加入要用到一个字符串a  String s1 = "a";先去字符串常量池中检索是否有a,没有再创建一份
             如果有了 String s2 = "a"; ,就不再创建,把已有的这个a返回
             所以导致此时 使用 s1 == s2;他也是true,因为他们指向同一个字符串对象,就是a
     
     2.基本使用
         1.创建一个对象,他们都指向常量池
         String s1 = "a";
         String s2 = "a";
         System.out.println(s1.equals(s2));         //返回值为true,比较的是值
         System.out.println(s1 == s2);              //返回值为true,比较的是地址
         s1 = 'b';           //String一旦创建不能更改的意思是变量指向的对象中的数据不能更改,不是这个变量不能更改
         
         //如果使用了new的方式,那么会创建堆内存对象,该字符串对象会保存在堆内存中
         String s3 = new String("a");
         String s4 = new String("a");
         System.out.println(s3 == s4);               //因为s3和s4不指向常量池,而是分别指向了堆内存,所以地址不同,为false
         System.out.println(s3.equals(s4);           //但是String中覆写了equals方法比较值,所以是true        
         注: String中对比是否相等,尽量使用equals而不去使用 == 
     
     3.不要频繁拼接
         因为字符串创建后不能更改,如果频繁拼接会频繁创建新数组频繁制造垃圾,效率很低,并且垃圾回收可能也会出问题
    4.构造方法(String是特殊的,可以像基本数据类型一样赋值)
         1.字面量: String s1 = "asad";
         2.
         3.字节数组:byte[] bytes = {97,46,7,84,46};
                    String s3 = new String(bytes);
                    System.out.println(s3);              //将字节转化为字符串输出  abcdef
         4.字节数组,只截取一部分,4表示起始下标(包含),2表述个数
             String s4 = new String(byte,4,2);           
             System.out.println(s4);                     //ef
         5.字符数组
             char[] chars = {'a','b','c','d'};
                 String s5 = new String(chars);
                 System.out.println(s5);
         6.字符数组,只截取一部分,1表示起始下标(包含),2表示个数
                 String s6 = new String(chars,1,2);
                 System.out.println(s6);
         
     5.常用方法
         学习API:1.功能是什么
                  2.入参和出参是什么
                  3.怎么用
                  (一定要记住API有哪些功能,入参出参怎么用都可以百度,但一定要记住哪些功能可以用API解决)
         1. char charAt(int index): 返回该字符串中,指定位置(下标)的字符
             String s1 = "qwerasdf";
             char c1 = s1.charAt(2);
             System.out.println(c1);                     //e
         
         2.boolean endsWith(String suffix):判断字符串是否以指定字符串结尾
           boolean startsWith(String prefix):同上,判断开始
           System.out.println("Hello.java".endsWith(".java"));       //注意:有空格就无法匹配上
         
         3.boolean equalslgnoreCase(String str):不区分大小写比较两个字符是否相等
             System.out.println("abc".equalslgnoreCase("aBc"));
        4.byte[] getBytes(): 把字符串转化为字节数组并返回
             byte[] bytes = "abc".getBytes();
             for(int i=0;i<bytes.length;i++){
                 System.out.println(bytes[i]);
             }
        5.char[] toCharArray():把字符串转换为字符数组并返回
             char[] chars = "abc".toCharArray();
             for(int i=0;i<chars,length;i++){
                 System.out.println(chars[i]);
             }
        6. int indexOf(String str):获取该字符串中指定字符串的起始索引,找不到返回-1
             System.out.println("askdhwqer".indexOf("kd"));          //2
        7.int indexOf(String str,int index); 从指定位置开始查找(包含)获取该字符串中指定字符串的起始索引,找不到返回-1
             System.out.println("askdhwqer".indexOf("s",5));         //-1
         
         8.index lastIndexOf(String str):同上,最后一次出现的索引,找不到返回-1
             System.out.println("sagsadgsdfsdag".lastIndexOf("a"));  //2
        9.int length(): 返回该字符串的长度
             System.out.println("abc".length());
        10.String replaceAII(String regex.String replacement); 替换指定字符,支持正则表达式
             String replace(String str.String replacement);不支持正则表达式
             // 用1 把 a 替换了并返回新的字符串
             // 支持正则表达式,但是没有写正则表达式 是没有区别的
             System.out.println("hucgasdqweasd".replaceAll("a", "1"));
             System.out.println("hucgasdqweasd".replace("a", "1"));
             // 因为 . 在正则表达式中,代表任意字符
             System.out.println("qwe.rty.yui.uio".replaceAll(".", ","));
             // 可以使用 \ 转义
             System.out.println("qwe.rty.yui.uio".replaceAll("\\.", ","));
             System.out.println("qwe.rty.yui.uio".replace(".", ","));
        11.String[] split(String regex):分割字符串,返回字符串数组,支持正则表达式
             注意: 点 需要转义
             String s2 = "2020.1.14";
             String[] arr = s2.split("\\.");
             for(int i=0;i<arr.length;i++){
                 System.out.println(arr[i]);
             }
        12.String substring(int begin); 获取该字符串中,以某个下标起始的子字符串(包含)
             System.out.println("abcdef".substring(2));                  //cdef
        13.String substring(int begin,int end);    获取该字符串中,以某个下标起始(包含)到
             某个下标结束的子字符串(不包含)
             System.out.println("avcdef".substring(2,4));                //cd
        14.String trim(): 去除字符串两边的空格
             System.out.println("   advc dsff   ".trim());
        15. //String toUpperCase(): 转大写
             //String toLowerCase(): 转小写
                 System.out.println("asd".toUpperCase());
        16.//static String valueOf(Object obj): 调用该对象的toString方法,如果为null,则不再
             调用toString,而是返回字符串null
                 String s = null;
             //打印一个引用类型的时候,会自动调用String的valueOf,所以会自动调用toString方法
                 System.out.println(s);
    6.注意
         String a = "a";
         String b = "b";
         String str = "ab";
         //字面量相加,在编译阶段就把 + 去掉了
         String d = "a" + "b";
         //true
         System.out.ptintln(d == str);
         //true
         System.out.println(d.equals(str));
         //变量相加,因为变量的值是可变的,运算之前没有办法确定变量的值,
             所以没办法优化只能转化为new的方式,重新创建并拼接字符串
         String c = a+b;
         String e = a+"b";
         //false
         System.out.println(c == str);
         //true
         System.out.println(c.equals(str));
         //上面相加因为变量的值无法去欸但那个,如果声明为常量,可以优化
2.StringBuffer 和 StringBuilder
     1.概述
         都是字符串缓冲区,可以做拼接操作
         区别:
             String:底层是char数组,定长,一旦创建不可更改,不适合做字符串拼接操作
             
             StringBuffer和StringBuilder:底层是char数组,变长,预先在内存中申请一块空间,
                 用来保存很多字符,如果空间不够会自动扩容
             默认容量为16,扩大容量(当前容量+1)*2,  16->34->70
             这俩区别:
                 StringBuffer线程安全,在多线程环境下,不会出现问题
                 StringBuilder非线程安全,在多线程环境下可能会出现问题
     
     2.基本使用
         创建一个对象
             StringBuilder sb = new StringBuilder();
             String[] arr = {"a","b","c"};
             for(int i = 0;i<arr.length;i++){
                 //append就是添加操作,做拼接操作,可以链式调用
                 sb.append(arr[i]).append(",");
             }
             //toString可以把StringBuilder转换为String类型
             String str = sb.toStrign();
             System.out.println(str);
    3.常用方法
         //反转
             sb.reberse();
         //获取已有元素个数
             System.out.println(sb.length());
         //当前容量(数组长度)
             System.out.println(sb.capacity());
         //toString可以把StringBuilder转换为String类型 
             String str = sb.toString();
3.包装类
     1.概述
         问:想要对基本类型进行更多操作怎么办?
         答:最方便的方式就是将其封装成对象,因为在对象描述中就可以定义更多的属性和行为
         对该基本数据类型进行操作我们不需要对基本类型进行封装,JDK已经为我们封装好了
        概念:
             1.装箱就是自动将基本数据类型转换为包装器类型
             2.拆箱就是自动将包装器类型转换为基本数据类型
             
             *char的封装类型为Character,int的封装类型为Integer,其他都是首字母大写
    2.使用
         //基本类型
             byte b1 = 12;
         //封装为包装类
             Byte b2 = new Byte(b1);
             m1(b2);
    3.Integer
         1.基本使用
             //最大值
                 System.out.println(Integer.MAX_VALUE);
             //创建对象
                 Integer i1 = new Integer(123);
             //传递字符串也可以,但必须是纯数字
                 Integer i2 = new Integer("123");
     
         2.相互转换(重要)
             //int->Integer
                 Integer i1 = new Integer(123);
                 i1 = Integer.valueOf(123);
             
             //Integer->int
                 int i2 = i1.intValue();
            //String->Integer
                 Integer i3 = new Integer("123");
                 i3 = Integer.valueOf("123");
            //Integer->String
                 String string = i3.toString();
            //int->String 
                 String string1 = 123+"";
            //String->int
             //重要 static int parseInt(String  str):把纯数字的字符串转换为int类型
                 int i4 = Integer.parseInt("123");
        3.常用方法
             //把数字以二进制的字符串形式,并返回
                 String s1 = Integer.toBinaryString(10);
             //同上,八进制
                 s1 = Integer.toOctalString(10);
             //同上,十六进制
                 s1 = Integer.toHexString(10);
                 System.out.println(s1);
         
         4.自动装箱与自动拆箱
             八种包装类都覆写了 toString 和 equals()方法
            Integer  i3 = 123;          //编译之后相当于 Integer i3 = Integer.valueOf(123);
             int i4 = i3;                //编译之后就等于 int i4 = i3.intValue();
             m1(i3);
             //1234为int型, 会先进行自动装箱为Integer类型,然后再发生多态转型为Object类型
             m1(1234);
        5.深入整型常量池
             Integer i1 = new Integer(10);
             Integer i2 = new Integer(10);
             System.out.println(i1 == i2);           //false 
             System.out.println(i1.equals(i2));      //true
             Integer i3 = Integer.valueOf(123);
             Integer i4 = Integer.valueOf(123);
             System.out.println(i3 == i4);           //true
             Integer i5 = 12;                        //编译后 Integer.valueOf(12);
             Integer i6 = 12;
             System.out.println(i5 == i6);           //true
             Integer i7 = 222;
             Integer i8 = 222;
             System.out.println(i7 == i8);           //false,因为整形常量池的方位在-128~127之间
             
             判断这个数值是否在-128~127之间,不在就new对象   p14页
        6.总结
             常量池就是提前准备好一些对象,当我们要保存数据的时候,发现已经创建好了,就直接拿走,不需要重新创建
            总结:
                 当我们通过new Integer(xx)创建对象的时候,不管值是多少,==永远是false
                当我们使用Integer i1 = xxx;这种方式的时候,编译之后会转换为Integer.valueOf();这种方式会经过整形常量池
                 假如xxx这个值在-128到127之间,则不需要new对象,而是使用常量池中以创建的对象
                 否则不在范围内,则还是等于 new Integer(xxx)这种方式
因此 Integer i1 = xxx; i2 = xxx; 如果xxx在-128~127之间,则i1==i2 是true
如果通过构造方法直接创建对象是不经过常量池的
4.System
     1.概述
         System类提供的public static long currentTimeMillis()用来返回当前时 间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
         此方法适于计算时间差。
        1.System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。 该类位于java.lang包。
         2.由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实 例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便 的进行调用。
         3.成员变量
         4.System类内部包含in、out和err三个成员变量,分别代表标准输入流
         (键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
         5.成员方法
         6.native long currentTimeMillis():
         该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时
         间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
         7.void exit(int status):
         该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表
         异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
    2.常用方法
         //标准输出->打印到控制台
             System.out.println(123);
         //表示错误,以红色字体展示到控制台
             System.err.println(123);
         //in表示标准输入,接收控制台输入的信息
             new Scanner(System.in);
         //获取时间原点到当前时间的毫秒数(1970.1.1 8:0:0)
             long startTime = System.currentTimeMillis();
             System.out.println("正在执行");
             long endTime = System.currentTimeMillis();
             System.out.println("耗时:" + (endTime-startTime));
         //退出JVM虚拟机,0表示正常关闭,1表示异常关闭,一般用于图形界面关闭窗口
             System.exit(0);
         //执行不到
             System.out.println("================");
5.Date
     1.概述
         获取时间和时间操作
    2.构造方法
         //获取当前系统时间
             Date d1 = new Date();
         //传入毫秒数,获取时间原点到指定毫秒数的时间
             Date d2 = new Date(1000);
         //Fri Jan 14 16:15:57 CST 2022
             System.out.println(d1);
    3.常用方法
         //获取指定时间的毫秒数
             System.out.println(d1.getTime());
         //把时间转换为 字符串类型
             System.out.println(d1.toString());
    4.格式化
         年   y
         月   M
         日   d 
         时   H 
         分   m 
         秒   s 
         毫秒 S 
        //创建时间格式化对象
         SimpleDateFormat sdf new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");
         //格式化返回字符串
             String string = sdf.format(d1);
             System.out.println(string);
        //时间格式的字符串转换为Date对象
             String strDate = "2022/01/14 16:21:36";
         //格式化对象的时间格式,要和字符串的格式一致
             sdf = new SimpleDateFormat(yyyy/MM/dd HH:mm:ss);
         //转换返回Date对象
             Date date = sdf.parse(strDate);
             System.out.println(date);
    5.Calendar
         // 获取当前日历
         Calendar c = Calendar.getInstance();
         // 获取当前是本周第几天 , 周日是第一天
         System.out.println(c.get(Calendar.DAY_OF_WEEK));
         // 年
         System.out.println(c.get(Calendar.YEAR));
         // 月 , 0 是1月 , 11是12月, 所以 结果 +1 才是正确的
         System.out.println(c.get(Calendar.MONTH)+1);
         // 日 获取今天是当前月中第几天
         System.out.println(c.get(Calendar.DAY_OF_MONTH));
         // 时  12小时制
         System.out.println(c.get(Calendar.HOUR));
         // 24小时制
         System.out.println(c.get(Calendar.HOUR_OF_DAY));
         // 分
         System.out.println(c.get(Calendar.MINUTE));
         // 秒
         System.out.println(c.get(Calendar.SECOND));
6.Random
     1.概述
         随机数从0开始
     
     2.使用
         // 创建随机数生成器
         Random r = new Random();
         // 在int范围内 随机生成一个数字
         int i = r.nextInt();
         System.out.println(i);
         
         // 传入10  说明要在 0~9之间生成
         i = r.nextInt(10);
         System.out.println(i);
         
         // 生成 10~22  
         // nextInt(最大值 - 最小值 + 1) + 最小值
         int result = r.nextInt(100 - 20 + 1) + 20;
         System.out.println(result);
    
    多线程:并发:同时出发,并行:同时进行
  










