课前回顾:
1.final
修饰类:不能被继承
修饰方法:不能被重写
修饰局部变量:不能被二次赋值
修饰对象:地址值不能变,但内容可以变
修饰成员变量:不能被二次赋值,需要手动赋值
2.内部类:
匿名内部类:
new 父类/接口(){
重写方法
}.重写的方法()
父类/接口 对象名 = new 父类/接口(){
重写方法
};
对象名.重写的方法()
3.异常:
Throwable
Error
Exception:
编译时期异常:Exception以及除RuntimeException之外的子类
运行时期异常:RuntimeException以及子类
创建异常:
throw new 异常对象
处理异常:
throws:如果处理多个异常,多个异常之间有子父类继承关系,我们可以直接抛父类
try...catch:
如果处理多个异常,多个异常之间有子父类继承关系,我们可以直接捕获父类
finally:和try...catch结合使用,表示一定要执行的代码
多用在关闭资源方面
自定义异常:
定义一个类,如果继承Exception,表示编译时期异常;如果继承RuntimeException,表示运行时期异常
查看异常信息的方法:Throwable
getMessage():获取异常信息
toString():获取异常类型以及信息
printStackTrace():输出的异常信息是最前全的
Object:所有类的根类,所有类都会直接或者间接继承Object
toString()->返回对象的字符串表示形式
如果想要输出对象名不是地址值的话,就重写toString
equals()->比较对象的地址值
如果想要比较对象的内容,就重写equals方法
今日重点:
1.String的创建以及方法的使用
2.记住String的一个面试题
3.会使用StringBuilder去做字符串拼接
第一章.Object类
1.Object的介绍
1.概述:
所有类的根类(父类)
2.注意:
所有的类都会直接或者间接的去继承Object类
如果一个类没有明确的写出extends 父类,此类的父类就是Object
2.Object类中的toString方法
1.Object类中的toString方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
返回对象的字符串表示形式
2.总结:
我们输出对象名,如果没有重写Object类中的toString方法,默认调用的是Object中的toString,直接输出的就是地址值
如果我们重写了toString方法,那么默认就调用重写后的toString了,如果重写的toString返回还是地址值,重写无意义,所以我们重写toString之后,应该返回属性值
3.结论:
如果想输出的对象名不是地址值,就重写Object类中的toString方法
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("柳岩", 36);
System.out.println(person);
System.out.println(person.toString());
ArrayList<String> list = new ArrayList<>();
list.add("孙悟空");
list.add("后裔");
list.add("嫦娥");
System.out.println(list);//[猪八戒,太上老君,玉皇大帝]
System.out.println(list.toString());//[猪八戒,太上老君,玉皇大帝]
}
}
3.Object类中的equals方法
1.Object类中的equals方法
public boolean equals(Object obj) {
return (this == obj);
}
==:
如果是基本类型:比较的是值
如果是引用类型:比较的是地址值
2.总结
如果没有重写equals方法,默认调用Object中的equals方法,比较的是地址值
如果重写了equals方法,再比较地址值就没有意义了,我们应该重写之后比较对象的内容(属性值)
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/*
问题1:obj接受的是Person,obj是Object类型,用obj.name和age不行的
因为name和age是Person的特有成员,多态情况下,调用不了
解决1:
将obj向下转型
问题2:
如果重写的equals方法接受的不是Person类型,会导致强转异常
解决2:
先判断,再向下转型
问题3:
如果调用equals方法传递null咋整
解决3:
提前做非空判断
问题4:
如果调用equals方法传递自己咋整
解决4:
提前判断,如果是自己,直接return true
*/
/* public boolean equals(Object obj){
if (this==obj){
return true;
}
//非空判断
if (obj==null){
return false;
}
if (obj instanceof Person){
Person person2 = (Person)obj;
return this.name.equals(person2.name) && this.age==person2.age;
}
return false;
}*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("柳岩", 36);
Person person2 = new Person("柳岩", 36);
System.out.println(person1.equals(person2));//false
ArrayList<String> list = new ArrayList<>();
System.out.println(person1.equals(list));
System.out.println(person1.equals(null));
System.out.println(person1.equals(person1));
}
}
小结:
如果想输出对象名不是地址值而是属性值,重写toString
如果想比较两个对象的属性值,重写equals方法
4.Object类中的getClass()方法
Class<?> getClass() -> 获取的是类对象->设计到反射
Person p1 = new Person("柳岩",36);
Class aClass = p1.getClass();
System.out.println(aClass);
运行结果:class com.atguigu.p_object.Person
将来学反射,需要记住的单词:
Class 类
Method 成员方法
Constructor 构造方法
Field 成员变量
5.native方法
private static native void registerNatives();
static {
registerNatives();//注册本地方法
}
方法作用:当该类被加载的时候,调用该方法完成对该类中本地方法的注册
在Object类中,除了有registerNatives这个本地方法之外,还有hashCode()、clone()等本地方法,而在Class类中有forName0()这样的本地方法等等。也就是说,凡是包含registerNatives()本地方法的类,同时也包含了其他本地方法。所以,显然,当包含registerNatives()方法的类被加载的时候,注册的方法就是该类所包含的除了registerNatives()方法以外的所有本地方法
registerNatives()注册当前类的本地方法
native:修饰符,关键字-->代表的是本地的
1.注意:本地方法不是一个抽象方法
2.本地方法是有方法体的:C语言编写,本地方法的方法体源码没有开源,简单理解为本地方法对Java语言的扩展
比如后面io流部分,Java本身没有读写功能,调用的都是操作系统的读写功能
而操作系统上的读写功能用的就是native修饰
windows系统就是C语言写的
3.位置:本地方法栈
4.意义:给系统打交道
小结:
1.native的方法在本地方法栈中运行
2.native是C语言编写,所以我们看不到方法体
3.registerNatives()代表的是注册当前类中的本地方法
java语言有很多功能没有,很多时候就需要调用c语言编写的本地方法去完成需求
而native是独立于jdk之外的,所以我们想使用本地方法之前,需要利用registerNatives()将本地方法注册进来,才能使用
6.GC垃圾回收简介
运行垃圾回收器,JVM将从堆内存中清理对象,清理对象的同时会调用对象的finalize()方法,JVM的垃圾回收器是通过另一个线程开启的,因此程序中的效果并不明显。
public class Person {
@Override
protected void finalize() throws Throwable {
System.out.println(this+"....."+"被回收了!");
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person);
person = null;
System.gc();
}
}
public static void gc()->System类中的方法,运行垃圾回收器
GC:什么时候回收(如果我们的对象没有用)
比如:Person p = new Person()
p = null;
GC ROOTS-->根据可达性分析算法判断这个对象的引用是否到GC ROOTS中,如果从GC ROOTS
出发,找不到对应的引用,它会自动判断这个对象该死
构造方法:创建对象
析构函数:销毁对象 这是c中有的 java中没有析构函数这个概念
finalize():在回收之前,会自动调用此方法,当然不是垃圾回收器调用的,是本类调用的,是垃圾回收器通知当前类调用的此方法
垃圾回收关键点:
1.垃圾回收机制只回收JVM堆内存里的对象空间。
2.对其他物理连接,比如数据库连接(Connection)、输入流输出流(IO)、Socket连接(网络编程)无能为力
3.现在的JVM有多种垃圾回收实现算法,表现各异。
4.垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行
5.可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。
6.程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有
一些效果,但是系统是否进行垃圾回收依然不确定。
7.垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。
8.永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。
第二章.String
1.String介绍
1.概述:代表的是字符串
2.特点:
a.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现
凡是带""的都是String类的一个对象
String s = "abc";
b.字符串是常量,它们的值在创建之后不能更改
String s = "hello";
s+="world";//"helloworld"
c. String 对象是不可变的,所以可以共享
String a = "abc"
String b = "abc";
2.String的实现原理
1.实现原理:String底层就是一个数组
2.jdk8: String底层是一个char[] -> 一个char 占 内存 2个字节
jdk9: String底层是一个byte[] -> 一个byte 占 内存 1个字节
3.注意:
我们创建的字符串都会自动放到数组中
String s = "abc"-> char[] value = {'a','b','c'}
private final char value[];
数组的前面的修饰符final, 最终的数组,数组一旦建立,数组的地址就被锁死(常量)使用常量的原因,为了线程安全
3.String的创建
String() ->利用空参构造创建String对象
String(String original)->利用有参构造创建String对象
String(char[] value) ->根据char[]数组创建String对象
String(byte[] bytes)->通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
简化:
String 变量名 = "" -> 最常用的一种字符串创建方式
public class Demo01String {
public static void main(String[] args) {
//String() ->利用空参构造创建String对象
String s1 = new String();
System.out.println(s1);
//String(String original)->利用有参构造创建String对象
String s2 = new String("abc");
System.out.println(s2);
//String(char[] value) ->根据char[]数组创建String对象
char[] chars = {'a','b','c'};
String s3 = new String(chars);
System.out.println(s3);
/*
String(byte[] bytes)->通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
平台:指的是操作系统 操作系统默认编码集为GBK
IDEA:运行的时候添加了一个启动参数,而启动参数将idea运行时遵循的编码设置成了utf-8
在utf-8编码中 3个字节代表一个中文
在GBK中 2个字节代表一个中文
*/
byte[] bytes = {-28, -67, -96};
String s4 = new String(bytes);
System.out.println(s4);
}
}
扩展构造:
String(byte[] bytes, String charsetName) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。,可以根据我们指定的字符集去创建String对象
String(byte[] bytes, int offset, int length) :将byte数组的一部分转成String
bytes:要转的数组
offset:从数组的哪个索引开始转
length:转多少个
String(char[] value, int offset, int count) :将char数组的一部分转成String
value:要转的数组
offset:从数组的哪个索引开始转
count:转多少个
public class Demo02String {
public static void main(String[] args) throws UnsupportedEncodingException {
/*
String(byte[] bytes, String charsetName) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
可以根据我们指定的字符集去创建String对象
*/
byte[] bytes = {-28, -67, -96,-27, -91, -67};
String s1 = new String(bytes,"GBK");
System.out.println(s1);
/*
String(byte[] bytes, int offset, int length) :将byte数组的一部分转成String
bytes:要转的数组
offset:从数组的哪个索引开始转
length:转多少个
*/
byte[] bytes1 = {97,98,99,100};
String s2 = new String(bytes1,0,2);
System.out.println(s2);//ab
/*
String(char[] value, int offset, int count) :将char数组的一部分转成String
value:要转的数组
offset:从数组的哪个索引开始转
count:转多少个
*/
char[] chars = {'a','b','c','d'};
String s3 = new String(chars,1,3);
System.out.println(s3);//bcd
}
}
4.String 面试题
public class Test04 {
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(s2==s3);//false
}
}
String s = new String("abc"), 创建了几个对象?
1个或者2个
1个: 如果"abc"提前创建出来了,那么String s = new String("abc")就创建了一个
2个: 如果"abc"没有提前创建出来,那么String s = new String("abc"),就创建了两个
首先自己会先将"abc"创建出来,其次new
5.字符串常见问题
public class Test05 {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = "hello"+"world";
String s5 = s1+"world";
String s6 = s1+s2;
System.out.println(s3==s4);//true
System.out.println(s3==s5);//false
System.out.println(s4==s5);//false
System.out.println(s3==s6);//false
}
}
如果定义字符串等号右边是字符串字面值,都是在常量池中
如果定义字符串等号右边有变量参与,会在堆内存中创建新的对象,开辟新的空间
以上代码反编译结果:
第三章.String的方法
1.判断方法
- public boolean equals (Object anObject) :比较字符串内容(双引号里面的)是否相等
- public boolean equalsIgnoreCase (String anotherString) :比较字符串内容(双引号里面的)是否相等,忽略大小写
public class Demo01Equals {
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
//- public boolean equals (Object anObject) :比较字符串内容(双引号里面的)是否相等
boolean equals = s1.equals(s2);
System.out.println(equals);
//- public boolean equalsIgnoreCase (String anotherString) :比较字符串内容(双引号里面的)是否相等,忽略大小写
String s3 = new String("ABC");
System.out.println(s3.equals(s1));
System.out.println(s3.equalsIgnoreCase(s1));
}
}
2.练习1
已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
步骤:
1.定义两个已知的字符串 分别代表username 和 password
2.创建Scanner对象
3.循环输入,如果输入的用户名和密码跟已知的username 和 password相等,证明登录成功
4.否则,登录失败
public class Demo02EqualsTest {
public static void main(String[] args) {
//定义已知的用户名和密码
String username = "root";
String password = "1234";
//创建Scanner对象
Scanner sc = new Scanner(System.in);
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("登录成功");
}else{
if (i==2){
System.out.println("账号冻结");
}else{
System.out.println("登录失败");
}
}
}
}
}
在开发中,如何正确判断String的内容呢?
public class Demo03Equals {
public static void main(String[] args) {
String s = null;
method(s);
}
private static void method(String s) {
/*
如果将s放在前面调用equals方法,由于s是一个变量,将来s接收的值不一定是啥
如果s接收的是null就会出现空指针
所以我们可以将固定的字符串放在前面调用equals方法,防止空指针
*/
/*if (s.equals("abc")){
System.out.println("s的内容是abc");
}*/
if ("abc".equals(s)){
System.out.println("s的内容是abc");
}
}
}
3.获取功能
- public int length () :返回此字符串的长度。
- public String concat (String str) :将指定的字符串连接到该字符串的末尾。
- public char charAt (int index) :返回指定索引处的 char值。
- public int indexOf (String str) :获取的是指定字符串在老串中第一次出现的索引位置
- public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
- public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。
public class Demo04Get {
public static void main(String[] args) {
String s = "abcdef";
//- public int length () :返回此字符串的长度。
System.out.println(s.length());
//- public String concat (String str) :将指定的字符串连接到该字符串的末尾。,返回一个新串
String s1 = s.concat("hahah");
System.out.println(s1);
System.out.println(s);
//- public char charAt (int index) :返回指定索引处的 char值。
char s2 = s.charAt(2);
System.out.println(s2);
//- public int indexOf (String str) :获取的是指定字符串在老串中第一次出现的索引位置
int index = s.indexOf("a");
System.out.println(index);
//- public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
String substring = s.substring(2);
System.out.println(substring);
/*- public String substring (int beginIndex, int endIndex) :
返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。*/
String substring1 = s.substring(2, 4);
System.out.println(substring1);
}
}
4.练习2
遍历字符串
public class Demo05GetTest {
public static void main(String[] args) {
String s = "abcdef";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
System.out.println(c);
}
System.out.println("==============");
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
}
5.练习3
在控制台输出结果。例如,数组为 int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
public class Demo06GetTest {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
String str = "[";
for (int i = 0; i < arr.length; i++) {
if (i==arr.length-1){
str = str+arr[i]+"]";
}else{
str = str+arr[i]+",";
}
}
System.out.println(str);
}
}
6.转换功能
- public char[] toCharArray () :将此字符串转换为新的字符数组。
- public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
- public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使用replacement字符串替换。
public class Demo07ZhuanHuan {
public static void main(String[] args) {
String s = "abc";
//- public char[] toCharArray () :将此字符串转换为新的字符数组。
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
//- public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
byte[] bytes = s.getBytes();
System.out.println(Arrays.toString(bytes));
/*- public String replace (CharSequence target, CharSequence replacement) :
将与target匹配的字符串使用replacement字符串替换。*/
String s1 = s.replace("a", "z");
System.out.println(s1);
}
}
7.练习4
键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
步骤:
1.创建Scanner对象,调用next方法录入一个字符串 abbcAA
2.定义三个变量,分别统计大写,小写,数字字符的个数
int big = 0;
int small = 0;
int number = 0;
3.遍历字符串,将每一个字符获取出来
如何判断大写字母? B 66 A-Z->整数范围是:65-90 如果字符对应的int值在65-90之间,证明是大写字母
big++
如何判断小写字母? a-z->整数范围是:97-122 如果字符对应的int值在97-122之间,证明是小写字母
small++
如何判断数字? '0'-'9'->整数范围是:48-57 如果字符对应的int值在48-57之间,证明是数字
number++
public class Demo08ZhuanHuanTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//统计大写字母个数
int big = 0;
//统计小写字母个数
int small = 0;
//统计数字个数
int number = 0;
System.out.println("请你输入一个字符串:");
String data = sc.next();
//遍历字符串
char[] chars = data.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c>='A' && c<='Z'){
big++;
}
if (c>='a' && c <='z'){
small++;
}
if (c>='0' && c<='9'){
number++;
}
}
System.out.println("大写字母个数为:"+big);
System.out.println("小写字母个数为:"+small);
System.out.println("数字个数为:"+number);
}
}
8.分割功能
public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。
public class Demo09Split {
public static void main(String[] args) {
String s = "abc,txt";
String[] split = s.split(",");
System.out.println(Arrays.toString(split));
String s1 = "abc.txt";
String[] split1 = s1.split("\\.");
System.out.println(Arrays.toString(split1));
}
}
第四章.扩展方法
boolean contains(CharSequence s) :判断老串中是否包含指定的串儿
boolean endsWith(String suffix) :判断字符串是否以指定的串儿结尾
boolean startsWith(String prefix) :判断字符串是否以指定的串儿开头
String toLowerCase() :将字符串转成小写
String toUpperCase() :将字符串转成大写
String trim() :去掉字符串两端空格
public class Demo10Other {
public static void main(String[] args) {
String s = "abcdefg";
//boolean contains(CharSequence s) :判断老串中是否包含指定的串儿
System.out.println(s.contains("a"));
//boolean endsWith(String suffix) :判断字符串是否以指定的串儿结尾
System.out.println(s.endsWith("fg"));
//boolean startsWith(String prefix) :判断字符串是否以指定的串儿开头
System.out.println(s.startsWith("abc"));
//String toLowerCase() :将字符串转成小写
String s1 = "ABCDEFG";
System.out.println(s1.toLowerCase());
//String toUpperCase() :将字符串转成大写
System.out.println(s.toUpperCase());
String s2 = "ABC1212abc";
System.out.println(s2.toUpperCase());
//String trim() :去掉字符串两端空格
System.out.println("========================");
String s3 = " abc d e ";
System.out.println(s3);
String trim = s3.trim();
System.out.println(trim);
System.out.println("=============去掉所有空格=============");
String replace = s3.replace(" ", "");
System.out.println(replace);
}
}
第五章.StringBuilder
1.StringBuilder的介绍
1.为什么学:如果要是用String做字符串拼接,每拼接一次,都会产生一个新的串儿,就会在堆内存中产生一个新的空间
耗费内存,所以出现了StringBuilder来代替String做字符串拼接
2.概述:
一个可变的字符序列
3.特点:
a.StringBuilder底层是一个char[] value;没有被final修饰
b.StringBuilder创建出来自带一个缓冲区(char[]),默认长度为16
c.如果拼接字符串,所有的字符串都会在这个缓冲区保存,不会在堆内存中产生新的串儿,始终就这一个StringBuilder对象,不会产生新的对象
d.如果超过了16,StringBuilder中的缓冲区(char[])自动扩容
注意:扩容并不是直接改变底层数组的长度,而是采用了(Arrays.copyOf->数组复制)
e.扩容多少: 2倍+2
2.StringBuilder的使用
1.构造:
StringBuilder()->创建一个StringBuilder对象 缓冲区是空的
StringBuilder(String str)->创建一个StringBuilder对象 缓冲区存好了str
public class Test01StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb);
StringBuilder sb1 = new StringBuilder("abc");
System.out.println(sb1);
}
}
StringBuilder的方法:
StringBuilder append(任意类型数据)->数据拼接,返回的是StringBuilder自己
StringBuilder reverse() -> 字符串翻转->返回的StringBuilder,也是自己
String toString()->将StringBuilder转成String对象
public class Test02StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
StringBuilder sb1 = sb.append("哈哈哈");
System.out.println(sb);
//链式调用
sb.append(1).append("孙悟空").append("唐僧");
System.out.println(sb);
System.out.println("=======================");
sb.reverse();
System.out.println(sb);
System.out.println("=======================");
//String toString()->将StringBuilder转成String对象
String s = sb.toString();
System.out.println(s.length());
}
}
//判断字符串是否对称
public class Test03StringBuilder {
public static void main(String[] args) {
String s = "蝶恋花香花恋蝶";
StringBuilder sb = new StringBuilder(s);
sb.reverse();
String s1 = sb.toString();
if (s.equals(s1)){
System.out.println("对称");
}
}
}
3.练习
定义一个方法,按照指定格式打印数组元素。例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
public class Test04StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("[");
int[] arr = {1,2,3,4};
for (int i = 0; i < arr.length; i++) {
if (i==arr.length-1){
sb.append(arr[i]).append("]");
}else{
sb.append(arr[i]).append(", ");
}
}
System.out.println(sb.toString());
}
}
4.String 和StringBuilder以及StringBuffer区别
String:
效率低
StringBuilder和StringBuffer区别
StringBuilder:
线程不安全,线程不同步
效率高
StringBuffer:
线程安全
效率比StringBuilder低
从拼接效率上来看,三者排序(由快到慢)
StringBuilder>StringBuffer>String