包装类
包装类的分类
黄色父类都是Object

包装类和基本数据的转换
jdk5 前,是手动装箱和拆箱
jdk5 后,就可以自动装箱和自动拆箱
public class Integer01 {public static void main(String[] args) {//演示 int <--> Integer 的装箱和拆箱//jdk5 前是手动装箱和拆箱//手动装箱 int->Integerint n1 = 100;Integer integer = new Integer(n1);Integer integer1 = Integer.valueOf(n1);//手动拆箱//Integer -> intint i = integer.intValue();//jdk5 后,就可以自动装箱和自动拆箱int n2 = 200;//自动装箱 int->IntegerInteger integer2 = n2; //底层使用的是 Integer.valueOf(n2)//自动拆箱 Integer->intint n3 = integer2; //底层仍然使用的是 intValue()方法}}
包装类型和 String 类型的相互转换 Wrapper VS String
public class WrapperVSString {public static void main(String[] args) {//包装类(Integer)->StringInteger i = 100;//自动装箱//方式 1String str1 = i + "";//方式 2String str2 = i.toString();//方式 3String str3 = String.valueOf(i);//String -> 包装类(Integer)String str4 = "12345";Integer i2 = Integer.parseInt(str4);//使用到自动装箱Integer i3 = new Integer(str4);//构造器System.out.println("ok~~");}}
Integer 类和 Character 类的常用方法
public class WrapperMethod {public static void main(String[] args) {System.out.println(Integer.MIN_VALUE); //返回最小值System.out.println(Integer.MAX_VALUE);//返回最大值System.out.println(Character.isDigit('a'));//判断是不是数字System.out.println(Character.isLetter('a'));//判断是不是字母System.out.println(Character.isUpperCase('a'));//判断是不是大写System.out.println(Character.isLowerCase('a'));//判断是不是小写System.out.println(Character.isWhitespace('a'));//判断是不是空格System.out.println(Character.toUpperCase('a'));//转成大写System.out.println(Character.toLowerCase('A'));//转成小写}}
课堂测试题(很重要)

三目运算符是一个整体如果有double,会把精度调为0.0
if else 则不是
Integer 类面试题 1 WrapperExercise02.java
public class WrapperExercise02 {public static void main(String[] args) {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j); //False//所以,这里主要是看范围 -128 ~ 127 就是直接返回/*public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}*/Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码Integer n = 1;//底层 Integer.valueOf(1);System.out.println(m == n); //T//所以,这里主要是看范围 -128 ~ 127 就是直接返回//,否则,就 new Integer(xx);Integer x = 128;//底层 Integer.valueOf(1);Integer y = 128;//底层 Integer.valueOf(1);System.out.println(x == y);//False}}
解读:
如果 i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回
如果不在 -128~127,就直接 new Integer(i)
public class WrapperExercise03 {public static void main(String[] args) {//示例一Integer i1 = new Integer(127);Integer i2 = new Integer(127);System.out.println(i1 == i2);//F//示例二Integer i3 = new Integer(128);Integer i4 = new Integer(128);System.out.println(i3 == i4);//F//示例三Integer i5 = 127;//底层 Integer.valueOf(127)Integer i6 = 127;//-128~127System.out.println(i5 == i6); //T//示例四Integer i7 = 128;Integer i8 = 128;System.out.println(i7 == i8);//F//示例五Integer i9 = 127; //Integer.valueOf(127)Integer i10 = new Integer(127);System.out.println(i9 == i10);//F//示例六Integer i11=127;int i12=127;//只有有基本数据类型,判断的是//值是否相同System.out.println(i11==i12); //T//示例七Integer i13=128;int i14=128;System.out.println(i13==i14);//T}}
第一代日期类
Date : 精确到毫秒,代表特定的瞬间
SimpleDateFormat : 格式的解析日期的类
SimpleDateFormat : 格式化的解析日期的具体类
他允许进行格式化(日期 -> 文本),解析(文本 -> 日期)和规范化
Date
获取当前系统时间
这里的 Date 类是在 java.util 包
默认输出的日期格式是国外的方式, 因此通常需要对格式进行转换
Date d1 = new Date(); //获取当前系统时间System.out.println("当前日期=" + d1);Date d2 = new Date(9234567); //通过指定毫秒数得到时间System.out.println("d2=" + d2); //获取某个时间对应的毫秒数

创建 SimpleDateFormat 对象,可以指定相应的格式
这里的格式使用的字母是规定好,不能乱写
format:将日期转换成指定格式的字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日 hh:mm:ss E");String format = sdf.format(d1); // format:将日期转换成指定格式的字符串System.out.println("当前日期=" + format);
可以把一个格式化的 String 转成对应的 Date
得到 Date 仍然在输出时,还是按照国外的形式,如果希望指定格式输出,需要转换
在把 String -> Date , 使用的 sdf 格式需要和你给的 String 的格式一样,否则会抛出转换异常
parse():将指定格式字符串转换成日期
String s = "1996 年 01 月 01 日 10:20:30 星期一";Date parse = sdf.parse(s);System.out.println("parse=" + sdf.format(parse));
第二代日期类
calendar(日历)类
Calendar 是一个抽象类, 并且构造器是 private
可以通过 getInstance() 来获取实例
提供大量的方法和字段提供给程序员
Calendar没有提供对应的格式化的类,因此需要程序员自己组合来输出(灵活)
如果我们需要按照 24小时进制来获取时间
Calendar.HOUR ==改成=> Calendar.HOUR_OF_DAY
Calendar c = Calendar.getInstance(); //创建日历类对象//比较简单,自由System.out.println("c=" + c);//2.获取日历对象的某个日历字段System.out.println("年:" + c.get(Calendar.YEAR));// 这里为什么要 + 1, 因为Calendar 返回月时候,是按照 0 开始编号System.out.println("月:" + (c.get(Calendar.MONTH) + 1));System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));System.out.println("小时:" + c.get(Calendar.HOUR));System.out.println("分钟:" + c.get(Calendar.MINUTE));System.out.println("秒:" + c.get(Calendar.SECOND));//Calender 没有专门的格式化方法,所以需要程序员自己来组合显示System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH) +" " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) );
使用get()方法调用属性
Calendar 返回月时候,是按照 0 开始编号
第三代日期类
LocalDate(日期/年月日),LocalTime(时间/时分秒),LocalDateTime(日期时间/年月日时分秒) JDK8加入
LocalDate只包含日期,可以获取日期字段
LocalTime只包含时间,可以获取时间字段
LocalDateTime包含日期+时间,可以获取日期和时间字段
//1. 使用 now() 返回表示当前日期时间的 对象LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()System.out.println(ldt);//2. 使用 DateTimeFormatter 对象来进行格式化// 创建 DateTimeFormatter 对象DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String format = dateTimeFormatter.format(ldt);System.out.println("格式化的日期=" + format);System.out.println("年=" + ldt.getYear());System.out.println("月=" + ldt.getMonth());System.out.println("月=" + ldt.getMonthValue());System.out.println("日=" + ldt.getDayOfMonth());System.out.println("时=" + ldt.getHour());System.out.println("分=" + ldt.getMinute());System.out.println("秒=" + ldt.getSecond());LocalDate now = LocalDate.now(); //可以获取年月日LocalTime now2 = LocalTime.now();//获取到时分秒//提供 plus 和 minus 方法可以对当前时间进行加或者减//看看 890 天后,是什么时候 把 年月日-时分秒LocalDateTime localDateTime = ldt.plusDays(890);System.out.println("890 天后=" + dateTimeFormatter.format(localDateTime));//看看在 3456 分钟前是什么时候,把 年月日-时分秒输出LocalDateTime localDateTime2 = ldt.minusMinutes(3456);System.out.println("3456 分钟前 日期=" + dateTimeFormatter.format(localDateTime2));
- 使用 now() 返回表示当前日期时间的 对象
LocalDateTime ldt = LocalDateTime.now();
- 使用 DateTimeFormatter 对象来进行格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String format = dateTimeFormatter.format(ldt);
Instant 时间戳
- 通过 静态方法 now() 获取表示当前时间戳的对象
//1.通过 静态方法 now() 获取表示当前时间戳的对象Instant now = Instant.now();System.out.println(now);
- 通过 from 可以把 Instant 转成 Date
//2. 通过 from 可以把 Instant 转成 DateDate date = Date.from(now);
- 通过 date 的 toInstant() 可以把 date 转成 Instant 对象
//3. 通过 date 的 toInstant() 可以把 date 转成 Instant 对象Instant instant = date.toInstant();
字符串的特性
- String是一个final类,代表不可变的字符序列
- 字符串是不可变.一个字符串对象一旦被分配,内容是不可变的.
以下语句创建了几个对象:String s1 = "hello";s1 = "haha";两个
以下语句创建了几个对象:String s1 = "hello"+"abc";只有一个
编译器会做一个优化,判断创建的常量池对象,是否有引用指向
String a = “hello” + “abc”; —-> String a = “helloabc”;
以下语句创建了几个对象:String a = "hello";String b = "abc";String c = a + b;
底层:
先创建一个
StringBuilder sb = StringBuilder()执行
sn.append("hello")
现版本:indexCoder = prepend(indexCoder, buf, s2);执行
sb.append("abc")
现版本:indexCoder = prepend(indexCoder, buf, s1);执行
String c = sb.toString()最后是 c 指向堆中的sb对象(String) value[] —> 池中的 “helloabc”
因为toString方法的底层是static String simpleConcat(Object first, Object second) {String s1 = stringOf(first);String s2 = stringOf(second);// start "mixing" in length and coder or arguments, order is not// importantlong indexCoder = mix(initialCoder(), s2);indexCoder = mix(indexCoder, s1);byte[] buf = newArray(indexCoder);// prepend each argument in reverse order, since we prepending// from the end of the byte arrayindexCoder = prepend(indexCoder, buf, s2);indexCoder = prepend(indexCoder, buf, s1);return newString(buf, indexCoder);}
重要规则:如果是两个常量相加,看的是池。String c1 = a + b; 变量相加是在堆中
Arrays
1. toString
返回数组的字符串形式
Arrays.toString(arr)
2. sort排序(自然排序和制定排序)
- 可以直接使用冒泡排序 , 也可以直接使用 Arrays 提供的 sort 方法排序
- 因为数组是引用类型,所以通过 sort 排序后,会直接影响到 实参 arr
- sort 重载的,也可以通过传入一个接口 Comparator 实现定制排序
- 调用 定制排序 时,传入两个参数 (1) 排序的数组 arr (2) 实现了 Comparator 接口的匿名内部类 , 要求实现 compare 方法
- 先演示效果,再解释
- 这里体现了接口编程的方式 , 看看源码,就明白
源码分析:
(1) Arrays.sort(arr, new Comparator()
(2) 最终到 TimSort 类的 private static void binarySort(T[] a, int lo, int hi, int start, Comparator c)()
(3) 执行到 binarySort 方法的代码, 会根据动态绑定机制 c.compare()执行我们传入的 // 匿名内部类的 compare ()
if (c.compare(a[runHi++], a[lo]) < 0) { // Descendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)runHi++;reverseRange(a, lo, runHi);} else { // Ascendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)runHi++;}return runHi - lo;}
(4)
new Comparator() {@Overridepublic int compare(Object o1, Object o2) {Integer i1 = (Integer) o1;Integer i2 = (Integer) o2;return i2 - i1;}}
(5) public int compare(Object o1, Object o2) 返回的值>0 还是 <0 // 会影响整个排序结果, 这就充分体现了 接口编程+动态绑定+匿名内部类的综合使用 将来的底层框架和源码的使用方式,会非常常见
Arrays.sort(arr); // 默认排序方法 //定制排序
Arrays.sort(arr, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {Integer i1 = (Integer) o1;Integer i2 = (Integer) o2;return i2 - i1;}});System.out.println("===排序后===");System.out.println(Arrays.toString(arr));
3.接口+动态排序实现(一天看一遍)
public class ArraysSortCustom {public static void main(String[] args) {int[] arr = {1, -1, 8, 0, 20};//bubble01(arr);bubble02(arr, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {int i1 = (Integer) o1;int i2 = (Integer) o2;return i2 - i1;// return i2 - i1;}});System.out.println("==定制排序后的情况==");System.out.println(Arrays.toString(arr));}//结合冒泡 + 定制public static void bubble02(int[] arr, Comparator c) {int temp = 0;for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {//数组排序由 c.compare(arr[j], arr[j + 1])返回的值决定if (c.compare(arr[j], arr[j + 1]) > 0) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}}
4.binarySearch通过二分搜索法查找,要求必须排好序
int index = Arrays.binarySearch(arr,3);
- 使用 binarySearch 二叉查找
- 要求该数组是有序的. 如果该数组是无序的,不能使用 binarySearch
- 如果数组中不存在该元素,就返回 return -(low + 1); // key not found.
5. copyOf 数组元素的复制
- 从 arr 数组中,拷贝 arr.length 个元素到 newArr 数组中
- 如果拷贝的长度 > arr.length 就在新数组的后面 增加 null
- 如果拷贝长度 < 0 就抛出异常 NegativeArraySizeException
- 该方法的底层使用的是 System.arraycopy()
BigInteger和BigDecimal类
应用场景:
BigInteger适合保存比较大的整形
BigDecimal适合保存精度更高的浮点型(小数)
当我们编程中,需要处理很大的整数,long 不够用 可以使用 BigInteger 的类来搞定BigInteger bigInteger = new BigInteger("23788888899999999999999999999");BigInteger bigInteger2 = newBigInteger("10099999999999999999999999999999999999999999999999999999999999999999999999999999999");System.out.println(bigInteger);
当我们需要保存一个精度很高的数时,double 不够用 可以使用 BigDecimal
double d = 1999.11111111111999999999999977788d;// System.out.println(d);BigDecimal bigDecimal = new BigDecimal("1999.11");BigDecimal bigDecimal2 = new BigDecimal("3");System.out.println(bigDecimal);
BigInteger运算
- 在对 BigInteger 进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * /
- 可以创建一个 要操作的 BigInteger 然后进行相应操作
BigInteger add = bigInteger.add(bigInteger2);System.out.println(add);//加BigInteger subtract = bigInteger.subtract(bigInteger2);System.out.println(subtract);//减BigInteger multiply = bigInteger.multiply(bigInteger2);System.out.println(multiply);//乘BigInteger divide = bigInteger.divide(bigInteger2);System.out.println(divide);//除
BigDecimal运算
- 如果对 BigDecimal 进行运算,比如加减乘除,需要使用对应的方法
- 创建一个需要操作的 BigDecimal 然后调用相应的方法即可
System.out.println(bigDecimal.add(bigDecimal2));System.out.println(bigDecimal.subtract(bigDecimal2));System.out.println(bigDecimal.multiply(bigDecimal2));System.out.println(bigDecimal.divide(bigDecimal2));//可能抛出异常 ArithmeticException//在调用 divide 方法时,指定精度即可. BigDecimal.ROUND_CEILING//如果有无限循环小数,就会保留 分子 的精度System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));
math类
public class MathMethod {public static void main(String[] args) {//看看 Math 常用的方法(静态方法)//1.abs 绝对值int abs = Math.abs(-9);System.out.println(abs);//9//2.pow 求幂double pow = Math.pow(2, 4);//2 的 4 次方System.out.println(pow);//16//3.ceil 向上取整,返回>=该参数的最小整数(转成 double);double ceil = Math.ceil(3.9);System.out.println(ceil);//4.0//4.floor 向下取整,返回<=该参数的最大整数(转成 double)double floor = Math.floor(4.001);System.out.println(floor);//4.0//5.round 四舍五入 Math.floor(该参数+0.5)long round = Math.round(5.51);System.out.println(round);//6//6.sqrt 求开方double sqrt = Math.sqrt(9.0);System.out.println(sqrt);//3.0//7.random 求随机数// random 返回的是 0 <= x < 1 之间的一个随机小数// 思考:请写出获取 a-b 之间的一个随机整数,a,b 均为整数 ,比如 a = 2, b=7// 即返回一个数 x 2 <= x <= 7// 老韩解读 Math.random() * (b-a) 返回的就是 0 <= 数 <= b-a// (1) (int)(a) <= x <= (int)(a + Math.random() * (b-a +1) )// (2) 使用具体的数给小伙伴介绍 a = 2 b = 7// (int)(a + Math.random() * (b-a +1) ) = (int)( 2 + Math.random()*6)// Math.random()*6 返回的是 0 <= x < 6 小数// 2 + Math.random()*6 返回的就是 2<= x < 8 小数// (int)(2 + Math.random()*6) = 2 <= x <= 7// (3) 公式就是 (int)(a + Math.random() * (b-a +1) )for(int i = 0; i < 100; i++) {System.out.println((int)(2 + Math.random() * (7 - 2 + 1)));}//max , min 返回最大值和最小值int min = Math.min(1, 9);int max = Math.max(45, 90);System.out.println("min=" + min);System.out.println("max=" + max);}}
reserve方法
将字符串中指定部分翻转
String str = "abcdef";System.out.println("===交换前===");System.out.println(str);try {str = reverse(str, 1, 4);} catch (Exception e) {System.out.println(e.getMessage());return;}System.out.println("===交换后===");System.out.println(str);
String VS StringBuffer VS StringBuilder
StringBuilder 和 StringBuffer 非常相似,均代表可变的字符序列,而且方法也一样
String : 不可变字符序列,效率低.但是复用率高
StringBuffer : 可变字符序列,效率较发哦(增删),线程安全,看源码
StringBuilder : 可变字符序列,效率最高,线程不安全
String使用注意说明 :
string s = "a";创建了一个字符串s += "b";实际上原来的”a”字符串对象已经丢了,现在又产生了一个字符串s + “b”(也就是”ab”).如果多次执行这些改变串内容的操作,会导致大量副本字符串0对象存留在内存中,降低效率.如果这样的操作放到循环中,会极大影响程序的性能 => 结论:如果字符串存在大量的修改操作,一般使用StringBuffer和StringBuilder.
如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder.
如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer.
如果我们的字符串很少修改,被多个对象引用,使用String,比如配置信息等.
效率: StringBuilder > StringBuffer > String
String类
String 类的理解和创建对象

String 对象用于保存字符串,也就是一组字符序列
“jack” 字符串常量, 双引号括起的字符序列
字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节
String 类有很多构造器,构造器的重载
常用的有 :
String s1 = new String();
String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count)
String s5 = new String(byte[] b)String 类实现了
接口 Serializable【String 可以串行化:可以在网络传输】
接口 Comparable [String 对象可以比较大小]String 是 final 类,不能被其他的类继承
String 有属性 private final char value[]; 用于存放字符串内容
一定要注意:value 是一个 final 类型, 不可以修改(需要功力):即 value 不能指向新的地址,但是单个字符内容是可以变化
String()方法
https://www.runoob.com/java/java-string.html
创建 String 对象的两种方式
String s = "hsp";String s = new String("hsp");
两种创建 String 对象的区别
方式一:先从常量池查看是否有”hsp”数据空间,如果有,直接指向;如果没有则重新创建,然后指向.s最终指向的是常量池的空间地址
方式二:先从堆中创建空间,里面维护了value属性,指向常量池的hsp空间.如果常量池没有”hsp”,重新创建,如果有,直接通过value指向.最终指向的是堆中的空间地址.

intern() 方法
https://blog.csdn.net/csdn_0911/article/details/79953177
Q:下列程序的输出结果:String s1 = “abc”;String s2 = “abc”;System.out.println(s1 == s2);A:true分析一下:程序执行,常量池中生成一个字符串,并将栈中的引用指向 s1,s2 先去查询常量池中是否有已经存在,存在,则返回常量池中的引用,所以s1 = s2。
Q:下列程序的输出结果:String s1 = new String(“abc”);String s2 = new String(“abc”);System.out.println(s1 == s2);A:false,两个引用指向堆中的不同对象。分析一下:第一步、常量池中生成一个字符串“abc”,并在堆中生成一个s1引用指向的对象,第二步、先去查询常量池中是否有已经存在“abc”,因为已经存在,所以不在生成,但堆中仍然会生成一个s2引用指向的对象,所以s1 , s2引用不一样。
Q:下列程序的输出结果:String s1 = “abc”;String s2 = “a”;String s3 = “bc”;String s4 = s2 + s3;System.out.println(s1 == s4);A:false,因为s2+s3实际上是使用StringBuilder.append来完成,会生成不同的对象。分析一下:程序执行,s1,s2,s3在常量池中分别生成字符串,并将栈中的引用指向s1,s2,s3,而s4在编译的时候,其方法内部创建StringBuilder来拼接对象,在堆中生成了新的对象。
引号声明的字符串都是会直接在字符串常量池中生成的,而 new 出来的 String 对象是放在堆空间中的。
public static void main(String[] args) {String str1 = "abc";String str2 = new String("abc");String str3 = str2.intern();System.out.println(str1==str2);//#1System.out.print (str1==str3);//#2}输出结果为: false true#1:str1指向常量池中的对象引用,str2指向堆中的对象引用,所以返回false;#2:str2.intern()指向str1的在常量池中的对象引用,所以str1==str3
public static void main(String[] args) {String abc = "abc";final String abcFinal = "abc";String str1 = "abc01";String str2 = "abc"+"01";String str3 = abc + "01";String str4 = abcFinal+"01";String str5 = new String("abc01").intern();System.out.println(str1 == str2);//#3System.out.println(str1 == str3);//#4System.out.println(str1 == str4);//#5System.out.println(str1 == str5);//#6}输出的结果为:true false true true#3:str1指向常量池中的对象引用,而str2在编译期间,+号会自动合并为一个字符串,因为常量池中已经生成了str1的对象,所以str2不在生成,直接将常量池对象的引用赋值给栈中的str2。#4:str4实际上是使用StringBuilder.append来完成,会生成不同的对象。#5:final修饰的变量,在编译期间会自动进行常量替换,这是与#4不同。所以不在生成新的对象,直接将常量池对象的引用str1赋值给栈中的str4。#6:都是指向常量池中的对象引用。
public static void main(String[] args) {String str2 = new String("abc")+new String("01");str2.intern();String str1 = "abc01";System.out.println(str2==str1);//#7}输出的结果为:true#8:str1指向常量池中的对象引用,而str2指向堆中的对象引用,并在常量池生成俩个对象,“abc”和“01”,接着str2.intern()返回str1指向常量池中的对象引用,但是对于str2没有影响,结果为false,如果是str2 = str2.intern();则最终结果将是true。
当调用 intern 方法是,如果池已经包含一个等于此 String 对象的字符串(用equals(Object)方法确定),则返回池中的字符串.否则,将此String对象添加到池中,并返回此String对象的引用.
b,intern()方法最终返回的是常量池的地址(对象)
format()方法
http://c.biancheng.net/view/4700.html
语法1
format(String format,Object……args)
参数说明:
- format:格式字符串。
- args:格式字符串中由格式说明符引用的参数。参数数目是可变的,可以为 0。

charAt()方法
charAt() 方法用于返回指定索引处的字符。索引范围为从 0 到 length() - 1。
public char charAt(int index)
substring() 方法
public String substring(int beginIndex)或public String substring(int beginIndex, int endIndex)

StringBuffer类
基本介绍
- StringBuffer代表可变的字符序列,可以对字符内容进行增删.
- 很多方法与String相同,但StringBuffer是可变长度的
- StringBuffer是一个容器
基础
StringBuffer 的直接父类 是 AbstractStringBuilder
StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
在父类中 AbstractStringBuilder 有属性 char[] value,不是 final
该 value 数组存放 字符串内容不是final的,因此存放在堆中的 (不在常量池)StringBuffer 是一个 final 类,不能被继承
因为 StringBuffer 字符内容是存在 char[] value, 所有在变化(增加/删除)
String VS StringBuffer
- String保存的是字符串常量,里面的值不能修改,每次String类的更新实际上就是更改地址,效率低(根本原因是final类型的char数组)
private final char value[]
存放在常量池中
- StringBuffer 保存的是字符串变量,里面的值可以更改,每次StringBuffer实际上可以更新内容,不用每次更新地址,效率较高.(空间不够时,才更新地址)
char[] value
存放在堆中
String -> StringBuffer
String str = "hello tom";
方式一 : 使用构造器
注意 : 返回的才是StringBuffer对象,对str本身没有影响
StringBuffer stringbuffer = new StringBuffer(str);
方式二 : 使用的是append方法
StringBuffer stringBuffer1 = new StringBuffer();stringBuffer1 = stringBuffer1.append(str);
StringBuffer -> String
StringBuffer stringBuffer3 = new StringBuffer("韩顺平教育");
方式 1 : 使用 StringBuffer 提供的 toString 方法
String s = stringBuffer3.toString();
方式 2 : 使用构造器来搞定
String s1 = new String(stringBuffer3);
StringBuffer方法
public class StringBufferMethod {public static void main(String[] args) {StringBuffer s = new StringBuffer("hello");//增s.append(',');// "hello,"s.append("张三丰");//"hello,张三丰"s.append("赵敏").append(100).append(true).append(10.5);//"hello,张三丰赵敏 100true10.5" System.out.println(s);//"hello,张三丰赵敏 100true10.5"//删/** 删除索引为>=start && <end 处的字符* 解读: 删除 11~14 的字符 [11, 14)*/s.delete(11, 14);System.out.println(s);//"hello,张三丰赵敏 true10.5"//改//老韩解读,使用 周芷若 替换 索引 9-11 的字符 [9,11)s.replace(9, 11, "周芷若");System.out.println(s);//"hello,张三丰周芷若 true10.5"//查找指定的子串在字符串第一次出现的索引,如果找不到返回-1int indexOf = s.indexOf("张三丰");System.out.println(indexOf);//6//插//老韩解读,在索引为 9 的位置插入 "赵敏",原来索引为 9 的内容自动后移s.insert(9, "赵敏");System.out.println(s);//"hello,张三丰赵敏周芷若 true10.5"//长度System.out.println(s.length());//22System.out.println(s);}}
练习
public class StringBufferExercise01 {public static void main(String[] args) {String str = null;// okStringBuffer sb = new StringBuffer(); //oksb.append(str);//需要看源码 , 底层调用的是 AbstractStringBuilder 的 appendNullSystem.out.println(sb.length());//4System.out.println(sb);//null//下面的构造器,会抛出 NullpointerExceptionStringBuffer sb1 = new StringBuffer(str);//看底层源码 super(str.length() + 16);//直接抛出空指针异常NullpointerExceptionSystem.out.println(sb1);}}
AbstractStringBuilder 的 appendNull
private AbstractStringBuilder appendNull() {ensureCapacityInternal(count + 4);int count = this.count;byte[] val = this.value;if (isLatin1()) {val[count++] = 'n';val[count++] = 'u';val[count++] = 'l';val[count++] = 'l';} else {count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');}this.count = count;return this;}
appendNull() 函数会把 null 放在数组 value 中
StringBuilder
基本介绍
一个可变的字符序列.此类提供一个与 StringBuffer 兼容的 API ,但不保证同步(StringBuilder 不是线程安全).该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候.如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快.
在 StringBuilder 上的主要操作是 append 和 insert 方法.可重载这些方法,以接收任意类型的数据.
StringBuffer 的直接父类 是 AbstractStringBuilder
StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
在父类中 AbstractStringBuilder 有属性 char[] value,不是 final
该 value 数组存放 字符串内容,引出存放在堆中的StringBuffer 是一个 final 类,不能被继承
因为 StringBuffer 字符内容是存在 char[] value, 所有在变化(增加/删除)
不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String
System类
exit 退出当前程序
- exit(0) 表示程序退出
- 0 表示一个状态 , 正常的状态
arraycopy复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组主要是搞清楚这五个参数的含义
源数组
* @param src the source array. // srcPos: 从源数组的哪个索引位置开始拷贝 // @param srcPos starting position in the source array. // dest : 目标数组,即把源数组的数据拷贝到哪个数组 // @param dest the destination array. // destPos: 把源数组的数据拷贝到 目标数组的哪个索引 // @param destPos starting position in the destination data. // length: 从源数组拷贝多少个数据到目标数组 // @param length the number of array elements to be copied | 含义 | 参数 | 内容 | | —- | —- | —- | | 源数组 | src | the source array | | 从源数组的哪个索引位置开始拷贝 | srcPos | starting position in the source array | | 目标数组,即把源数组的数据拷贝到哪个数组 | dest | the destination array | | 把源数组的数据拷贝到 目标数组的哪个索引 | destPos | starting position in the destination data. | | 从源数组拷贝多少个数据到目标数组 | length | the number of array elements to be copied |
