日期
第一代
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;
public class Main {
public static void main(String[] args) throws ParseException {
//两种构造器的使用
//1、获取当前系统时间
Date d1 = new Date();
//默认输出的日期格式是国外的方式,需要对格式进行转换
System.out.println(d1.toString());
//获取对应的毫秒数 getTime()
long millTimes = d1.getTime();
//2、通过指定毫秒数获取时间
Date d2 = new Date(9234567);
System.out.println(d2);
//指定相应的格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
String format = sdf.format(d1);
System.out.println(format);
//可以把一个格式化的String转成对应的Date
//得到Date在输出时,还是按照国外的形式,如果希望指定格式输出,需要转换
//在把String => Date, 使用的sdf格式需要和你给的String的格式一样,否则会抛出转换异常
String s = "1996年01月01日 10:20:30 星期一";
Date parse = sdf.parse(s);
System.out.println(parse);
}
}
第二代Calendar(日历)
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Main {
public static void main(String[] args) {
//1、Calendar是一个抽象类,并且构造器是protected
//2、可以通过getInstance()来获取实例
//3、没有专门的格式化类,需要自己组合显示
//4、按照24小时进制来获取时间 Calendar.HOUR_OF_DAY
Calendar c = Calendar.getInstance();//创建日历类对象
System.out.println(c);//输出有很多字段
//获取日历对象的某个日历字段
System.out.println("年 " + c.get(Calendar.YEAR));
//返回月的时候是按照 0 开始编号
System.out.println("月 " + (c.get(Calendar.MONTH) + 1));
System.out.println("日 " + c.get(Calendar.DAY_OF_MONTH));
System.out.println("小时 " + c.get(Calendar.HOUR));
System.out.println("分钟 " + c.get(Calendar.MINUTE));
System.out.println("秒 " + c.get(Calendar.SECOND));
}
}
第三代
LocalDate(年月日)
LocalTime(时分秒)
LocalDateTime(日期+时间)
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
//1、使用now()返回表示当前日期时间的对象
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
System.out.println(ldt.getYear());
System.out.println(ldt.getMonth());//月,英文单词
System.out.println(ldt.getMonthValue());//月,具体的数
System.out.println(ldt.getDayOfMonth());//日
//2、of() 获取指定的时间
LocalDateTime localDateTime = LocalDateTime.of(2022,12,5,11,23,45);
System.out.println(localDateTime);
//3、使用DateTimeFormatter对象进行格式化
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH小时mm分钟ss秒");
String format = dtf.format(ldt);
System.out.println(format);
}
}
String
final
:String是不可被继承的,赋值后不可修改(地址不可以修改,内容可以变化)。
Serializable
:可序列化的接口。凡是实现此接口的类的对象就可以通过网络或本地流进行数据的传输(序列化)。
Comparable
:凡是实现此接口的类,其对象都可以比较大小。在这个接口里面有抽象方法,String类实现了这个接口里面的抽象方法,指明了怎么算叫“大”,怎么算叫“小”,给了一种标准(重写了方法)。
CharSequence
:字符序列。
可以看到String类实现了相关的接口,没有明显地写父类,也就是说它是继承Object类的。
两种创建String对象的区别
字符串常量池不允许存放两个相同的字符串常量。
方式一:直接赋值 String s = "hsp";
String可以通过字面量的方式来定义。字符串放在了字符串常量池当中,如果有直接指向,没有则重新创建然后指向,最终指向的是常量池的空间地址
方式二:调用构造器 String s = new String("hsp");
先在堆中创建空间,里面维护了value属性,指向常量池的abc地址。如果没有则重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址
String的不可变性
1、当对字符串变量重新赋值时,需要重新指定一个字符串常量的位置进行赋值,不能在原有的位置修改。
2、当对现有的字符串进行拼接操作时,需要重新开辟空间保存拼接以后的字符串,不能在原有的位置修改。
String a = "hello" + "abc"; ==> String a = "helloabc" 只创建了一个对象
常量 + 常量 并没有创建新的对象
3、当调用字符串的replace()
替换现有的某个字符时,需要重新开辟空间保存修改以后的字符串,不能在原有的位置修改。
String与基本数据类型、包装类之间的转换
//基本数据类型 => String
int num = 10;
String s1 = num + "";
String s2 = String.valueOf(num);
//String => 基本数据类型
String s3 = "1234"'
int num = Integer.parseInt(s3);
//String => char[]
char[] arr = str.toCharArray();
//char[] => String
String str = new String(arr);
String的常见方法
StringBuffer
public class StringBuffer01 {
public static void main(String[] args) {
//1. StringBuffer 的直接父类 是 AbstractStringBuilder
//2. StringBuffer 实现了 Serializable, 即StringBuffer的对象可以串行化
//3. 在父类中 AbstractStringBuilder 有属性 char[] value,不是final
// 该 value 数组存放 字符串内容,引出存放在堆中的
//4. StringBuffer 是一个 final类,不能被继承
//5. 因为StringBuffer 字符内容是存在 char[] value, 所有在变化(增加/删除)
// 不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String
StringBuffer stringBuffer = new StringBuffer("hello");
}
}
String 和 StringBuffer 相互转换
public class StringAndStringBuffer {
public static void main(String[] args) {
//看 String——>StringBuffer
String str = "hello tom";
//方式1 使用构造器
//注意: 返回的才是StringBuffer对象,对str 本身没有影响
StringBuffer stringBuffer = new StringBuffer(str);
//方式2 使用的是append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str);
//看看 StringBuffer ->String
StringBuffer stringBuffer3 = new StringBuffer("韩顺平教育");
//方式1 使用StringBuffer提供的 toString方法
String s = stringBuffer3.toString();
//方式2: 使用构造器来搞定
String s1 = new String(stringBuffer3);
}
}
StringBuffer 类常见方法
public class StringBufferMethod {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("hello");
//增
s.append(',');// "hello,"
s.append("张三丰");//"hello,张三丰"
s.append("赵敏").append(100).append(true).append(10.5);//"hello,张三丰赵敏100true10.5"
System.out.println(s);//"hello,张三丰赵敏100true10.5"
//删
/*
* 删除索引为>=start && <end 处的字符
* 解读: 删除 11~14的字符 [11, 14)
*/
s.delete(11, 14);
System.out.println(s);//"hello,张三丰赵敏true10.5"
//改
//使用 周芷若 替换 索引9-11的字符 [9,11)
s.replace(9, 11, "周芷若");
System.out.println(s);//"hello,张三丰周芷若true10.5"
//查找指定的子串在字符串第一次出现的索引,如果找不到返回-1
int indexOf = s.indexOf("张三丰");
System.out.println(indexOf);//6
//插
//在索引为9的位置插入 "赵敏",原来索引为9的内容自动后移
s.insert(9, "赵敏");
System.out.println(s);//"hello,张三丰赵敏周芷若true10.5"
//长度
System.out.println(s.length());//22
System.out.println(s);
}
}
比较
① StringBuilder 和StringBuffer 非常相似,均代表可变的字符序列,而且方法也一样;
② String:不可变字符序列,效率低,但是复用率高;
③ StringBuffer:可变字符序列、效率较高(增删)、线程安全(适合多线程);
④ StringBuilder:可变字符序列、效率最高、线程不安全(适合单线程);
⑤ 效率:StringBuilder > StringBuffer > String
选择
① 如果字符串存在大量的修改操作,一般男使用StringBuffer和StringBuilder;
② 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder;
③ 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer;
④ 如果字符串存在很少量的修改操作,被多个对象引用,使用String,比如配置信息等。