String类:
    String类位于java.lang包中,被final所修饰,String类是不可改变类,所有字符串常量都在常量池中,常量池在方法区中。
    它代表字符串,Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
    也就是说String str = "abc";不需要通过new就产生了一个对象
    String类最大的特性:一旦被初始化就不可被改变。
        例:String str = "abc";//创建了一个对象
            str = "bbc";//这里又创建了一个对象
            是str指向的地址变了,abc对象的内容并没有变
    String类重写了equals()方法,该方法判断字符串是否相同
        演示说明:

package com.itheima.string;
            public class StringTest {
                public static void main(String[] args) {
                    String str1 = "abc";
                    String str2 = new String("abc");
                    String str3 = "abc";
                    //str1在内存中有一个对象,str2在内存中有两个对象
                    System.out.println(str1 == str2);//false
                    System.out.println(str1.equals(str2));//true
                    System.out.println(str1 == str3);//true
                    //为什么str1 == str3,返回true呢?
                    //字符串这种特殊类型的数据存放在常量池中,
                    //str3创建对象的时候会在常量池中去找,如果有就不再独立开辟空间
                    //str1和str3指向了同一个对象
                }
            }


    String类的常用方法:
         int length() 返回此字符串的长度。
         char charAt(int index) 返回指定索引处的char值。下标从0开始,到length()-1结束,
            如果访问到非法下标,会引出StringIndexOutOfBoundsException异常
         int indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引。
         int indexOf(int ch, int fromIndex) 返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
         int indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引。
         int indexOf(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
         int lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出现处的索引。
         int lastIndexOf(int ch, int fromIndex) 返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
         int lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引。
         int lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
         以上几个indexOf()或lastIndexOf()方法,在查询不到的时候,返回-1
             演示:
                String str = "hahexihahexi";
                System.out.println(str.charAt(0));//h
                System.out.println(str.indexOf('s'));//-1
                System.out.println(str.indexOf("hexi"));//2
                System.out.println(str.lastIndexOf('h', 9));//8
         boolean contains(String str) 当且仅当此字符串包含指定的 char 值序列时,返回 true。
         boolean isEmpty() 当且仅当 length() 为 0 时返回 true。JDK1.6之后出新的新方法
         boolean startsWith(String prefix) 测试此字符串是否以指定的前缀开始。
         boolean startsWith(String prefix, int toffset) 测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
         boolean endsWith(String suffix) 测试此字符串是否以指定的后缀结束。
         boolean equalsIgnoreCase(String anotherString) 将此String与另一个String比较,不考虑大小写。
            演示:
                String str = "hehexixihaha";
                System.out.println(str.startsWith("xixi"));//false
                System.out.println(str.endsWith("haha"));//true
                System.out.println(str.startsWith("xixi", 4));//true
                System.out.println(str.contains("hehe"));//true
                System.out.println("HEHExixiHaHA".equalsIgnoreCase(str));//true
        String replace(char/String oldChar, char/String newChar)
            返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
            演示:
                        String str1 = "hahahexihei";
                        String str2 = str1.replace("xi", "he");
                        System.out.println(str1);//hahahexihei
                        System.out.println(str2);//hahahehehei
                    注意:str1并没有改变,因为字符串一旦初始化不可改变,str和str2是两个不同的对象
        String[] split(String regex) 切割
            演示:
                String str = "hehe,xixi,haha,heihei";
                String[] arr = str.split(",");
                for(String item : arr)
                    System.out.println(item);
            运行结果:
                hehe
                xixi
                haha
                heihei
        String substring(int beginIndex) 从指定位置开始切割,一直到字符串末尾
        String substring(int beginIndex, int endIndex) 从beginIndex(下标从0开始)切割,到endIndex(下标从1开始)结束
            演示:
                String str1 = "中关村,黑马训练营";
                String str2 = str1.substring(4);
                System.out.println(str2);//黑马训练营
                String str3 = str1.substring(4, 9);
                System.out.println(str3);//黑马训练营
        String toLowerCase() 将字符串转换成小写形式
        String toUpperCase() 将字符串转换成大写形式
        String trim() 取出字符串前端和后端的空格,不会取出中间的空格
        int compareTo(String anotherString) 按字典顺序比较两个字符串。
            如果str1>str2,返回正数,如果str1<str2返回负数,如果相等返回0
            演示:
                String str1 = "abc";
                String str2 = "ABC";
                System.out.println(str2.compareTo(str1));//-32
                System.out.println(str1.compareTo(str2));//32
                System.out.println(str1.toUpperCase().compareTo(str2));//0
        static String valueOf(多种参数类型 变量名):这个功能很强大!!!把指定类型的参数转换成字符串
        String concat(String str) 将指定字符串连接到此字符串的结尾。
            演示:
                String str = "haha";
                String str2 = "xixi";
                String str3 = str2.concat(str);
                str.concat("hehe");
                System.out.println(str);//haha
                System.out.println(str3);//xixihaha
            注意:str的值并没有改变,原因和上述一样!!!
    将字符数组转成字符串:
        构造方法:
            String(char[] value)
            String(char[] value, int offset, int count) 将字符数组中的一部分转成字符串,offset是开始位置,count是个数
            演示:
                char[] chs = {'黑','马','程','序', '员'};
                String str1 = new String(chs);
                System.out.println(str1);//黑马程序员
                String str2 = new String(chs, 2, 3);
                System.out.println(str2);//程序员
        静态方法:
            static String copyValueOf(char[] data)
            static String copyValueOf(char[] data, int offset, int count) 将字符数组中的一部分转成字符串,offset是开始位置,count是个数
            演示:
                String str3 = String.copyValueOf(chs);
                System.out.println(str3);//黑马程序员
                String str4 = String.copyValueOf(chs, 2, 3);
                System.out.println(str4);//程序员
    将字符串转成字符数组:
        char[] toCharArray()
   
    将字节数组转成字符串:
        构造方法:
            String(char[] value)
            String(char[] value, int offset, int count) 将字节数组中的一部分转成字符串,offset是开始位置,count是个数
            演示:
                byte[] bys = {65,66,97,98};
                String str1 = new String(bys);
                System.out.println(str1);//ABab
                String str2 = new String(bys, 2, 2);
                System.out.println(str2);//ab
    将字符串转成字节数组:
        byte[] getBytes() 
StringBuffer:
    StringBuffer是一个容器,而且长度是可变的,可以直接操作多个数据类型,最终通过toString()方法变成字符串。
    线程安全
    常用方法:
        StringBuffer apend():将任意类型追加到序列中,但是byte和short除外。
        StringBuffer insert():将任意类型插入到指定位置,byte和short除外。
        演示:
            StringBuffer sb = new StringBuffer();
            sb.append(false);
            sb.append(5);
            sb.insert(0, 'O');
            System.out.println(sb.toString());//Ofalse5
        StringBuffer delete(int start, int end) 移除此序列的子字符串中的字符。
        StringBuffer deleteCharAt(int index) 移除此序列指定位置的 char。
        演示:
            StringBuffer sb = new StringBuffer();
            sb.append("xiwhahehei");
            sb.deleteCharAt(2);
            System.out.println(sb.toString());//xihahehei
            sb.delete(2, sb.length());
            System.out.println(sb.toString());//xi
        StringBuffer replace(int start, int end, String str) 使用给定String中的字符替换此序列的子字符串中的字符。
        void setCharAt(int index, char ch) 将给定索引处的字符设置为 ch。
        演示:
            StringBuffer sb = new StringBuffer();
            sb.append("黑马程序员");
            sb.replace(2, sb.length(), "训炼营");
            System.out.println(sb.toString());//黑马训炼营
            sb.setCharAt(3, '练');
            System.out.println(sb.toString());//黑马训练营
        StringBuffer reverse() 将此字符序列用其反转形式取代。
StringBuilder:
    JDK1.5版本出现,StringBuilder和StringBuffer基本相似,区别在于:
    StringBuffer线程安全,StringBuiler线程不安全,但效率高
    单线程用StringBuilder,多线程用StringBuffer
基本数据类型对象包装类:
        byte      Byte
        short     Short
        int       Integer
        long      Long
        boolean      Boolean
        float      Float
        double      Double
        char      Charactor
    作用:用于基本数据类型和字符串类型之间的转换
    基本数据类型转字符串:
        基本数据类+"";
        基本数据类型.toString(基本数据类型值);
            如:Integer.toString(34);
    字符串转基本数据类型:
        xxx 变量 = Xxx.parseXx(String str);
        例如:int a = Integer.parseInt("123");//必须传入数字格式的字符串
              double d = Double.parseDouble("23.56");
    JDK1.5之后的新特性:自动装箱
        如:Integer i = new Integer(5); --> Integer i = 5;
            i = i/*i.intValue()*/ + 2;//自动拆箱,参与运算
            注意:判断null,不为null时,才能参与运算
    案例说明:
        Integer m = 128;
        Integer n = 128;
        System.out.println(m == n);//false
        Integer a = 127;
        Integer b = 127;
        System.out.println(a == b);//true
        解析:因为a和b指向了同一个Integer对象,当数值在byte范围内时,对于新特性,不会开辟新的空间
              如果数值超出了byte范围,就会开辟新空间
Scanner类:
    使用Scanner类可以用来获取输入。通常输入源是控制台,也就是说用它可以获取键盘输入!
    常用方法:
        构造方法:
            Scanner sc = new Scanner(Sytem.in);
        获取输入的方法:
            String next():获取一个单词;
            String nextLine():获取一行输入;
            int nextInt():获取一个整数。
            double nextDouble():获取一个小数
    特点:每次输入都需要给出回车,表示输入结束。但回车也一个字符串,
         先nextInt(),获取一个整数,再nextLine()获取一行字符串。就会出问题
         因为nextInt()时,输入结束时会输入一个回车符,这个回车符会被nextLine()获取,所以会出问题。
    解决方案:让两个输入使用不同的Scanner对象
Random类
    获取生成伪随机数。
    Random r = new Random();
    int n = nextInt(100);//生成的一个随机数,范围是0~100,但包含0,却不包含100。有头没尾。
Math类
    完全静态方法类
        因为没有实例方法,所以就不需要创建本类实例;
        因为不需要实例,也就不需要有构造器;
        因为怕有默认构造器,所以需要有private构造器;
        这样的类好像也不需要有子类,所以Math是final类。

    方法介绍
        static double abs(double):返回参数的绝对值
        static double max(double d1, double d2):返回参数d1和d2中的大者。
        static double min(double d1, double d2) :返回参数d1和d2中的小者。
        static double sqrt(double):求参数的平方根
        static double cbrt(double):求参数的立方根
        static double pow(double a, double b):求a的b次方
        static double ceil(double):返回大于等于参数的最小整数。
        static double floor(double):返回小于等于参数的最大整数。
        static long round(double):四舍五入
        static int round(float):四舍五入
        static double random():返回一个0~1之间的随机数。     
Calendar类:
    Java提供了Calendar类来更好的处理日期和时间,Calendar类是一个抽象类,
    所以不能使用构造器来创建对象,但它提供了几个静态getInstance()方法来获取对象。
        static Calendar getInstance() 使用默认时区和语言环境获得一个日历。
            示例:Calendar cal = Calendar.getInstance();
    常用方法:
        Date getTime() 返回一个表示此Calendar时间值(从历元至现在的毫秒偏移量)的Date对象。
            示例:Calendar cal = Calendar.getTime();
                  Date d = cal.getTime();
        void add(int field, int amount)
            根据日历的规则,为给定的日历字段添加或减去指定的时间量。
        void roll(int field, int amount)
            与add()方法类似,区别在于加上amount后超过了该字段的最大范围,不会向上一个字段进位
        int get(int field) 返回指定日期的字段值
        int getActualMaximum(int field) 给定此Calendar的时间值,返回指定日历字段可能拥有的最大值。
        int getActualMinimum(int field) 给定此Calendar的时间值,返回指定日历字段可能拥有的最小值。
        void set(int field, int value) 将给定的日历字段设置为给定值
        void set(int year, int month, int date) 设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值。
        void set(int year, int month, int date, int hourOfDay, int minute)
            设置Calendar对象的年、月、日、时、分、秒6个字段值
        注意:上述方法包含int类型的field参数,是Calendar类的静态Field,如Calendar.YEAR。
              月份是从0开始。
        示例:
            Calendar c = Calendar.getInstance();
            //取出年份
            System.out.print("今年是:" + c.get(Calendar.YEAR) + "年, ");
            //取出月份
            System.out.print((c.get(Calendar.MONTH) + 1) + "月, ");
            //取出日
            System.out.println(c.get(Calendar.DATE) + "号");
            System.out.println("今天是一周的第" + c.get(Calendar.DAY_OF_WEEK) + "天");
            c.add(Calendar.YEAR, -2);
            c.add(Calendar.DATE, 13);
            System.out.println(c.getTime());
            //32号超出了12月的范围,会导致月份增加,变成13,对应的是2月
            //13超出了月份字段范围,所以会导致年的值增加,变成2013
            c.set(2012, 12, 32, 12, 30);
            System.out.println(c.getTime());
            运行结果:
                今年是:2013年, 3月, 19号
                今天是一周的第3天
                Fri Apr 01 11:16:02 CST 2011
                Fri Feb 01 12:30:48 CST 2013//2013年-2月-1号23:30:02
            通过结果可以看出,add()和set()设置的时间值超出了某时间字段的范围,会自动增加
    add()和roll()的区别:
        add():
            1:当修改的字段超出了它允许的范围时,会发生进位,上一级字段增加
            演示:
                Calendar c = Calendar.getInstance();
                c.set(2012,7,5,0,0,0);//2012-8-5
                c.add(Calendar.MONTH, 6);//2013-2-5
            2:当修改的字段修改后的下一级字段也超出了允许的范围,
              那么下一级字段会变成该字段所属范围的最大值,该字段对应的上一级字段不会增加
            演示:
                Calendar c = Calendar.getInstance();
                c.set(2012,7,31,0,0,0);//2012-8-31
                c.add(Calendar.MONTH, 6);//是2013-2-28,不是2013-3-2
        roll():
            1:当被修改的字段超出它允许的范围时,上一级字段不会增大,被修改的字段会发生变化
            演示:
                Calendar c = Calendar.getInstance();
                c.set(2012, 7, 2);//2012-8-2
                c.roll(Calendar.MONTH, 6);//2012-2-2
            2:当修改的字段修改后的下一级字段也超出了允许的范围,与add()2类似
            演示:
                Calendar c = Calendar.getInstance();
                c.set(2012, 7, 31);//2012-8-31
                c.roll(Calendar.MONTH, 6);//2012-2-29
    设置Calendar的容错性:
        Calendar提供了一个setLenient(boolean lenient)方法,用于设置它的容错性,默认情况下为true,
        当通过setLenient(false),就可以让它对set()方法中的参数进行严格的检查
        演示:
            Calendar c = Calendar.getInstance();
            c.set(2012, 12,20);
            System.out.println(c.getTime());//1处,这里没问题
            //设为false,对时间设置参数进行严格检查
            c.setLenient(false);
            c.set(2012, 12,20);
            System.out.println(c.getTime());//2处,引发IllegalArgumentException异常
        注意:如果把2处的输出语句注释掉,不会引发异常,因为set()方法的延迟修改
    set()方法的延迟修改:
        当通过set()方法,设置时间参数的时候,该Calendar代表的时间不会立即修改,
        知道下次调用get(),getTime(),getTimeInMillis(),add()或roll()时,才会设置成功。
        这就是set()方法的延迟修改
        好处:多次调用set()方法不会触发多次不必要的计算
    打印日历演示:

package com.itheima;
        /*
         * 打印日历,用号数+*号代表今天
         * */
        import java.util.Calendar;
        public class PrintCalendar {
            public static void main(String[] args) {
                printCalendar(2);
            }
            public static void printCalendar(int month)
            {
                //创建Calendar对象
                Calendar cal = Calendar.getInstance();
                //把当前月份设置成要打印的月份
                cal.set(Calendar.MONTH, month);
                //获取当天月份一共有多少天
                int max = cal.getActualMaximum(Calendar.DATE);
                //获取今天是多少号
                int today = cal.get(Calendar.DATE);
                System.out.println("  日          一          二          三         四          五          六");
                int w = cal.get(Calendar.DAY_OF_WEEK);
                for(int i = Calendar.SUNDAY; i < w; i++) {
                    System.out.print("          ");
                }
                for(int i = 1; i <= max; i++)
                {
                    //把当前号设置成i号
                    cal.set(Calendar.DATE, i);
                    if(today == i)
                        System.out.print(i + "* ");
                    else{
                        if(i < 10)
                            System.out.print(" " + i + "  ");
                        else
                            System.out.print(i + "  ");
                    }
                    //打印到星期六换行,星期六是一周中的第7天
                    if(cal.get(Calendar.DAY_OF_WEEK) == 7)
                    {
                        System.out.println();
                    }
                }
            }
        }