String类型与八大包装类型

学习内容

String类型

String类型是引用数据类型,他的包路径是:java.lang.String
String类型在底层是一个char数组(Java9开始改为byte数组)
在Java中规定,双引号括起来的都是字符串对象,是不可变的,被放到字符串常量池中。

为什么要把双引号括起来的String对象放到字符串常量池中?
因为字符串在实际开发过程中使用频繁,为了执行效率,所以把字符串放到字符串常量池中。 

 String对象的创建方式

  1.  使用双引号""括起来的都是String对象,这种方式创建的对象都是存放在字符串常量池中
  2. 使用构造方法创建String对象,这种方式创建的对象都是存放在堆内存中 
* public String(byte[] bytes) -----> 使用byte数组创建字符串对象
  * public String(byte[] bytes,int offset,int count) -----> 使用byte数组指定位置创建字符串对象
  * public String(char[] chars) -----> 使用char数组创建字符串对象
  * public String(char[] chars,int offset,int count) -----> 使用char数组指定位置创建字符串对象
  * public String(String original) -----> 使用字符串对象创建字符串对象

 String字符串存储原理

先看下面程序

public class Test2 {
	public static void main(String[] args){
		String str1 = "abc";
		String str2 = "abc";
		String str3 = "bcd" + "efg"; 
		String str4 = new String("abc");
		String str5 = new String("abc");
		String str6 = new String("bcd");
	}
}

 内存图如下:

java的String应该导入什么包 java string在哪个包_java

通过内存图可以看出使用双引号括起来的字符串都放到 String Table(字符串常量池) 中;使用构造方法创建的字符串都放到了堆内存中。
  那么问题来了,在上面的程序中一共创建了多少个String对象?

知道了程序的内存结构,我们来分析一下下面的程序

public class Test2 {
	public static void main(String[] args){
		String str1 = "abc";
		String str2 = "abc";
		String str3 = "bcd" + "efg"; 
		String str4 = new String("abc");
		String str5 = new String("abc");
		String str6 = new String("bcd");
		
		System.out.println(str1 == str2);
		System.out.println(str4 == str5);
		System.out.println(str1 == str4);
	}
}

对于上面的程序,控制台输出的结果是什么? 

java的String应该导入什么包 java string在哪个包_java的String应该导入什么包_02

因为"=="运算符比较的是变量的值,而引用数据类型中存放的值都是对象的内存地址,通过内存图我们可以看出

str1(0x111) == str2(0x111) ----> 内存地址相同,结果为true
 str4(0x555) == str5(0x666) ----> 内存地址不相同,结果为false
 str1(0x111) == str4(0x555) ----> 内存地址不相同,结果为false

String类型常用方法

比较

完成功能    

方法

比较两个字符串是否相同 

public boolean equals(Object)

忽略大小写比较两个字符串是否相同

public boolean equalsIgnoreCase(String)

按字典顺序比较字符串的大小

public int compareTo(String)

  1. equal方法具有对称性,即"s1.equal(s2)"与"s2.equal(s1)"效果一样
  2. 如果比较一个常量一个变量,建议将变量写在前面,即 “常量字符串”.equals(s2),这么写可以避免空指针异常

 获取

功能

方法

获取当前字符串的字符个数

public int length()

拼接字符串(创建了新对象)

public String concat(String)

获取当前字符串指定索引位置的单个字符

 

public char charAt(int)

返回字符串在当前字符串中第一次出现的索引位置

 public int indexOf(String)

字符串截取(从指定索引位置开始直到到结束) 

   public String substring(int)

字符串截取(从指定索引位置开始到指定索引位置结束)(左闭右开)

public String substring(int,int)

转换

功能

 方法

转换成字符数组

 public char[] toCharArray()

转换成字节数组 

public byte[] getBytes()

分割字符串

如果要使用.分割需要转义字符    public String[] split(String)

替换字符串

(在当前字符串中将后一个参数字符替换前一个参数字符) 

public String replace(char,char)

替换字符串

(在当前字符串中将后一个参数字符串替换前一个参数字符串)

public String replace(charSecqence,charSecqence)

转换大写

public String toUpperCase()

转换小写

public String toLowerCase()

String类还有一个静态方法String.valueOf(多类型重载),当该方法参数为Object是会调用该Object的toString()

 字符串的拼接

使用字符串连接符"+"进行拼接

  •   由于字符串是不可变的,所以在每次拼接后都会产生新的字符串,这样会占用大量的字符串常量池内存,造成空间浪费。
  • 使用String实例方法concat(String)
  •   调用concat()拼接字符串,方法内部代码执行会产生一个新的String对象
  • 使用StringBuffer或StringBuilder
  •   使用StringBuffer或StringBuilder追加内容,如果追加后不超出StringBuffer或StringBuilder的容量,那么并不会产生新的对象

 StringBuffer和StringBuilder

String与StringBuffer区别:
String和StringBuffer底层都是数组(Java9之前是char数组,Java9(包括9)之后是byte数组。),String底层的数组被final修饰,StringBuffer底层的数组没有被final修饰,所以StringBuffer可以扩容,String不能进行扩容

StringBuffer与StringBuilder区别
StringBuffer中方法都被synchronize关键字修饰,表示在多线程环境下运行时安全的,而StringBuilder中的方法没有被synchronize关键字修饰,所以StringBuilder时非线程安全的。 

八大包装类型 

为什么要使用包装类型?

 在调用方法时,若方法参数是引用数据类型(Object类型),那么使用基本数据类型是无法传参进去的,所以需要包装类间接传参。

 八种基本数据类型对应的八种包装类型都是什么?

基本类型

包装类型

byte

java.lang.Byte(父类Number)

short

java.lang.Short(父类Number)

int

java.lang.Integer(父类Number)

long

java.lang.Long(父类Number)

float

java.lang.Float(父类Number)

double

java.lang.Double(父类Number)

boolean

java.lang.Boolean(父类Object)

char

java.lang.Character(父类Object)

 

java的String应该导入什么包 java string在哪个包_开发语言_03

 八种包装类常用的属性和方法(以Integer为例)

因为八种包装类的方法基本相似,所以通过学习Integer的常用方法可以对其他包装类照葫芦画瓢。

属性

• public static final int MIN_VALUE;  -------> 获取int类型的最小值
• public static final int MAX_VALUE; -------> 获取int类型的最大值

构造方法

• public Integer(int);   -------> 通过一个int类型数据创建一个Integer对象
• public Integer(String); -------> 通过一个String类型的数据创建一个Integer对象

 如果构造方法中传入的实参是String类型,在程序运行时可能会出现数值格式化异常——NumberFormatException

实例方法

• public int intValue();    -------> 将当前Integer类型转换成int类型
• public float floatValue(); -------> 将当前Integer类型对象转换成float类型
  • 等等…

对于所有的Number类型对象,都可以任意转换成相应的基本数据类型(byte,short,int,long,float,double) 

 静态方法

• public static int praseInt(String);
• public static Integer valueOf(int/String);
• public staitc toStirng(int);
• public static toBinaryString(int);
• public static toOctalString(int);
• public staitc toHexString(int);

手动装箱与手动拆箱

public static void main(String[] args){	
	//手动装箱
	Integer i1 = new Integer(10);
	//手动拆箱
	int i2 = i1.intValue();
}

自动装箱与自动拆箱(Java5新特性)

public static void main(String[] args){
	//自动装箱
	Integer i1 = 10;
	//自动拆箱
	int i2 = i1;
}

包装类使用算数运算符(+ - * / %)进行算数运算时都会执行自动拆箱动作

整数型常量池

在Java中为了执行效率,在类加载时刻会在方法区中会声明并初始化一个长度为256的Integer静态常量数组,其中存储了范围在[-128,127]中的Integer对象,我们将这个Integer数组为称作整数型常量池(下图是Java8源码)

java的String应该导入什么包 java string在哪个包_jvm_04

 Integer面试题

public class Test2 {
	public static void main(String[] args){
		Integer i1 = 127;
		Integer i2 = 127;
		Integer i3 = 128;
		Integer i4 = 128;
		System.out.println(i1 == i2);
		System.out.println(i3 == i4);
	}
}

java的String应该导入什么包 java string在哪个包_java的String应该导入什么包_05

 Stirng、Integer、int类型相互转换

java的String应该导入什么包 java string在哪个包_开发语言_06