一、String概述
String类在Java.lang包下,String类定义的变量可以用于指向字符串对象,然后操作该字符串。java程序中所有的字符串文字(双引号中的字符)都为此类的对象。String类常被称为不可变字符串类型,它的对象在创建后不可被改变。以双引号方式给出的字符串对象,在堆内存的字符串常量池中存储,并返回地址给栈内存的变量。
String是字符串类型,可以定义字符串变量指向字符串对象。String变量的每次修改其实都是产生并指向新的对象,原来的字符串对象不会发生改变。
案例分析:
public class text {
public static void main(String[]args){//进入栈内存
String name = "A";//在字符串常量池中创建一个对象“A”,并返回地址给栈内存中的变量name
name += "B";//在字符串常量池中创建一个对象“B”,并于之前存储的对象”A“进行运算,生成新的对象”AB“存储在字符串常量池中,并返回地址。
name += "C";//在字符串常量池中创建一个对象“C”,并于之前新生成的对象”AB“进行运算,生成新的对象”ABC“存储在字符串常量池中,并返回地址给栈内存中的变量name。
System.out.println(name);//因此输出的结果是"ABC",而不是地址。(jvm会对字符串进行优化)
}
}
二、String类创建对象的两种方式,及内存原理
方式一:直接使用双引号创建 如:String name = "ABC";
方式二:通过构造器创建 如:1、String s1 = new String();//s1 = ''
2、String s2 = new String("ABC")//s2 = "ABC"
3、 char[] chars = {'a','b','中','国'}
String s3 = new String(chars);//构造器会对字符数组进行优化处理
System.out.println(s3);
4、 byte[] b = {97,98,99,65,66,67}
String s4 = new String(b);
System.out.println(s4);
内存原理:双引号定义的字符串对象,存储在堆内存的字符串常量池中,且相同内容只存储一份。
通过new构造器的方式创建的对象,每new一次都会在堆内存中产生一个新的对象。
案例分析:
public class text {
public static void main(String[]args){//进入栈内存
char[] b = {97,98,99,65,66,67};
String s3 = new String(b);
String s4 = new String(b);//用构造器定义的字符串对象,每new一次就在堆内存中产生一个新的对象,则每个对象的地址不相同,但由于jvm会对字符串对象进行优化,所以不能直输出不同的对象地址
System.out.println(s4==s3);//false
String a = "abcABC";
String c = "abcABC";//用双引号定义的字符串对象,相同内容只存储一份。
System.out.println(a==c);//true
}
}
三、String常见面试题
1、public class text {
public static void main(String[]args){//进入栈内存
String s2 = new String("abc");
String s1 = "abc";
System.out.println(s1 == s2);//false
}
}
2、public class text {
public static void main(String[]args){//进入栈内存
String s2 = "ab";
String s3 = s2+"c";
String s1 = "abc";
System.out.println(s1 == s3);//false
}
}
3、public class text {
public static void main(String[]args){//进入栈内存
String s2 = "ab"+"c";//java存在编译优化机制,在编译时“ab”+“c”会直接转成“abc”
String s1 = "abc";
System.out.println(s1 == s2);//true
}
}
四、String类常用API
1、字符串内容比较
equals()内容比较
equalsIgnoreCase()忽略大小写内容比较
2、其他常用API
public class Login {
public static void main(String[] args) {
//public int length():获取字符串长度
String keycode = "AcD332";
System.out.println(keycode.length());//6
//public char charAt(int index)获取某个索引位置处的字符
System.out.println(keycode.charAt(3));//3
System.out.println("----------------");
for (int i = 0; i < keycode.length(); i++) {//遍历字符串
System.out.println(keycode.charAt(i));
}
System.out.println("------------------");
//public char[] toCharArray()把字符串转换成字符数组
for (int i = 0; i < keycode.toCharArray().length; i++) {
System.out.println(keycode.charAt(i));
}
//public String substring(int beginIndex,int endIndex)截取包前不包后
System.out.println(keycode.substring(0,4));//前四位
//public String substring(int beginIndex)从当前索引一直截取到末尾
System.out.println(keycode.substring(4));
//public String replace(CharSequence target,CharSequence replacement)//将字符串中的字符串替换
System.out.println(keycode.replace("3","*"));//AcD**2(遇到3就替换成*,也可以遇到“A”替换成“**”)
//public boolean contains(CharSequence s)//判断字符串中是否包含某字符串
System.out.println(keycode.contains("33"));//true
System.out.println(keycode.contains("3c"));//false
//public boolean startsWiths(String prefix)//判断是否以某字符串开始
System.out.println(keycode.startsWith("0A"));//false
System.out.println(keycode.startsWith("A"));//true
//public String[] split(String s)//按照某字符串内容把字符串分割成字符串数组返回
String s = "a,b,c,d";
String[] arr = s.split(",");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
五、String案例
1、用户登录及生成验证码并比对
import java.util.Random;
import java.util.Scanner;
public class Login {
public static void main(String[] args) {
login();
Scanner sc = new Scanner(System.in);
System.out.print("请输入验证码位数:");
int N = sc.nextInt();
String keycode = keycode(N);
System.out.print("请输入验证码:");
String code = sc.next();
contrast(code, keycode);
}
public static void login() {
boolean flag = true;
String name = "ABC";
String password = "123456";
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("username:");
String username = sc.next();
System.out.println("userpassword:");
String userpassword = sc.next();
if (name.equals(username) || password.equals(userpassword)) {
if (name.equals(username)) {
if (password.equals(userpassword)) {
System.out.println("用户名密码正确!");break;
} else {
System.out.println("密码错误!请重新输入!(您还有" + (2 - i) + "次机会)");
}
} else {
System.out.println("用户名错误!请重新输入!(您还有" + (2 - i) + "次机会)");
}
} else {
System.out.println("用户名或密码错误!请重新输入!(您还有" + (2 - i) + "次机会)");
}
if (i == 2) {
System.out.println("账户被锁定!");
System.exit(0);
}
}
}
public static String keycode(int N) {
//利用String存储大小写字母及数字,随机生成验证码
String code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
String keycode = "";
Random r = new Random();
for (int i = 0; i < N; i++) {
char c = code.charAt(r.nextInt(0, 62));
keycode += c;
}
System.out.println(keycode);
return keycode;
}
public static void contrast(String code, String keycode) {
if (code.equalsIgnoreCase(keycode)) {
System.out.println("验证码正确!登录成功!");
} else {
System.out.println("您输入的验证码有误!请重新输入");
}
}
}
2、手机号屏蔽
import java.util.Scanner;
public class Shield {
public static void main(String[] args) {
System.out.println("请输入电话号码:");
Scanner sc = new Scanner(System.in);
String telnum = sc.next();
System.out.println(shield(telnum));
}
public static String shield(String telnum){
String f = telnum.substring(0,3);
String e = telnum.substring(7,11);
// telnum = telnum.replace(telnum.substring(3,7),"****")//用replace()方法若中间四位与后四位一致则会出现bug
telnum = f+"****"+e;
return telnum;
}
}