声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)
往期回顾
Java学习day18:IO流(一篇文章知识点详解)-CSDN博客
Java学习day19:StringBuffer类、枚举类enum
一、StringBuffer类
通过看API官方手册我们知道StringBuffer类是一个线程安全的,可变的字符序列,String 不可变
用final修饰的,所以不能被继承
1.常用方法
|------------------------------|--------------------------------------|
| append(" string str "); | //追加数据,直接拼接在后面 |
| insert(int i, "string str"); | //插入 这个int i 就是下标索引 |
| reverse() | //字符串反转 |
| delet(int start, int end) | //删除一个字符串 始终记得 要头不要尾 start包含 end 不包含 |
示例:
package com.qfedu.a_stringbuffer;
public class Demo1 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
//构造一个没有字符的字符串缓冲区(容器),初始容量为16个字符。
//在整个缓冲去放数据,放啥数据?字符串!!!
System.out.println(sb);
sb.append("xi");//追加
sb.append("he");
sb.append("ha");
//插入 这个2 就是下标索引
sb.insert(2, "gou");
System.out.println(sb);//xigouxihehehaha
//字符串反转
System.out.println(sb.reverse());//ahahehehixuogix
//删除一个字符串delet(int start, int end)
//不要怀疑 始终记得 要头不要尾 start包含 end 不包含
System.out.println(sb.delete(1,3));
}
}
2.String、Stringbuffer、StringBuilder
关于StringBuffer的代码相当简单,应该说大家是都会的,但是底层和面试问的东西比较深的所以一定看看一些东西。
2.1有String了为啥还要学习StringBuffer和StringBuilder?
因为拼接字符串的效率不一样的。
//字符串String 拼接的是时候,效率底 + concat()
//StringBuffer 和StringBuilder拼接字符串效率高
//为啥StringBuffer和StringBuilder高,为啥String效率低
//如果使用String拼接100个字符串,会出来100个对象 因为String 不可变的
String str = "123";
str += "457";
str += "457";
str += "457";
str += "457";
//以上有几个对象? 6个
2.2面试题:String、Stringbuffer、StringBuilder区别
参考博文:String、StringBuilder和StringBuffer三者区别_string,stringbuffer以及stringbuilde三者之间的区别?-CSDN博客
示例验证:
public class Test {
public static void main(String[] args) {
//String 连接10000次消耗1127ms
//StringBuffer 连接10000次消耗5ms
//StringBuilder 连接10000次消耗3ms
StringTest(10000);
StringBufferTest(10000);
StringBuilderTest(10000);
}
public static void StringTest(int n){
String str = "";
//获取当前系统的时间 还没有执行下面for循环的时候的时间
Long startTime = System.currentTimeMillis();
//使用for循环来拼接!!!
for(int i=0;i<n;i++){
str += i;
}
//获取当前系统的时间 执行下面for循环的时候的时间
Long endTime = System.currentTimeMillis();
System.out.println("String 连接"+ n +"次消耗"+(endTime-startTime)+"ms");
}
public static void StringBufferTest(int n){
StringBuffer str = new StringBuffer();
Long startTime = System.currentTimeMillis();
for(int i=0;i<n;i++){
str.append(i);
}
Long endTime = System.currentTimeMillis();
System.out.println("StringBuffer 连接"+ n +"次消耗"+(endTime-startTime)+"ms");
}
public static void StringBuilderTest(int n){
StringBuilder str = new StringBuilder();
Long startTime = System.currentTimeMillis();
for(int i=0;i<n;i++){
str.append(i);
}
Long endTime = System.currentTimeMillis();
System.out.println("StringBuilder 连接"+ n +"次消耗"+(endTime-startTime)+"ms");
}
}
我们可以清楚的看到String的字符串的连接效率是最低的,这一点对于大量字符串的拼接可以很明显的表示出来,所以说大量字符串的拼接最好不要选择String。StringBuffer和StringBuilder对于字符串的拼接效率是大致相同的。
再问:为啥StringBuilder效率高?
因为StringBuilder是线程不安全的,StringBuffer线程安全
3.总结
|---------------------------------------------------------------------|
| 1.String为固定长度的字符串,StringBuilder和StringBuffer为变长字符串; |
| 2.stringBuffer是线程安全的,StringBuilder是非线程安全的; |
| 3.StringBuffer和StringBuilder的默认初始容量是16,可以提前预估好字符串的长度,进一步减少扩容带来的额外开销 |
二、枚举类enum
Java 中的枚举是一个特殊的类,枚举就是用来表示常量的,只不过是常量的换一种写法而已!!!
一般来说,这个常量都是用final修饰的,所以对同一个常量,即使用不同方式获得,其hash值都是一样的
对于定义的枚举类型数组,其内存地址绝对不会再改变,也就不会在内存中有额外的开销
2.1语法格式
public enum 枚举类名 {
//下面写常量,常量之间使用逗号隔开
}
记得不是分号,是用逗号隔开,全部常量写完了才加分号
示例:
public enum Color {
//常量,一般都是大写的 没有任何数据类型的!!!
RED, GREEN, BLUE
}
枚举类的实例用法:
//声明一个枚举类 是一个特殊的类
enum Color2 {
RED, GREEN, BLUE
}
public class Demo2 {
public static void main(String[] args) {
//RED这个数据 属于Color2这个类的实例的
//Color2.RED 为啥可以用类名.常量 常量是static修饰的!!!
Color2 red = Color2.RED;
System.out.println(red);//RED
Color2 green = Color2.GREEN;
System.out.println(green);
}
}
可以看到是直接用类名.名字调用的,跟静态常量static修饰的一样。
2.2枚举在swicth-case中的使用
看这个之前先回顾一个知识点,switch-case里可以使用的数据类型有哪些?
byte,short,int,char,string,枚举
为什么没有long,因为switch语句中的表达式A的取值只能是整型或者可以转换为整型的数值类型,而int到long是需要强转的,这中间存在数据丢失的问题,所以没有long
而为什么在swicth-case使用枚举,因为可以通过switch-case将咱们的常量变成咱们所需要的数据类型
示例:
enum Color3 {
RED, GREEN, BLUE
}
//可以通过switch-case将咱们的常量变成咱们所数据类型
//RED===》红色
//只是一个用判断的一个东西
public class Demo3 {
public static void main(String[] args) {
Color3 red = Color3.RED;
switch (red) {
case RED:
System.out.println("红色");
break;
case GREEN:
System.out.println("绿色");
break;
case BLUE:
System.out.println("蓝色");
break;
}
}
}
本来是Color类的red,但是当满足case的情况下,就需要执行里面的,此时就可以转变为其他数据类型。
2.3枚举类中的几个方法
|------------|-----------------|
| values(); | 枚举类中所有的值,返回值是数组 |
| ordinal(); | 可以找到每个枚举类中常量的索引 |
| valueOf(); | 返回值的是指定字符串的枚举常量 |
示例:
enum Color4 {
RED, GREEN, BLUE
}
public class Demo4 {
public static void main(String[] args) {
//values();枚举类中所有的值
//ordinal();可以找到每个枚举类中常量的索引
//valueOf();返回值的是指定字符串的枚举常量
Color4[] values = Color4.values();//返回是数组
//增强for循环遍历
for (Color4 value : values) {
System.out.println(value + "对应的索引:" + value.ordinal());
}
//valueOf返回的是字符串的枚举常量对象
//只是换了一种写法而已。
//通过常量所对应的字符串获取常量的对象
Color4 red = Color4.valueOf("RED");
//一般开发使用Color4.RED;
Color4 red1 = Color4.RED;
System.out.println(red);
System.out.println(red.hashCode());
System.out.println(red1);
System.out.println(red1.hashCode());
}
}
这里就是获取枚举常量对象的两种方法:
1.直接枚举类名.常量对象
2.调用方法valuesOf()
但是记得,对同一个枚举常量对象,不管用怎样的方法获取,其hash值都是一样的。
2.4枚举在真实的开发中使用
在很多时候我们定义一些状态量都是使用0或者1,-1这样在数据库中定义,这样的数据存放在数据库的相应字段中方便数据读取,但是只存储数字,如果定义的表很多,对应的字段也很多,设计的状态就非常多,编码很容易分辨不清楚,一方面去数据库中查看相应字段的注释非常费时间,而且容易产生差错,如果我们使用枚举类,这个问题就很好的解决了。
比如当我们定义了许多状态量,比如订餐支付,未支付,订单的完结,派送,制作等有许多状态,如果不使用枚举,我们在代码层进行判断的时候总是要去思考这个状态是定义的什么呢,0还是-1呢,当项目比较大的时候,光靠我们记是不行的,干脆我们就使用枚举来简化我们的编程,而且还较少了逻辑上出错的可能。
在这种情况下我们就引入了枚举常量
示例:
enum ProductEnum {
UP(0, "在架"),
DOWN(1, "下架");
private Integer code;
private String message;
ProductEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
public class Demo5 {
public static void main(String[] args) {
System.out.println(ProductEnum.UP.getCode());
System.out.println(ProductEnum.UP.getMessage());
System.out.println(ProductEnum.DOWN.getCode());//1
System.out.println(ProductEnum.DOWN.getMessage());//"下架"
}
}
分析这段代码里,首先枚举是一个类,所以是可以有构造方法的,而且这里还必须加构造方法,同时加上对应的setter、getter方法。
在调用的时候也是类名.常量.方法去获取。
以上,就是今天的所有知识点了。StringBuffer类、enum枚举类是java中非常常用的类,大家得多花点时间,静下心看代码,写代码,多理解,多运用,重点是多去运用。
加油吧,预祝大家变得更强!