String使用时的注意事项
- String对象的内容不可改变,被称为不可变字符串对象。(每次试图改变字符串对象实际上是新产生了新的字符串对象了,变量每次都是指向了新的字符串对象,之前字符串对象的内容确实是没有改变的,因此说String的对象是不可变的。)
- 只要是以 “...” 方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份(这么设计主要是为了节约内存);但通过 new 方式创建字符串对象,每 new 一次都会产生一个新的对象放在堆内存中。
阅读程序并解答(1)
public class Test{ public static void main(String[] args){ String s2 = new String("abc"); String s1 = "abc"; System.out.println(s1 == s2); } }
- 两行代码分别创建了几个对象
- 运行结果
第一行代码执行时,new操作原本是让字符存储到了堆内存中,但此时String内部写了"abc",用双引号写出来的字符会被放入字符串常量池中;所以字符串常量池和堆内存中都各自有一个abc字符。
所以第一行代码创建了2个对象。
第二行代码是用双引号书写的字符,将被放到堆内存中的字符串常量池里,但此时已存在abc,故第二行代码没有创建新的对象。
s2的地址指向堆内存的abc,s1的地址指向堆内存中的字符串常量池的abc,所以两者地址并不相等,所以运行结果为false。
阅读程序并解答(2)
public class Test3{ public static void main(String[] args){ String s1 = "abc"; String s2 = "ab"; String s3 = s2 + "c"; System.out.println(s1 == s3); } }
public class Test4{ public static void main(String[] args){ String s1 = "abc"; String s2 = "a" + "b" + "c"; System.out.println(s1 == s2); } }
判断上面两段程序输出的结果分别是什么
第一段程序:s1指向放在字符串常量池里的abc,s3是由s2字符串加上字符串"c"运算之后得到的新字符串,所以s1与s3的地址并不相同,输出结果为false;
第二段程序:由于Java存在编译优化机制,程序在编译时,"a" + "b" + "c" 会直接转换成"abc",以提高程序的执行性能,所以检测到字符串常量池中原本存在"abc",不会创建新的字符串,s1与s2指向的地址相同,输出结果为true。
String的应用案例
案例1
需求:
统正确的登录名和密码是:Administrator/123456,请在控制台开发一个登录界面,接收用户输入的登录名和密码,判断用户是否登录成功,登录成功后展示::“欢迎进入系统!”,即可停止程序
(注意:要求最多给用户三次登录机会)
步骤:
- 开发登录界面,提示用户通过键盘输入登录名和密码。
- 设计一个登录方法,对用户的登录名和密码进行正确性认证。
- 根据登录方法返回的认证结果,判断用户是否登录成功。
- 使用循环控制登录界面最多显示3次。
package StringTest; import java.util.Scanner; public class Test1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); //1.写一个简陋的登陆界面 for (int i = 0; i < 3; i++) { System.out.println("请您输入登陆名称:"); String loginName = sc.next(); System.out.println("请您输入登陆密码:"); String passWord = sc.next(); //3.写一个判断账号与密码是否一致的方法 login(); //5.调用方法 boolean rs = login(loginName,passWord); if(rs){ System.out.println("登陆成功,欢迎进入系统"); break; }else{ System.out.println("登录名或密码错误,请您重新确认"); } } } public static boolean login(String loginName,String passWord){ String okLoginName = "Administrator"; String okPassWord = "123456"; //4.判断用户是否登陆成功 return okLoginName.equals(loginName) && okPassWord.equals(passWord); } }
运行结果:
案例2
需求:
(使用String实现)实现随机产生验证码,验证码的每位可能是数字、大写字母、小写字母。
步骤:
- 设计一个方法,该方法接收一个整型参数,最终要返回对应位数的随机验证码。
- 方法内定义2个字符串变量:1个用来记住生成的验证码,1个用来记住要用到的全部字符。
- 定义for循环控制生成多少位随机字符,每次得到一个字符范围内的随机索引,根据索引提取该字符,把该字符交给code变量连接起来,循环结束后,在循环外返回code即可。
- 主程序中,调用该方法即可得到随机验证码了。
package StringTest; import java.util.Random; public class Test2 { public static void main(String[] args) { System.out.println(createCode(4)); System.out.println(createCode(6)); } //1.设计方法返回指定位数的验证码 public static String createCode(int n){ //定义两个变量 一个存储最终产生的验证码 另一个存储所有可能用到的全部字符 String code = ""; String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Random r = new Random(); //3.开始定义循环产生每位随机字符 for (int i = 0; i < n; i++) { int index = r.nextInt(data.length()); //5.根据索引去全部字符中提取字符 code += data.charAt(index); } return code; } }
运行结果:
小结
1、字符串的比较使用==比较好吗?为什么?什么时候使用==?
- 不好,对于字符串对象的比较,==比较的是地址,容易出业务bug
- 基本数据类型的变量或者值应该使用==比较。
2、开发中比较字符串推荐使用什么方式比较?
- 使用String提供的equals方法,它只关心字符串内容一样就返回true。
方法名 |
public boolean equals(Object anObject) |
public boolean equalsIgnoreCase(String anotherString) |
END