String概述
String类代表字符串,String里定义的变量可以用于指向字符串类型,然后操作该字符串。
Java程序中所有字符串类型文字("")都为此类的对象。
String name = "peng";
String类特点
String常被称为不可变字符串类型,指的是它的对象在创建后不能被更改;
String中存储的是字符串对象的地址;
双引号直接创建的字符串对象,在堆内存中的字符串常量池中存储,相同的数据只存储一份;而通过new创建的对象直接存储在堆内存中;
通过new构造器创建的字符串对象,在堆内存中由同一字符串常量池中的数据创建并分开存储。
双引号直接创建的字符串对象(例如"abc"),而非直接创建的字符串对象计算的结果直接放在堆内存中(例如"ab"+"c"形成的"abc"对象直接存储在堆内存中)
public class Test{
public static void main(String[] args){
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
}
}
程序编译时,首先由方法区加载Test类,其次将main方法提到栈内存中,字符串s1、s2全部存储到堆内存的字符串常量池中(注:Java程序中所有由""给出的字符串对象在堆内存的字符串常量池中存储,而且相同内容只会在其中存储一份。)s1、s2在字符串常量池中属于只存储一份,产生的对象也就只有一个(由new()方法产生的对象为新的对象),所以s1、s2中指向的对象为同一个,所以s1==s2
public class Test {
public static void main(String[] args) {
char[] ch = {'a', 'b', 'c'};
String s1 = new String();
String s2 = new String();
System.out.println(s1 == s2); //false
}
}
g
String常见面试题
问:下列代码的运行结果是?
public class Test {
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2); //false
}
}
分析
s1实际上创建了两个对象,一个存储在字符串常量池中的abc,一个直接存储在堆内存中 的"abc"对象;
s2创建了0个对象,因为s1创建后字符串常量池中已经有"abc"这个字符串存在了,所以s2无法载创建一个abc对象;
因此,s1指向直接存储在堆内存中的abc对象,s2则指向字符串常量池中的abc,地址不同,不相等。
问:下列代码运行的结果是?
public class Test {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab";
String s3 = s2 + "c";
System.out.println(s1 == s3); //false
}
}
分析:
s1为直接由""创建的字符串对象,存储在字符串常量池中;
s2为两个""创建的字符串对象拼接而成的,拼接的结果直接存储在堆内存中;
s1和s2指向的对象不同,故不相等。
特例:Java编译优化机制,对于字面值在编译时自动转化,如下代码
s2在编译时会直接转成"abc"
public class Test {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2); //true
}
}
/*
* 上一段代码s3是在s2的基础上拼接其他""字符串,而读取s2的值是在运行时才会读取,编译时s2的值未知
所以不会触发Java编译优化机制
*/
String类常用API
字符串内容比较——equals()
public boolean equals(Object anObject) //将此字符串与指定字符串比较,只关心字符内容知否一致
public boolean equalsIgnoreCase(String anotherString) //将此字符串与指定字符串比较,忽略大小写,只关心字符内容知否一致,常用于验证码比对
补:==比较的是地址而非内容,基本数据类型比较时使用。
其他常用String类API
案例——String类开发验证码
练习题:使用String类完成随机生成的5位验证码
public class Test {
//练习题:使用String类实现随机生成六位验证码
public static void main(String[] args) {
//定义数据取值范围
String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//随机生成验证码
String code = "";
Random r = new Random();
for (int i = 0; i < 6; i++ ) {
int index = r.nextInt(data.length());
char c = data.charAt(index); //调用String类的API,通过索引提取字符串中的指定值
code += c;
}
//输出验证码
System.out.println(code);
}
}
练习题:使用String类模拟用户登录操作,有三次机会
public class login_String {
//使用String类模拟用户登录,只有三次机会
public static void main(String[] args) {
//定义正确的用户名、密码
String okLoginName = "peng";
int passWord = 123456;
//验证用户名、密码是否正确
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String loginname = sc.next();
if (loginname.equals(okLoginName)){
System.out.println("请输入密码:");
int password = sc.nextInt();
if (password == passWord){
System.out.println("欢迎进入系统");
}else {
System.out.println("您输入的密码有误,请重新输入,还剩余" + (2-i) + "次机会");
continue;
}
}else {
System.out.println("您输入的用户名有误,请重新输入,还剩余" + (2-i) + "次机会");
continue;
}
}
}
}
练习题:使用String类屏蔽手机号的中间四位
public class phonenumhide {
//练习题:通过String类屏蔽手机号中间四位
public static void main(String[] args) {
//让用户输入手机号
Scanner sc = new Scanner(System.in);
System.out.println("请输入手机号:");
String phoneNum = sc.next();
//屏蔽中间四位
String before = phoneNum.substring(0, 3); //187 2556 3345 截取前三位
String last = phoneNum.substring(7); //012 3456 78910 截取后四位
String newNum = before + "****" + last; //加*屏蔽
//输出屏蔽后的手机号
System.out.println(newNum);
}
}