Java从零到1的开始-Day13
一、String
1.String介绍
1.概述:String 类代表字符串
2.特点:
a.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例(对象)实现
凡是带双引号的都是String的对象
String s = "abc"
String是数据类型,是一个字符串类型
s:对象名
"abc":就是一个对象
b.字符串是常量,它们的值在创建之后不能更改
c.因为 String 对象是不可变的,所以可以共享
String s = "abc"
String s1 = "abc"
2.String的实现原理
1.String的实现原理:String的底层原本面貌是一个被final修饰的数组
a.jdk8之前:String底层是一个被final修饰的char数组->private final char[] value;
b.jdk8之后:String底层是一个被final修饰的byte数组->private final byte[] value;
2.为啥要从char数组变成byte数组呢?省内存
一个char类型占内存2个字节
一个byte类型占内存1个字节
String是常量的原因:因为底层的数组被final修饰了,一旦被final修饰,数组地址值直接锁死,不能更改
3.String的创建
1.String() -> 根据无参构造创建String对象(对象创建出来了,但是字符串没有内容)
2.String(String str) ->利用String字符串创建一个String对象
3.String(char[] chars)-> 利用char数组创建一个String对象
4.String(byte[] bytes)-> 利用byte数组创建一个String对象(通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String)
平台:操作系统
我们的操作系统默认字符集:GBK
一个汉字在GBK中:占2个字节
一个汉字在UTF-8中:占3个字节
注意:在idea中,编写的代码都是按照UTF-8进行编码的,因为idea在执行的过程中
会添加一个启动参数:-Dfile.encoding=UTF-8
5.简化:String 变量名 = ""
public class Demo02String {
public static void main(String[] args) {
//1.String() -> 根据无参构造创建String对象(对象创建出来了,但是字符串没有内容)
String s1 = new String();
System.out.println("s1 = " + s1);
//2.String(String str) ->利用String字符串创建一个String对象
String s2 = new String("abc");
System.out.println("s2 = " + s2);
//3.String(char[] chars)-> 利用char数组创建一个String对象
char[] chars = {'a', 'b', 'c'};
String s3 = new String(chars);
System.out.println("s3 = " + s3);
/*
4.String(byte[] bytes)-> 利用byte数组创建一个String对象(通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String)
如果我们字节传递的是负数,会代表中文(中文对应的字节都是负数)
平台:操作系统
我们的操作系统默认字符集:GBK
一个汉字在GBK中:占2个字节
一个汉字在UTF-8中:占3个字节
注意:在idea中,编写的代码都是按照UTF-8进行编码的,因为idea在执行的过程中
会添加一个启动参数:-Dfile.encoding=UTF-8
*/
byte[] bytes = {97,98,99};
String s4 = new String(bytes);
System.out.println("s4 = " + s4);
System.out.println("==========================");
byte[] bytes1 = {-27,-101,-67};
String s5 = new String(bytes1);
System.out.println("s5 = " + s5);
}
}
扩展构造:
1.String(byte[] bytes, int offset, int length) -> 将字节数组的一部分转成String
bytes:要转的数组
offset:从数组的哪个索引开始转
length:转多少个
2.String(char[] value, int offset, int count)-> 将字符数组的一部分转成String
value:要转的数组
offset:从数组的哪个索引开始转
count:转多少个
public class Demo03String {
public static void main(String[] args) {
/*
1.String(byte[] bytes, int offset, int length) -> 将字节数组的一部分转成String
bytes:要转的数组
offset:从数组的哪个索引开始转
length:转多少个
*/
byte[] bytes = {97,98,99,100,101,102};
String s = new String(bytes, 2, 3);
System.out.println("s = " + s);
System.out.println("==============================");
/*
2.String(char[] value, int offset, int count)-> 将字符数组的一部分转成String
value:要转的数组
offset:从数组的哪个索引开始转
count:转多少个
*/
char[] chars = {'a', 'b', 'c', 'd', 'e', 'f'};
String s1 = new String(chars, 2, 3);
System.out.println("s1 = " + s1);
}
}
4.String 面试题
public class Demo04String {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1==s2);//true
System.out.println(s1==s3);//false
System.out.println(s2==s3);//false
}
}
1.问题: String s = new String("abc") 共有几个对象? -> 2个 -> abc,以及new对象
2.问题: String s = new String("abc") 共创建了几个对象? 1个或者2个
5.字符串常见问题
public class Demo05String {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = "hello"+"world";
String s5 = s1+s2;
String s6 = s1+"world";
System.out.println(s3==s4);//true
System.out.println(s3==s5);//false
System.out.println(s3==s6);//false
}
}
二、String的方法
1.判断方法
1.boolean equals(Object obj) ->比较字符串内容
2.boolean equalsIgnoreCase(String s) -> 比较字符串内容,忽略大小写 -> 常见于验证码对比使用
public class Demo01String {
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
boolean result01 = s1.equals(s2);
System.out.println("result01 = " + result01);
System.out.println("===========================");
String s3 = "ABc";
boolean result02 = s1.equalsIgnoreCase(s3);
System.out.println("result02 = " + result02);
System.out.println("===========================");
//String s4 = "壹贰叁";
//String s5 = "一二三";
//System.out.println(s4.equalsIgnoreCase(s5));
}
}
2.练习1
已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录成功与否,给出相应的提示
public class Demo02String {
public static void main(String[] args) {
//1.创建Scanner对象
Scanner sc = new Scanner(System.in);
//2.定义两个字符串,代表已经注册过的用户名和密码
String username = "root";
String password = "root";
//3.循环录入3次用户名和密码,跟已知的username和password做比较
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String name = sc.next();
System.out.println("请输入密码:");
String pwd = sc.next();
if (name.equals(username) && pwd.equals(password)) {
System.out.println("登录成功");
break;//结束循环
} else {
if (i == 2) {
System.out.println("账号冻结");
} else {
System.out.println("登录失败");
}
}
}
}
}
public class Demo03String {
public static void main(String[] args) {
String s = null;
method(s);
}
/**
* s是一个变量,我们如果用s去调用equals,如果s接收的是null
* 那么就会出现空指针异常
*
* 所以,为了防止空指针异常 -> 我们应该将确定的字符串放equals前面
*
*
* 解决方案2:Objects工具类
* boolean equals(v1,v2) -> 可以比较字符串,但是可以防空指针
* @param s
*/
private static void method(String s) {
/* if ("abc".equals(s)){
System.out.println("是abc");
}else{
System.out.println("不是abc");
}*/
if (Objects.equals("abc",s)){
System.out.println("是abc");
}else {
System.out.println("不是abc");
}
}
}
3.获取功能
1.String concat(String str) 拼接字符串,返回一个新串
2.char charAt(int index) 根据索引获取对应的字符
3.int indexOf(String str) 根据指定的字符串获取对应的第一次出现的索引
4.String substring(int beginIndex) 从指定的索引位置开始截取字符串到最后,返回一个新串儿
5.String substring(int beginIndex,int endIndex)从beginIndex截取到endIndex,返回一个新串儿
含头不含尾
6.int length() 获取字符串长度
public class Demo04String {
public static void main(String[] args) {
String s = "abcdefg";
//1.String concat(String str) 拼接字符串,返回一个新串
String newStr1 = s.concat("hahah");
System.out.println("newStr1 = " + newStr1);
//2.char charAt(int index) 根据索引获取对应的字符
char data = s.charAt(2);
System.out.println("data = " + data);
//3.int indexOf(String str) 根据指定的字符串获取对应的第一次出现的索引
System.out.println(s.indexOf("c"));
//4.String substring(int beginIndex) 从指定的索引位置开始截取字符串到最后,返回一个新串儿
System.out.println(s.substring(2));
//5.String substring(int beginIndex,int endIndex)从beginIndex截取到endIndex,返回一个新串儿
//含头不含尾
System.out.println(s.substring(2,4));
//6.int length() 获取字符串长度
System.out.println(s.length());
}
}
4.练习
遍历字符串
public class Demo05String {
public static void main(String[] args) {
String s = "abcdefg";
for (int i = 0;i<s.length();i++){
System.out.println(s.charAt(i));
}
}
}
5.转换功能
1.char[] toCharArray() -> 将字符串转成char数组
2.byte[] getBytes() -> 将字符串转成byte数组
3.String replace(CharSequence target, CharSequence replacement)->将target指定的字符串替换成replacement指定的串儿
String类是CharSequence接口的实现类
4.byte[] getBytes(String charsetName)->将字符串按照指定的编码规则去转成byte数组
charsetName:不区分大小写
public class Demo06String {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "abcdefg";
//1.char[] toCharArray() -> 将字符串转成char数组
char[] chars = s.toCharArray();
/*
println是一个方法,是PrintStream类中的一个方法
System.out其实返回的对象就是PrintStream对象
PrintStream中的print方法以及println方法
有直接输出char数组的方法
*/
System.out.println(chars);
//2.byte[] getBytes() -> 将字符串转成byte数组
byte[] bytes = "abcdefg".getBytes();
System.out.println(Arrays.toString(bytes));
byte[] bytes1 = "你".getBytes();
System.out.println(Arrays.toString(bytes1));
//3.String replace(CharSequence target, CharSequence replacement)->将target指定的字符串替换成replacement指定的串儿
//String类是CharSequence接口的实现类
String newStr = s.replace("a", "z");
System.out.println("newStr = " + newStr);
//4.byte[] getBytes(String charsetName)->将字符串按照指定的编码规则去转成byte数组
//charsetName:不区分大小写
byte[] bytes2 = "你".getBytes("GBK");
System.out.println(Arrays.toString(bytes2));
}
}
6.分割功能
1.String[] split(String regex) -> 按照指定规则(正则表达式)分割字符串,返回的是字符串数组
public class Demo08String {
public static void main(String[] args) {
/*
1.String[] split(String regex) -> 按照指定规则(正则表达式)分割字符串,返回的是字符串数组
*/
String s = "abc,java,txt";
String[] split = s.split(",");
/*
增强for
1.格式:
for(元素类型 变量名 : 要遍历的集合名或者数组名){
变量名:代表每一个元素
}
2.快捷键:
数组名或者集合名.for
*/
for (String element : split) {
System.out.println(element);
}
System.out.println("======================");
/*
split方法参数位置其实传递的是正则表达式
1.所谓的正则表达式其实就是字符串的一种规则
2.正则作用: 对字符串进行校验, 比如校验邮箱,手机号,用户名等
.在正则表达式中代表的是任意字符
需要转义: \\.
*/
String s1 = "java.txt";
String[] split1 = s1.split("\\.");
for (String element : split1) {
System.out.println(element);
}
}
}
三、其他方法
boolean contains(CharSequence s) -> 判断字符串中是否包含指定的串儿
boolean endsWith(String suffix) -> 判断字符串是否以指定的串儿结尾
boolean startsWith(String prefix) -> 判断字符串是否以指定的串儿开头
String toLowerCase() -> 将大写字母转成小写
String toUpperCase() -> 将小写字母转成大写
String trim() -> 去掉字符串两端空格
public class Demo09String {
public static void main(String[] args) {
String s = "abcdefg";
//boolean contains(CharSequence s) -> 判断字符串中是否包含指定的串儿
System.out.println(s.contains("ab"));
//boolean endsWith(String suffix) -> 判断字符串是否以指定的串儿结尾
System.out.println(s.endsWith("g"));
//boolean startsWith(String prefix) -> 判断字符串是否以指定的串儿开头
System.out.println(s.startsWith("a"));
//String toLowerCase() -> 将大写字母转成小写
System.out.println("SDFADS".toLowerCase());
//String toUpperCase() -> 将小写字母转成大写
System.out.println(s.toUpperCase());
//String trim() -> 去掉字符串两端空格
String s1 = " a b c ";
System.out.println(s1);
System.out.println(s1.trim());
System.out.println(s1.replace(" ",""));
}
}
四、String新特性_文本块
预览的新特性文本块在Java 15中被最终确定下来,Java 15之后我们就可以放心使用该文本块了。
JDK 12引入了Raw String Literals特性,但在其发布之前就放弃了这个特性。这个JEP与引入多行字符串文字(文本块)在意义上是类似的。Java 13中引入了文本块(预览特性),这个新特性跟Kotlin中的文本块是类似的。
现实问题
在Java中,通常需要使用String类型表达HTML,XML,SQL或JSON等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。
文本块就是指多行字符串,例如一段格式化后的XML、JSON等。而有了文本块以后,用户不需要转义,Java能自动搞定。因此,文本块将提高Java程序的可读性和可写性。
目标
-
简化跨越多行的字符串,避免对换行等特殊字符进行转义,简化编写Java程序。
-
增强Java程序中字符串的可读性。
举例
会被自动转义,如有一段以下字符串:
<html>
<body>
<p>HelloWorld</p>
</body>
</html>
将其复制到Java的字符串中,会展示成以下内容:
"<html>\n" +
" <body>\n" +
" <p>Hello, 尚硅谷</p>\n" +
" </body>\n" +
"</html>\n";
即被自动进行了转义,这样的字符串看起来不是很直观,在JDK 13中,就可以使用以下语法了:
"""
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
使用“”“作为文本块的开始符和结束符,在其中就可以放置多行的字符串,不需要进行任何转义。看起来就十分清爽了。
文本块是Java中的一种新形式,它可以用来表示任何字符串,并且提供更多的表现力和更少的复杂性。
(1)文本块由零个或多个字符组成,由开始和结束分隔符括起来。
-
开始分隔符由三个双引号字符表示,后面可以跟零个或多个空格,最终以行终止符结束。
-
文本块内容以开始分隔符的行终止符后的第一个字符开始。
-
结束分隔符也由三个双引号字符表示,文本块内容以结束分隔符的第一个双引号之前的最后一个字符结束。
以下示例代码是错误格式的文本块:
String err1 = """""";//开始分隔符后没有行终止符,六个双引号最中间必须换行
String err2 = """ """;//开始分隔符后没有行终止符,六个双引号最中间必须换行
如果要表示空字符串需要以下示例代码表示:
String emp1 = "";//推荐
String emp2 = """
""";//第二种需要两行,更麻烦了
(2)允许开发人员使用“\n”“\f”和“\r”来进行字符串的垂直格式化,使用“\b”“\t”进行水平格式化。如以下示例代码就是合法的。
String html = """
<html>\n
<body>\n
<p>Hello, world</p>\n
</body>\n
</html>\n
""";
(3)在文本块中自由使用双引号是合法的
String story = """
Elly said,"Maybe I was a bird in another life."Noah said,"If you're a bird , I'm a bird."
""";
五、StringBuilder类
1.StringBuilder的介绍
1.概述:和StringBuffer一样都是一个可变的字符序列(底层自带缓冲区,说白就是没有被final修饰的byte数组),此类提供一个与 StringBuffer 兼容的 API
2.作用:主要是为了拼接字符串
3.问题:拼接字符串我们可以直接用String拼接,那么为啥还要学StringBuilder呢?
a.String每拼接一次,都会产生一个新的字符串对象,如果拼接次数多,会占用内存,而且拼接效率比较低
b.StringBuilder底层自带一个缓冲区,拼接的字符串内容都会在这个缓冲区中保存,在拼接的过程中不会随意产生新的对象
4.StringBuilder的特点:
a.底层是一个没有被final修饰的数组(自带的缓冲区),没有被final修饰为了好扩容
b.底层的缓冲区默认长度为16,拼接的字符串内容都会在这个缓冲区中存储
c.如果超出了缓冲区长度,会自动扩容(创建一个新的数组,指定新长度,将老数组中的元素复制到新数组中去,然后将新数组地址值给老数组)
d.扩容多少倍呢? -> 默认是2倍+2
如果一次性拼接存储的字符个数没有超过默认的扩容机制,就按照2倍+2去扩容
如果一次性拼接存储的字符个数超过了默认的扩容机制,就按照实际拼接存储的字符个数来扩容
2.StringBuilder的使用
1.构造:
a.StringBuilder()
b.StringBuilder(String str)
public class Demo01StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb);
System.out.println("======================");
StringBuilder sb1 = new StringBuilder("abc");
System.out.println("sb1 = " + sb1);
}
}
1.常用方法:
a.StringBuilder append(任意类型) 字符串拼接,返回的是StringBuilder自己
b.StringBuilder reverse() -> 将StringBuilder中的内容翻转,返回的还是StringBuilder自己
c.String toString() -> 将StringBuilder转成String
因为用StringBuilder主要是拼接字符串快,省空间,拼接完之后,如果我们需要对拼接好的字符串内容进行操作,就需要调用String中的方法,所以我们需要将StringBuilder对象转成String对象
public class Demo02StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
//StringBuilder sb1 = sb.append("张无忌");
//System.out.println(sb);
//System.out.println(sb1);
//System.out.println(sb==sb1);
sb.append("张无忌");
/*
链式调用
*/
sb.append("赵敏").append("周芷若").append("涛哥").append("柳岩");
/*
System.out -> 返回的是PrintStream对象
在这个基础上就可以继续调用PrintStream对象中的println方法
也是链式调用
*/
System.out.println(sb);
sb.reverse();
System.out.println(sb);
String s = sb.toString();
System.out.println(s.length());
}
}
练习:键盘录入一个字符串,判断此字符串是否为"回文内容"
上海自来水来自海上
山西运煤车煤运西山
蝶恋花香花恋蝶
鱼游水美水游鱼
abcba
public class Demo03StringBuilder {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String data = sc.next();
//1.创建StringBuilder对象
StringBuilder sb = new StringBuilder();
//2.拼接数据
sb.append(data);
//3.数据翻转
sb.reverse();
//4.将StringBuilder转成字符串
String s = sb.toString();
//5.判断翻转之前和翻转之后的内容是否相等
if (data.equals(s)){
System.out.println("是回文内容");
}else{
System.out.println("不是回文内容");
}
}
}
String,StringBuilder,StringBuffer区别:
1.相同点:都可以字符串拼接
2.不同点:
a.String:每拼接一次都会产生新的对象,占用内存,拼接效率低
b.StringBuilder:不会随意产生新对象,效率高,线程不安全
c.StringBuffer:不会随意产生新对象,效率低,线程安全
3.从拼接效率来说:
StringBuilder>StringBuffer>String
原文地址:https://blog.csdn.net/NJG1013/article/details/145260846
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!