Java常用类
包装类
什么是包装类?
以前定义变量,经常使用基本数据类型,基本数据类型就是一个数,在这基础上加点属性、方法、构造器,就可以将基本数据类型封装成一个新的类——包装类。
包装类是引用数据类型,int,byte是基本数据类型。
对应关系
| 基本数据类型 | 对应的包装类 | 继承关系 |
|---|---|---|
| byte | Byte | Object-->Number |
| short | Short | Object-->Number |
| int | Integer | Object-->Number |
| long | Long | Object-->Number |
| float | Float | Object-->Number |
| double | Double | Object-->Number |
| char | Character | Object |
| boolean | Boolean | Object |
为什么需要封装为包装类
- Java是面向对象的语言,擅长操作各种各样的类。
- 以前学习装数据的是数组,如int[],String[],Student[],以后学习装数据的是集合,它有一个特点就是只能装引用类型的数据。
包装类常用属性、常用方法(重点)
【1】Integer类可以直接使用,无需导包:

【2】类的继承关系:

【3】实现的接口:

【4】这个类被 final修饰,说明这个类不能被子类继承,也就是说它没有子类:

【5】包装类是对基本数据类型的封装
对 int类型封装生成 Integer类:

【6】类的历史:
Integer类从JDK1.0诞生

【7】属性:
package com.commonclass.demo01;
/*
使用包装类 Integer的静态常量,模拟类型溢出
*/
public class Field {
public static void main(String[] args) {
//属性
System.out.println(Integer.MAX_VALUE); //2147483647
System.out.println(Integer.MIN_VALUE); //-2147483648
//补数,物极必反
System.out.println(Integer.MAX_VALUE+1); //-2147483648 类型溢出
System.out.println(Integer.MIN_VALUE-1); //2147483647
}
}
【8】构造器,发现没有无参构造,但是有 有参构造
(1)int类型作为构造器的参数,返回对应的包装类
Integer i1 = new Integer(12);

(2)String类型作为构造器的参数:
Integer i2 = new Integer("15"); //String的数字可以
// Integer i3 = new Integer("ilil"); //异常,无法转成int类型

【9】包装类特有的机制:自动装箱,自动拆箱:(重点难点)
- 自动装箱是从
JDK1.5以后的新特性。 - 自动装箱,自动拆箱是将基本数据类型和包装类进行快速转换。
package com.commonclass.demo01.test;
/*
自动装箱,自动拆箱
*/
public class AutoCast {
public static void main(String[] args) {
//自动装箱:int --> Integer
Integer i = 2;
System.out.println("基本类型已自动装箱为包装类!包装类为:" + i);
//自动拆箱:Integer --> int
Integer i2 = new Integer(5);
int num = i2;
System.out.println("包装类已转换为基本类型,基本类型为:" + num);
}
}
验证:
1、采用反编译验证,发现自动装箱走的是 valueOf()方法!这个方法是静态方法!
2、发现自动拆箱走的是 intValue()方法!这个方法是普通方法

可以自己打断点测试观察是否走入valueOf方法中:

说明:
1)static final int low = -128;最小值是-128
2)static final int high 是127;最大值是127
3)if (i >= IntegerCache.low && i <= IntegerCache.high) if语句当作过滤器,判断传入的 i 是否在这个范围内?这个范围是 -128 ~ 127
4)return IntegerCache.cache[i + (-IntegerCache.low)]; 从 cache数组中取一个Integer值,这个值是int基本类型的包装类
5)如果传入的 i 在 -128 ~ 127 之间,直接从cache数组中取对应的包装类,如果不在范围,就交给 Integer() 方法,也会返回对应的包装类!
【10】常用方法:
学习方法:通过看源码和API帮助文档了解怎么使用和实现方法,不需要死记硬背。用到的时候看API文档就行。
valueOf()方法的底层:【重点】

Integer类常用方法:
compareTo()、equals()、intValue()、parseInt()、toString()
package com.commonclass.demo01;
public class Method01 {
public static void main(String[] args) {
//compareTo:比较包装类大小,只返回三个值:-1,0,1,表示小于,等于,大于
Integer i1 = new Integer(6);
Integer i2 = new Integer(12);
//如果i1小于i2,返回-1;如果i1等于i2,返回0;如果i1大于i2,返回1
System.out.println(i1.compareTo(i2)); //return (x < y) ? -1 : ((x == y) ? 0 : 1);
//equals:比较两个对象的值,Integer类对Object中的equals方法进行了重写,比较的是底层封装的那个value的值
//Integer对象是通过new关键字创建的对象:
Integer i3 = new Integer(12);
Integer i4 = new Integer(12);
System.out.println(i3 == i4); //false,因为==比较的是两个对象的地址
boolean flag = i3.equals(i4); //true,equals比较的是两个对象里面的内容
System.out.println(flag);
/*
如果自动装箱的值在-128到127之间,那么==比较的是具体的数值
否则,比较的是对象的地址
*/
//Integer对象通过自动装箱实现:
System.out.println("***************");
// Integer i5 = 12;
// Integer i6 = 12;
// System.out.println(i5 == i6); //true,比较值
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5.equals(i6)); //true
System.out.println(i5 == i6); //false,比较对象的内存地址
System.out.println("***************");
//intValue():将包装类转换为基本类型int,Integer-->int
Integer i7 = 130;
int i = i7.intValue();
System.out.println(i);
//parseInt(String s):把String类型解析成int类型,String-->int
int i8 = Integer.parseInt("12");
System.out.println(i8);
//toString():把Integer包装类转换为String类型,Integer-->String
Integer i9 = 130;
System.out.println(i9.toString());
}
}
日期类(重点难点)
java.util.Date【重点】
常用方法:toString()
package com.commonclass.demo02;
import java.util.Date;
public class Date01 {
public static void main(String[] args) {
//java.util.Date:
Date d = new Date();
System.out.println(d); //隐式调用toString方法,Fri Oct 15 22:13:39 CST 2021
System.out.println(d.toString()); //显式调用toString方法,Fri Oct 15 22:13:39 CST 2021
System.out.println(d.toGMTString()); //过期方法,废弃方法
System.out.println(d.toLocaleString());//废弃方法
System.out.println(d.getYear()); //121,本质:121+1900=2021
System.out.println(d.getMonth()); //6,返回的值在0~11之间,0表示1月
//返回自1970年1月1日00:00:00 GMT 以来此Date对象表示的毫秒数
System.out.println(d.getTime()); //1627709788328
System.out.println(System.currentTimeMillis()); //1627709788328
/*
(1)问题:以后获取时间差用getTime()还是currentTimeMillis()?
答案:使用currentTimeMillis(),因为这个方法是静态方法,可以使用 类名.方法名()直接调用,方便快捷
(2)public static native long currentTimeMillis();
native表示本地方法
为什么没有方法体?
因为这个方法的具体实现不是通过Java写的,是C/C++
(3)这个方法的作用:
应用场景:一般会用来衡量一些算法所用的时间!
*/
long startTime = System.currentTimeMillis(); //开始计时
for (int i = 1; i <= 100000; i++) { //跑10w遍
System.out.println(i);
}
long endTime = System.currentTimeMillis(); //结束计时
System.out.println("耗时:"+ (endTime - startTime) + "ms");
}
}
java.sql.Date
java.sql.Date继承自 java.util.Date,所以java.sql.Date是子类,java.util.Date是父类。
1、java.sql.Date和java.util.Date的区别:
- java.util.Date:年月日 时分秒
- java.sql.Date:年月日
2、java.sql.Date和java.util.Date的联系:
- java.util.Date(子类) extends java.util.Date(父类)
package com.commonclass.demo02;
import java.sql.Date;
public class Date02 {
public static void main(String[] args) {
Date d = new Date(1627709788328L);
System.out.println(d);
/*
(1)java.sql.Date和java.util.Date的区别:
java.util.Date:年月日 时分秒
java.sql.Date:年月日
(2)java.sql.Date和java.util.Date的联系:
java.util.Date(子类) extends java.util.Date(父类)
*/
//java.sql.Date和java.util.Date相互转换:
//【1】util --> sql
// java.util.Date date = new java.util.Date(); //创建util.Date的对象
java.util.Date date = new Date(1627709788328L); //根据指定秒数创建util.Date的对象
//方式1:向下转型
Date date1 = (Date)date;
/*
父类:Animal 子类:Dog
Animal an = new Dog(); 父类引用指向子类对象
Dog d = (Dog)an; 强转为子类
*/
//方式2:利用构造器
Date date2 = new Date(date.getTime()); //date2是java.sql.Date的对象
//【2】sql --> util
java.util.Date date3 = d;
//【3】String --> sql.Date
Date date4 = Date.valueOf("2021-6-1");
System.out.println(date4);
}
}
SimpleDateFormat【重点】
场景1:前台把数据传到后台,前台提交的是 String字符串格式,后台需要把 String类型转换成java.util.Date。
【1】String-->java.util.Date 类型转换:
分解步骤:
- String --> java.sql.Date
- java.sql.Date --> java.util.Date
package com.commonclass.demo02;
public class Date03 {
public static void main(String[] args) {
//1、String --> java.sql.Date
java.sql.Date date1 = java.sql.Date.valueOf("2020-1-1");
//2、java.sql.Date --> java.util.Date
java.util.Date date2 = date1;
System.out.println(date2.toString());
// System.out.println(date2);
}
}
上面的代码有局限性,字符串的格式只能是 年-月-日 拼接的形式,换成其他类型,就会出现异常:
java.lang.IllegalArgumentException:非法的参数异常

【2】因为这样的原因,引入新的类:SimpleDateFormat
SimpleDateFormat主要有两个方法,parse()方法作用是把String解析成Date,format()方法作用是把Date格式化成String。
package com.commonclass.demo02;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Date04 {
public static void main(String[] args) {
//日期转换
//SimpleDateFormat(子类) extends DateFormat(父类是一个抽象类)
//自定义转换格式:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//String --> Date
try {
Date date = df.parse("2021-1-3 11:22:40"); //解析语句可能会报异常
// System.out.println(date);
System.out.println(date.toString());
} catch (ParseException e) {
e.printStackTrace();
}
//Date --> String
String format = df.format(new Date());
System.out.println(format);
//其他的Date --> String,预设的转换格式
Date date = new Date();
System.out.println(date.toString());
System.out.println(date.toGMTString());
System.out.println(date.toLocaleString());
}
}
【3】自定义日期格式:
这个就够用了,yyyy-MM-dd HH:mm:ss

Calendar日期类
常用方法:get()、set()
package com.commonclass.demo02;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Date05 {
public static void main(String[] args) {
//Calendar是一个抽象类,不可以直接创建对象,但我们可以创建它的实现类对象
//GregorianCalendar(子类) extends Calendar(父类)
Calendar cal = new GregorianCalendar();
Calendar cal2 = Calendar.getInstance(); //静态方法getInstance返回一个Calendar对象
System.out.println(cal);
System.out.println(cal2);
//常用的方法:
//get方法,传入参数:Calendar中定义的常量
System.out.println(cal.get(Calendar.YEAR));
System.out.println(cal.get(Calendar.MONTH));
System.out.println(cal.get(Calendar.DATE));
System.out.println(cal.get(Calendar.DAY_OF_WEEK));
System.out.println(cal.getActualMaximum(Calendar.DATE)); //获取当月日期的最大天数
System.out.println(cal.getActualMinimum(Calendar.DATE)); //获取当月日期的最小天数
//set方法:可以改变Calendar中的内容
cal.set(Calendar.YEAR, 2000);
cal.set(Calendar.MONTH, 5);
cal.set(Calendar.DATE, 20);
System.out.println(cal);
//String --> Calendar
//分解步骤:
//1、String --> java.sql.Date
java.sql.Date date = java.sql.Date.valueOf("2020-8-20");
//2、java.sql.Date --> Calendar
cal.setTime(date);
System.out.println(cal);
}
}
Calendar练习:
需求:用户输入日期,程序返回输入日期当月的日期。

package com.commonclass.demo02;
import java.util.Calendar;
import java.util.Scanner;
public class Date06 {
public static void main(String[] args) {
//1.录入日期的字符串String:
Scanner sc = new Scanner(System.in);
System.out.print("请输入你想要查看的日期:(提示:请按照例如2019-3-7的格式)");
String strDate = sc.next();
//String --> Calendar
//分解:
//(1)String --> java.sql.Date
java.sql.Date date = java.sql.Date.valueOf(strDate);
//(2)java.sql.Date --> Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
//2.后续操作:
//星期提示:
System.out.println("日\t一\t二\t三\t四\t五\t六\t");
//获取本月的最大天数:
int maxDay = cal.getActualMaximum(Calendar.DATE);
//获取当前日期中的日:
int nowDay = cal.get(Calendar.DATE);
//将日期调为本月的1号:
cal.set(Calendar.DATE,1);
//获取这个1号是本周的第几天:
int num = cal.get(Calendar.DAY_OF_WEEK);
//前面要空出来的天数为:
int day = num - 1;
//引入一个计数器:
int count = 0;
//在日期开始之前把空出来的天数打印出来:
for (int i = 1; i <= day; i++) {
System.out.print("\t");
}
//空出来的天数也要放入计数器
count += day;
//遍历:从1号开始到maxDay号进行遍历:
for (int i = 1; i <= maxDay; i++) {
if (i == nowDay) { //如果遍历的i和当前日子一样的话,后面多加一个*
System.out.print(i+"*"+"\t");
} else {
System.out.print(i+"\t");
}
count++; // 每在控制台输出一个数字,计数器+1
if (count % 7 == 0) { //当计数器的个数是7的倍数的时候,进行换行
System.out.println();
}
}
}
}
JDK1.8新增日期时间API【重点】
JDK1.0中使用java.util.Date类 --》 第一批日期时间API
JDK1.1引入Calendar类 --》 第二批日期时间API
缺陷⚠️:
可变性:像日期和时间这样的类,应该是不可变的。
偏移性:Date 的年份是从1900年开始的,月份是从0开始的。
格式化:格式化只对Date有用,对Calendar无效。
所以:JDK1.8新增日期时间API类 --》 第三批日期时间API
新增LocalDate,LocalTime,LocalDateTime类。
now()是静态方法,now()--获取当前的日期,时间,日期+时间
of()是静态方法,of()--指定日期,时间,日期+时间
常用方法:now()、of()、get()、with()
代码实现:
package com.commonclass.demo02;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Date07 {
public static void main(String[] args) {
//完成实例化
//now()是静态方法
//方法1:now()--获取当前的日期,时间,日期+时间
LocalDate localDate = LocalDate.now();
System.out.println(localDate); //2021-08-08
LocalTime localTime = LocalTime.now();
System.out.println(localTime); //12:28:20.986490700
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); //2021-08-08T12:28:20.986490700
//方法2:of()--设置指定的日期,时间,日期+时间
LocalDate of1 = LocalDate.of(2018, 12, 15);
System.out.println(of1);
LocalTime of2 = LocalTime.of(11, 10, 30);
System.out.println(of2);
LocalDateTime of3 = LocalDateTime.of(2000, 1, 30, 10, 24, 30);
System.out.println(of3);
//LocalDate,LocalTime用的不如LocalDateTime多
//一系列常用的get方法
System.out.println(localDateTime.getYear()); //2021
System.out.println(localDateTime.getMonth()); //JULY
System.out.println(localDateTime.getMonthValue()); //7
System.out.println(localDateTime.getDayOfMonth()); //31
System.out.println(localDateTime.getDayOfWeek()); //SATURDAY,星期几
System.out.println(localDateTime.getHour()); //17
System.out.println(localDateTime.getMinute()); //11
System.out.println(localDateTime.getSecond()); //57
//一系列常用的with方法,这里不叫set方法,叫with
//with方法的特点是不可变性,修改后返回一个新的日期对象,源对象不被改变
LocalDateTime localDateTime1 = localDateTime.withMonth(10);
System.out.println(localDateTime);
System.out.println(localDateTime1);
LocalDateTime localDateTime2 = localDateTime.withHour(13);
System.out.println(localDateTime);
System.out.println(localDateTime2);
//提供了加减操作:
//加 plus
LocalDateTime localDateTime3 = localDateTime.plusMonths(2);
System.out.println(localDateTime);
System.out.println(localDateTime3);
//减 minus
LocalDateTime localDateTime4 = localDateTime.minusMonths(3);
System.out.println(localDateTime);
System.out.println(localDateTime4);
}
}
DateTimeFormatter【重点】
使用预定义的标准格式。如:ISO_LOCAL_DATE_TIME,ISO_LOCAL_DATE,ISO_LOCAL_TIME
常用方法:format()、parse()、ofPattern()
代码实现:
package com.commonclass.demo02;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
public class Date08 {
public static void main(String[] args) {
//格式化类:DateTimeFormatter
//方法一:使用预定义的标准格式。如:ISO_LOCAL_DATE_TIME,ISO_LOCAL_DATE,ISO_LOCAL_TIME
DateTimeFormatter df1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//df1可以帮我们完成LocalDateTime和String之间的相互转换
//LocalDateTime --> String
LocalDateTime now = LocalDateTime.now();
String str = df1.format(now);
System.out.println(str); //2021-07-31T17:37:49.1268028
//String --> LocalDateTime
TemporalAccessor parse = df1.parse("2021-07-31T17:37:49.1268028");
System.out.println(parse);
//方法二:本地化相关的格式。如:ofLocalizedDateTime()
//参数:FormatStyle.LONG,FormatStyle.MEDIUM,FormatStyle.SHORT
//FormatStyle.MEDIUM:2021年7月31日下午5:50:59
//FormatStyle.SHORT:2021/7/31 下午5:51
DateTimeFormatter df2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
//LocalDateTime -- > String
LocalDateTime now1 = LocalDateTime.now();
String str2 = df2.format(now1);
System.out.println(str2);
//String --> LocalDateTime
TemporalAccessor parse1 = df2.parse("2021/7/31 下午5:51");
System.out.println(parse1);
//方法三:自定义的格式:如:ofPattern("yyyy-MM-dd hh:mm:ss") 重点,以后常用
DateTimeFormatter df3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//LocalDateTime -- > String
LocalDateTime now2 = LocalDateTime.now();
String str3 = df3.format(now2);
System.out.println(str3); //2021-07-31 06:00:02
//String --> LocalDateTime
TemporalAccessor parse2 = df3.parse("2021-07-31 06:00:02");
System.out.println(parse2);
}
}
Math类
【1】直接使用,无需导包:

【2】final修饰这个类,表示这个类不能被继承,即这个类没有子类:

【3】构造器私有化,不能创建Math类的对象:

无法创建Math类对象:

【4】Math类的所有属性和方法都被static修饰,通过 类名.属性名,类名.方法名 可以直接调用,无需创建对象:

【5】常用方法:
random()、abs()、ceil()、floor()、round()、max()、min()
package com.commonclass.demo03;
public class Demo01 {
public static void main(String[] args) {
//常用属性
System.out.println("圆周率:" + Math.PI);
//常用方法
System.out.println("随机数:" + Math.random()); //[0.0,1.0)
System.out.println("绝对值:" + Math.abs(-10));
System.out.println("向上取整:" + Math.ceil(9.1)); //10.0
System.out.println("向下取整:" + Math.floor(9.9)); //9.0
System.out.println("四舍五入:" + Math.round(4.4)); //4
System.out.println("四舍五入:" + Math.round(4.5)); //5
System.out.println("最大值:" + Math.max(4, 6));
System.out.println("最小值:" + Math.min(4, 6));
}
}
【6】静态导包(了解)
静态导包后,不用写 类名.方法名 ,直接写 方法名 就能调用静态方法。
静态导包平时不建议使用!!!
package com.commonclass.demo03;
//静态导包
import static java.lang.Math.*;
public class Demo01 {
public static void main(String[] args) {
//常用属性
System.out.println(Math.PI);
//常用方法
System.out.println("随机数:"+random()); //[0.0,1.0)
System.out.println("绝对值:"+abs(-10));
System.out.println("向上取整:"+ceil(9.1));
System.out.println("向下取整:"+ floor(9.9));
System.out.println("四舍五入:"+round(4.4));
System.out.println("四舍五入:"+round(4.5));
System.out.println("最大值:"+max(4, 6));
System.out.println("最小值:"+min(4, 6));
}
//如果跟Math类中的方法重复了,默认会先走本类中的方法(就近原则)
public static int random() {
return 100;
}
}
String类(重点难点)
【1】直接使用,无需导包:

【2】字符串详解:
这个String类代表一个字符串。


【3】字符串对象

String str = "abc";
"abc"就是String类的一个具体的对象。
【4】字符串是不可变的
字符串存储在常量池中,String对象被创建后,这个对象中的字符序列是不可改变的,直到这个对象被销毁。

【5】这个String类被final修饰,不能被继承,没有子类:

【6】String底层是一个 char类型的数组

验证:

String类常用方法【重点】
【1】构造器:底层就是给对象底层的 value数组进行赋值操作。
//通过构造器来创建对象:
String s1 = new String();
String s2 = new String("abc");
String s3 = new String(new char[] {'a', 'b', 'c'});
【2】常用方法
length(),isEmpty(),charAt()
package com.commonclass.demo04;
public class Demo02 {
public static void main(String[] args) {
String s4 = "abc";
System.out.println("字符串的长度为:" + s4.length());
String s5 = new String("abc");
System.out.println("字符串是否为空:" + s5.isEmpty());
System.out.println("获取字符串下标对应的字符为:" + s5.charAt(1));
}
}
【3】equals方法:
比较两个String对象的字符串内容是否一样。

String s6 = new String("abc");
String s7 = new String("abc");
System.out.println(s6.equals(s7)); //true
【4】String类实现了Comparable接口,里面有一个抽象方法叫compareTo,所以String类一定要对这个方法进行重写:
//compareTo()比较包装类的大小
String s8 = new String("abc");
String s9 = new String("abc");
System.out.println(s8.compareTo(s9)); //0,表示两个相等

【5】常用方法
substring()、concat()、replace()、split()、toUpperCase()、toLowerCase()、trim()、toString()、valueOf()
//字符串的截取
String s10 = "abdkmclcxz";
System.out.println(s10.substring(3)); //从下标3开始截取,到字符串末尾
System.out.println(s10.substring(3, 6)); //下标[3,6)
//字符串拼接
System.out.println(s10.concat("mmmm"));
//字符串替换字符
String s11 = "abdkmclcxm";
System.out.println(s11.replace('m', 'e')); //把m替换成e
//按照指定的字符串进行分隔为数组的元素
String s12 = "a-b-c-d-e-f";
String[] strs = s12.split("-"); //以-分割字符串为String数组
System.out.println(Arrays.toString(strs));
//转字母大小写的方法
String s13 = "abc";
System.out.println(s13.toUpperCase());
System.out.println(s13.toUpperCase().toLowerCase());
//去除首尾空格
String s14 = " a m j ";
System.out.println(s14.trim());
//toString()
String s15 = "abc";
System.out.println(s15);
//System.out.println(s15.toString());
//其他类型转换为String类型
System.out.println(String.valueOf(false));
System.out.println(String.valueOf(123.43423f));
String的内存分析【重点难点】
【1】字符串拼接
package com.commonclass.demo04;
public class Demo03 {
public static void main(String[] args) {
String s1 = "a" + "b" + "c";
String s2 = "ab" + "c";
String s3 = "a" + "bc";
String s4 = "abc";
String s5 = "abc" + "";
}
}
上面的字符串,编译器会进行优化,直接合并成完整的字符串。
使用反编译验证:

字符串存储在常量池中,常量池的特点是第一次如果没有这个字符串,就放进去,如果有这个字符串,就直接从常量池中取。
//三个引用对象都指向字符串常量池中的一个String
String s1 = "abc";
String s2 = "abc";
String s3 = "abc";
内存分析:

【2】通过new关键字创建 String对象
String s6 = new String("abc");
内存分析
开辟两个空间:
1、字符串常量池中的字符串 "abc"
2、堆中创建的对象 new String("abc")
3、堆中存储对象的引用地址 String s6

【3】有变量参与的字符串拼接:
package com.commonclass.demo04;
public class Demo04 {
public static void main(String[] args) {
String a = "abc";
String b = a + "def";
System.out.println(b);
}
}
变量a在编译的时候不知道a是 “abc” 字符串,所以不会进行编译期优化,不会直接合并为 “abcdef” 。
反编译class字节码文件,反编译是为了更好的分析字节码文件是如何执行的。
利用IDEA的终端:


StringBuilder【重点难点】
【1】字符串的分类:
不可变字符串:String
可变字符串:StringBuilder,StringBuffer
StringBuilder和 StringBuffer的区别
- StringBuffer类是线程安全的,StringBuilder不是线程安全的
- 都是被final修饰的类,不能被继承,就是没有子类
【2】StringBuilder底层:
StringBuilder底层是一个 char类型的数组。
非常重要的两个属性:

【3】StringBuilder内存分析
package com.commonclass.demo04;
public class Demo05 {
public static void main(String[] args) {
//创建StringBuilder对象
//表面上调用StringBuilder的空构造器,实际上底层是对value数组进行初始化,默认长度是16
StringBuilder sb1 = new StringBuilder();
//表面上调用StringBuilder的有参构造器,传入一个int类型的数,实际底层是对value数组进行初始化,长度为你传入的数
StringBuilder sb2 = new StringBuilder(3);
StringBuilder sb = new StringBuilder("abc");
System.out.println(sb.append("def").append("aaaaaaaa").append("bbb").append("0000000").toString());
}
}

什么是可变?什么是不可变?
【1】String --> 不可变

【2】StringBuilder --> 可变
在 StringBuilder这个对象地址不变的情况下,想把 “abc” 变成 “abcdef” 是可能的,StringBuilder允许直接在后面追加。
package com.commonclass.demo04;
public class Demo06 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb.append("abc") == sb.append("def")); //true,比较的是地址
}
}
StringBuilder和StringBuffer常用方法
【1】StringBuilder常用方法
append()、delete()、insert()、replace()、setCharAt()、substring()
package com.commonclass.demo04;
public class Demo07 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("qianqinawanwan");
//增
sb.append("这是一首歌");
System.out.println(sb); //qianqinawanwan这是一首歌
//删
sb.delete(4, 7); //删除位置在[4,7)上的字符
System.out.println(sb); //qianawanwan这是一首歌
sb.deleteCharAt(13); //删除位置在13上的字符
System.out.println(sb); //qianawanwan这是首歌
//改 --> 插入
StringBuilder sb1 = new StringBuilder("$342324252432");
sb1.insert(3, ","); //在下标为3的位置上插入 ,
System.out.println(sb1); //$34,2324252432
//改 --> 替换
StringBuilder sb2 = new StringBuilder("$2凉凉4512421");
sb2.replace(2, 4, "晴天"); //在下标[2,4)位置上替换字符串
System.out.println(sb2); //$2晴天4512421
sb2.setCharAt(4, '!'); //把下标为4的字符替换成 !
System.out.println(sb2); //$2晴天!512421
//查
StringBuilder sb3 = new StringBuilder("absdsd");
for (int i = 0; i < sb3.length(); i++) {
System.out.print(sb3.charAt(i)+"\t");
}
System.out.println();
//截取
String str = sb3.substring(2, 4); //截取[2,4)返回的是一个新的String,对StringBuilder没有影响
System.out.println(str);
System.out.println(sb3);
}
}
【2】StringBuffer常用方法
append()、delete()、insert()、replace()、setCharAt()、substring()
package com.commonclass.demo04;
public class Demo07 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("qianqinawanwan");
//增
sb.append("这是一首歌");
System.out.println(sb); //qianqinawanwan这是一首歌
//删
sb.delete(4, 7); //删除位置在[4,7)上的字符
System.out.println(sb); //qianawanwan这是一首歌
sb.deleteCharAt(13); //删除位置在13上的字符
System.out.println(sb); //qianawanwan这是首歌
//改 --> 插入
StringBuffer sb1 = new StringBuffer("$342324252432");
sb1.insert(3, ","); //在下标为3的位置上插入 ,
System.out.println(sb1); //$34,2324252432
//改 --> 替换
StringBuffer sb2 = new StringBuffer("$2凉凉4512421");
sb2.replace(2, 4, "晴天"); //在下标[2,4)位置上替换字符串
System.out.println(sb2); //$2晴天4512421
sb2.setCharAt(4, '!'); //在下标4位置前插入 !
System.out.println(sb2);
//查
StringBuffer sb3 = new StringBuffer("absdsd");
for (int i = 0; i < sb3.length(); i++) {
System.out.print(sb3.charAt(i)+"\t");
}
System.out.println();
//截取
String str = sb3.substring(2, 4); //截取[2,4)返回的是一个新的String,对StringBuffer没有影响
System.out.println(str);
System.out.println(sb3);
}
}
String,StringBuilder,StringBuffer的区别
- String类是不可变类,一旦 String对象被创建后,在这个对象中的字符串是不可改变的,直到这个对象被销毁。
- StringBuffer类是字符序列可变的字符串,可以通过append、delete、insert、charAt等方法改变它的内容。一旦生成了最终的字符串,调用 toString方法将其从char数组转换成 String。
- JDK1.5新增了一个 StringBuilder类,与 StringBuffer相似,构造器和方法基本相同。不同的是 StringBuffer是线程安全的,而 StringBuilder是线程不安全的,所以StringBuilder性能略高。通常情况下,创建一个内容可变的字符串,优先考虑使用StringBuilder。
总结:
StringBuilder:从 JDK1.5开始,效率高,线程不安全
StringBuffer:从 JDK1.0开始,效率低,线程安全

浙公网安备 33010602011771号