package com.xt.java1;
import org.junit.Test;
import java.util.Date;
/**
* ClassName: StringBufferBuilder
* Description:关于StringBuffer和StringBuilder的使用
* date: 2022/4/17 17:28
*
* @author tongy
* @since JDK 1.8
*/
public class StringBufferBuilder {
/*
String StringBuffer StringBuilder的异同?相同:底层都是用char[]存储
String 不可变的字符序列
StringBuffer 可变的字符序列,线程安全,效率低
StringBuilder 可变的字符序列,线程不安全,效率高
源码分析:
String s=new String();//char[] value = new char[0]
String s1=new String("abc"); //char[] value = new char[]{'a','b','c'};
StringBuffer sb1=new StringBuffer(); //char[] value = new char[16];底层创建了一个长度是16的数组
sb1.append('a');//value[0]='a';
sb1.append('b');//value[1]='b';
StringBuffer sb2=new StringBuffer("abc");//char[] value=new char["abc".length()+16]
问题1.System.out.println(sb2.length()); //3
问题2.扩容问题:如果要添加的数据底层盛不下了,那就需要扩容底层的数组。
默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。
指导意义:开发中建议大家使用:StringBuffer(int capacity)或StringBuilder(int capacity)
String和StringBuffer、StringBuilder之间的转换
String-->StringBuffer\StringBuilder 调用StringBuffer\StringBuilder的构造器
StringBuffer\StringBuilder --> String ①调用String的构造器 ②调用StringBuffer、StringBuilder的构造器
*/
/*
JVM中字符串常量池存放位置说明:
jdk 1.6(jdk 6.0 java 6.0):字符串常量池存储在方法区(永久区)
jdk 1.7:字符串常量池存储在堆空间
jdk 1.8:字符串常量池存储在方法区(元空间)
*/
@Test
public void test1(){
StringBuffer sb1=new StringBuffer("abc");
sb1.setCharAt(0,'m');
System.out.println(sb1);
StringBuffer sb2=new StringBuffer();
System.out.println(sb2.length()); //0而不是16
}
@Test
public void test2(){
/*
StringBuffer的常用方法:
StringBuffer append(xxx) 添加
StringBuffer delete(int start,int end) 删除指定位置内容
StringBuffer replace(int start,int end,String str):把[start,end)位置替换为str
StringBuffer insert(int offset,xxx) 在指定位置插入xxx
StringBuffer reverse() 把当前字符序列逆转
substring(int start,int end) 返回子串,原串不改变
总结:
增:append(xxx)
删:delete(int start,int end)
改:setCharAt(int n,char ch) / replace(int start,int end,String str)
查:charAt(int n)
插:insert(int offset,xxx)
长度:length()
*遍历:
String、StringBuilder、StringBuffer三者的效率:
高到低的排序:StringBuilder > StringBuffer > String
*/
StringBuffer sb1=new StringBuffer("abc");
sb1.append(1);
sb1.append('1');
System.out.println(sb1);
// System.out.println(sb1.delete(2, 4));
sb1.replace(2,4,"hello");
sb1.insert(2,"xwq");
System.out.println(sb1.substring(2, 5));
System.out.println(sb1.reverse());
}
/*
java.util.Date类:
|---java.sql.Data类
两个构造器的使用:
>构造器1:new Date():创建一个对应当前时间的Date对象
>构造器2:创建指定毫秒数的Date
两个方法的使用:
>toString():显式当前的年、月、日、时、分、秒
>getTime():返回当前与1970年1月1日0时0分0秒之间的毫秒差;获取当前Date对象对应的时间戳
java.sql.Date对应着数据库中的日期类型变量
>如何实例化
>sql.Date --> util.Date对象(直接赋值,多态)
>如何将 java.util.Date对象 --> java.sql.Date对象
*/
@Test
public void test3(){
//构造器1:new Date():创建一个对应当前时间的Date对象
Date date = new Date();
System.out.println(date.toString());
System.out.println(date.getTime());
//构造器2:创建指定毫秒数的Date
Date date1 = new Date(1650193066396L);
System.out.println(date1);
//创建一个java.sql.Date对象
java.sql.Date date2 = new java.sql.Date(76547653788L);
System.out.println(date2);
//如何将 java.util.Date对象 --> java.sql.Date对象
//情况1:多态、强转
Date date3=new java.sql.Date(8765432456789876L);
java.sql.Date date4=(java.sql.Date) date3;
//情况2:
Date date5=new Date();
java.sql.Date date6=new java.sql.Date(date5.getTime());
}
}
package com.xt.exer;
import org.junit.Test;
/**
* ClassName: test1
* Description:一个面试题
* date: 2022/4/18 21:44
*
* @author tongy
* @since JDK 1.8
*/
public class test1 {
@Test
public void test(){
String str=null;
StringBuffer sb1=new StringBuffer();
sb1.append(str);
System.out.println(sb1.length()); //4 是"null"长度
System.out.println(sb1); //"null"
StringBuffer sb2=new StringBuffer(str);
System.out.println(sb2); //异常 NullPointerException
}
}