包装类
装箱与拆箱
装箱:从基本类型转换为对应的包装类对象。
拆箱:从包装类对象转换为对应的基本类型。
基本数值---->包装对象
Integer i = new Integer(4);//使用构造函数
Integer iii = Integer.valueOf(4);//使用包装类中的valueOf方法
包装对象---->基本数值
int num = i.intValue();
自动装箱与自动拆箱(JDK5.0新特性)
Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
//加法运算完成后,再次装箱,把基本数值转成对象。
基本类型与字符串之间的转换
基本类型转换String总共有三种方式
//将基本数据类型转换成字符串类型1:包装类型的实例方法toString()
String str1=new Integer(123).toString();
//将基本数据类型转换成字符串类型2:包装类型的静态方法toString(基本数据类型)
String str2=Integer.toString(234);
//将基本数据类型转换成字符串类型3:String类型的静态方法valueOf(基本数据类型)
String str3=String.valueOf(345);//推荐
//将基本数据类型转换成字符串类型4:字符串连接符
String str4=456+"";
String转换成对应的基本类型
//将字符串类型转换为基本数据类型1:包装类型的构造器
int num01=new Integer("567");
//将字符串类型转换为基本数据类型2:包装类型的静态方法parseXxx(字符串)
int num02=Integer.parseInt("678");//注意character
除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型:
public static byte parseByte(String s) :将字符串参数转换为对应的byte基本类型。
public static short parseShort(String s) :将字符串参数转换为对应的short基本类型。
public static int parseInt(String s) :将字符串参数转换为对应的int基本类型。
public static long parseLong(String s) :将字符串参数转换为对应的long基本类型。
public static float parseFloat(String s) :将字符串参数转换为对应的float基本类型。
public static double parseDouble(String s) :将字符串参数转换为对应的double基本类
型。
public static boolean parseBoolean(String s) :将字符串参数转换为对应的boolean基本
类型。
String类
特点
字符串不变:字符串的值在创建后不能被更改。
因为String底层是一个被final修饰的数组
数组的数据类型是什么?
- JDK8.0(包含)以前:char[]
- JDK9.0(包含)以后:byte[]
为什么在JDK9.0将char[]修改为byte[]
时间复杂度
在进行存储数据的时候,都清楚数据最终转换为二进制
如果是char[],里面的元素是char类型,先将char类型的元素根据编码转换成byte,再由byte转换成二进制
如果是byte[],里面的元素是byte类型,可以将byte类型元素直接转换成二进制
空间复杂度
内码:在源码中每创建一个char类型变量,需要根据内码的规则进行空间的划分
内码的规则:每个字符占用内存空间2个字节
外码:自定义一个char类型变量,需要根据外码的规则进行空间的划分
外码的规则:字符集编码
默认字符集编码UTF8:每个英文字符占用1个字节,每个中文字符占用3个字节
如果String底层是char[]
存储字符串"abc",遵循内码规则,里面含有3个字符,每个字符占用2个字节,总共占用6个字节
存储字符串"尚硅谷",遵循内码规则,里面含有3个字符,每个字符占用2个字节,总共占用6个字节
如果String底层是byte[]
存储字符串"abc",遵循字符编码规则,里面含有3个英文字母,每个英文字母根据UTF8的编码占用1个字节,总共占用3个字节
存储字符串"尚硅谷",遵循字符编码规则,里面含有3个中文汉字,每个中文汉字根据UTF8的编码占用3个字节,总共占用9个字节
String s1 = "abc";
s1 += "d";
System.out.println(s1); // "abcd"
// 内存中有"abc","abcd"两个对象,s1从指向"abc",改变指向,指向了"abcd"。
因为String对象是不可变的,所以它们可以被共享。
String s1 = "abc";
String s2 = "abc";
// 内存中只有一个"abc"对象被创建,同时被s1和s2共享。
- “abc” 等效于 char[] data={ ‘a’ , ‘b’ , ‘c’ } 。
String str = “abc”;
相当于:
char data[] = {‘a’, ‘b’, ‘c’};
String str = new String(data);
// String底层是靠字符数组实现的。
String对象为什么可以存储中文?
String 表示一个 UTF-16 格式的字符串,String 类提供处理 Unicode 代码点(即字符)和 Unicode 代码单元(即 char 值)的方法。
7.""和null区别:
""表示长度为0字符串对象,含有地址值
null字面值常量,是引用数据类型的默认值,null在堆空间没有地址值(常量区含有)
构造方法
public String() :初始化新创建的 String对象,以使其表示空字符序列。
public String(char[] value) :通过当前参数中的字符数组来构造新的String。
public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。
public String(String s) ` :通过当前参数中的String来构造新的String。
构造举例,代码如下:
// 无参构造
String str = new String();
// 通过字符数组构造
char chars[] = {'a', 'b', 'c'};
String str2 = new String(chars);
// 通过字节数组构造
byte bytes[] = { 97, 98, 99 };
String str3 = new String(bytes);
常用方法
判断功能的方法
public boolean equals (Object anObject) :将此字符串与指定对象进行比较。
public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小写。
public boolean contains(CharSequence s) :当且仅当此字符串包含指定的 char 值序列时,返回true。
public boolean endsWith(String suffix) :测试此字符串是否以指定的后缀结束。
public boolean isEmpty() :当且仅当 length() 为 0 时返回 true。
public boolean startsWith(String prefix) :测试此字符串是否以指定的前缀开始。
lpublic boolean startsWith(String prefix,int toffset) :测试此字符串从指定索引开始的子字符串
是否以指定前缀开始。
获取功能的方法
public int length () :返回此字符串的长度。
public String concat (String str) :将指定的字符串连接到该字符串的末尾。
public char charAt (int index) :返回指定索引处的 char值。
public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。
public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。注意beginIndex为数组长度和长度加1时的情况
public String substring (int beginIndex, int endIndex) :返回一个子字符串,从
beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。
转换功能的方法
public char[] toCharArray () :将此字符串转换为新的字符数组。
public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
public String replace (CharSequence target, CharSequence replacement) :将与
target匹配的字符串使用replacement字符串替换。
分割功能的方法
public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。
String类的练习
public class StringTest2 {
public static void main(String[] args) {
//键盘录入一个字符串数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串数据:");
String s = sc.nextLine();
//定义三个统计变量,初始化值都是0
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
//遍历字符串,得到每一个字符
for(int x=0; x<s.length(); x++) {
char ch = s.charAt(x);
//拿字符进行判断
if(ch>='A'&&ch<='Z') {
bigCount++;
}else if(ch>='a'&&ch<='z') {
smallCount++;
}else if(ch>='0'&&ch<='9') {
numberCount++;
}else {
System.out.println("该字符"+ch+"非法");
}
}
//输出结果
System.out.println("大写字符:"+bigCount+"个");
System.out.println("小写字符:"+smallCount+"个");
System.out.println("数字字符:"+numberCount+"个");
}
}
StringBuilder类
由于String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象。
根据这句话分析我们的代码,其实总共产生了三个字符串,即 “Hello” 、 “World” 和 “HelloWorld” 。
引用变量s首先指向 Hello 对象,最终指向拼接出来的新字符串对象,即 HelloWord 。
由此可知,如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。为了解决这一问题,可以使用 java.lang.StringBuilder 类。
2.StringBuilder为什么可以改变?
* * StringBuilder类底层是一个没有被final关键字修饰的数组
* 5.StringBuilder类底层数组的初始容量是多少?
* * StringBuilder类底层数组的初始容量取决于选择的构造器
* * (1)public StringBuilder(String str)
* * 初始容量: str.length() + 16
* * (2)public StringBuilder(int capacity)
* * 初始容量: 自定义
* * (3)StringBuilder(CharSequence seq)
* * 初始容量: seq.length() + 16
* * (4)StringBuilder()
* * 初始容量: 16
* * 6.StringBuilder类底层数组扩容标准是什么
* * JDK8.0(包含)以后:
* * 扩容标准:(原来数组长度 << 1) + 2;
* * JDK7.0:
* * 扩容标准:原来数组长度 * 2 + 2
* * JDK6.0(包含)以前:
* * 扩容标准:(原来数组长度 + 1) * 2;
构造方法
public StringBuilder() :构造一个空的StringBuilder容器。
public StringBuilder(String str) :构造一个StringBuilder容器,并将字符串添加进去。
常用方法
public StringBuilder append(…) :添加任意类型数据的字符串形式,并返回当前对象自
身。
public String toString() :将当前StringBuilder对象转换为String对象。
public class Demo02StringBuilder {
public static void main(String[] args) {
//创建对象
StringBuilder builder = new StringBuilder();
//public StringBuilder append(任意类型)
StringBuilder builder2 = builder.append("hello");
//对比一下
System.out.println("builder:"+builder);
System.out.println("builder2:"+builder2);
System.out.println(builder == builder2); //true
// 可以添加 任何类型
builder.append("hello");
builder.append("world");
builder.append(true);
builder.append(100);
// 在我们开发中,会遇到调用一个方法后,返回一个对象的情况。然后使用返回的对象继续调用方法。
// 这种时候,我们就可以把代码现在一起,如append方法一样,代码如下
//链式编程
builder.append("hello").append("world").append(true).append(100);
System.out.println("builder:"+builder);
}
}
备注:StringBuilder已经覆盖重写了Object当中的toString方法。
toString方法
通过toString方法,StringBuilder对象将会转换为不可变的String对象。
public class StringDemo07 {
public static void main(String[] args) {
String str="abc";
str.concat("atguigu");
System.out.println("str = " + str);//String一旦初始化不会被改变
StringBuilder sb=new StringBuilder("abc");
System.out.println("sb = " + sb);
sb.append("atguigu");
System.out.println("sb = " + sb);
System.out.println("=======================");
//在指定的索引位置插入字符串
sb.insert(3, "defg");
System.out.println("sb = " + sb);
System.out.println("=====================");
//针对字符串进行反转
sb.reverse();
System.out.println("sb = " + sb);
System.out.println("======================");
sb=new StringBuilder();
sb.append("Hello");
sb.append("World");
sb.append("atguigu");
System.out.println(sb);
}
}
StringBuilder,StringBuffer的区别
String:不可变的字符序列
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况(推荐),不保证安全
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况,保证安全