String不可变性、日期时间相关类(Java学习笔记七)
String类
代表字符串。String是一个final类,代表不可变的字符序列(不可变特性),也不可被继承。
字符串是常量,用双引号引起来表示,它们的值在创建后不能更改。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final byte[] value; private final byte coder; }
说明:
- String类实现了Serializable接口,表示字符串支持序列化。
- String类实现了Comparable接口,表示字符串支持比较大小。
- String对象的字符内容是存储在一个不可变字符数组value[]中的。
String的不可变性:
- 通过字面量的方式(不同于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中(String Pool,存在于方法区),且存储在value[]中。
- String Pool中不会存储相同内容的字符串。当字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value[]赋值(原有value[]不可变)。
- 当对现有字符串进行连接、String.replace()等任何修改操作时,同样都需要指定内存区域重新赋值。
两种赋值方式:
String str1 = "hello";//String Pool中 String str2 = "hello";//String Pool中 String str3 = new String("hello");//堆空间中开辟内存 String str4 = new String("hello");//堆空间中开辟内存 System.out.println(str1 == str2);//true System.out.println(str1 == str3);//false System.out.println(str1 == str4);//false System.out.println(str3 == str4);//false
不同拼接方式:
常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
只要其中有一个是变量,结果就在堆中 。
如果拼接的结果调用intern()方法,返回值就在常量池中
String s1 = "hello"; String s2 = "world"; String s3 = "helloworld";//String Pool中 String s4 = "hello"+"world";//String Pool中 String s5 = s1 + "world";//堆中 String s6 = "hello" + s2;//堆中 String s7 = s1 + s2;//堆中 System.out.println(s3 == s4);//true System.out.println(s3 == s5);//false System.out.println(s3 == s6);//false System.out.println(s3 == s7);//false System.out.println(s4 == s6);//false System.out.println(s5 == s6);//false
String常用方法
- int length():返回字符串的长度: return value.length 。
- charAt(int index):返回某索引处的字符return value[index] 。
- boolean isEmpty():判断是否是空字符串:return value.length == 0 。
- String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写 。
- String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写 。
- String trim():返回字符串的副本,忽略前导空白和尾部空白。
- boolean equals(Object obj):比较字符串的内容是否相同 。
- boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写。
- String concat(String str):将指定字符串连接到此字符串的结尾。等价于用“+” 。
- int compareTo(String anotherString):比较两个字符串的大小 。
- String substring(int beginIndex):返回一个新的字符串,它是此字符串的 beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
- boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束 。
- boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始 。
- boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
- boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true。
- int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引 。
- int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
- int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引。
- int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 (注:indexOf和lastIndexOf方法如果未找到都是返回-1)。
- String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用newChar 替换此字符串中出现的所有 oldChar 得到的。
- String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列,替换此字符串所有匹配字面值目标序列的子字符串。
- String replaceAll(String regex, String replacement) :使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
- String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此 字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中
- 字符串->字节数组 public byte[] getBytes() :使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
- public byte[] getBytes(String charsetName) :使用指定的字符集将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
-
String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
-
public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
-
String 类的构造器:String(char[]) 和 String(char[],int offset,int length) 分别用字符数组中的全部字符和部分字符创建字符串对象。
-
Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
-
调用String类的public String valueOf(int n)可将int型转换为字符串
StringBuffer和StringBuilder
String:不可变字符序列,线程安全;底层使用char[]存储。
StringBuffer:可变的字符序列,线程安全的,内部使用 synchronized 进行同步,但是效率偏低;底层使用char[]存储。
StringBuilder:可变的字符序列,效率高,但不是线程安全;底层使用char[]存储(JDK5后新增)。
(多线程需要操作共享数据时建议使用StringBuffer(int capacity);其余情况建议使用StringBuilder(int capacity))
效率:StringBuilder > StringBuffer > String。
源码分析:
String str = new String();// 底层new char[0] String str = new String(“abc”);// 底层new char[]{‘a’,‘b','c'};
StringBuffer sb1 = new StringBuffer();//底层char[] value = new char[16],创建了一个长度为16的数组。建议指定这个容量。 System.out.println(sb1.length());//0 sb1.append('a');//value[0] = 'a'; sb1.append('b');//value[1] = 'b'; //如果底层数组容量不够,则需要扩容。默认情况下扩容为原来的2倍,同时将原有数组中的元素复制到新的数组中。 StringBuffer sb2 = new StringBuffer("abc"); //底层char[] value = new char["abc".length()+16],创建了一个长度为"abc".length()+16的数组 System.out.println(sb2.length());//3
相关常用方法:
- StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接 。
- 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() :把当前字符序列逆转。
- (当append和insert时,如果原来value数组长度不够,可扩容。且如上方法支持方法链原理)
- public int indexOf(String str) :同String。
- public String substring(int start,int end) :同String。
- public int length() :同String。
- public char charAt(int n ) :同String。
- public void setCharAt(int n ,char ch):将下表为n的元素改为ch。
日期时间
JDK8之前
java.lang.System类:
System类提供的public static long currentTimeMillis()用来返回当前时 间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
java.util.Date类:
表示特定的瞬间,精确到毫秒。子类java.sql.Date,和数据库中的Date类型相应。转换时:
Date date = new Date(); java.sql.Date dateSql = new java.sql.Date(date.getTime());
- 构造器: Date():使用无参构造器创建的对象可以获取本地当前时间。
- Date(long date):指定毫秒数。
-
getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象 表示的毫秒数。
java.text.SimpleDateFormat类:
Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat 类是一个不与语言环境有关的方式来格式化和解析日期的具体类。
两大操作:1.格式化;2.解析。
- SimpleDateFormat() :默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern):该构造方法可以用参数pattern 指定的格式创建一个对象,该对象调用:public String format(Date date):方法格式化时间对象date 解析:public Date parse(String source):从给定字符串的开始解析文本,以生成一个日期。
Date date = new Date(); // 产生一个Date实例 // 产生一个formater格式化的实例 SimpleDateFormat formater = new SimpleDateFormat(); System.out.println(formater.format(date));// 2020/5/31 下午2:30 SimpleDateFormat formater2 = new SimpleDateFormat("yyyy年MM月dd日 EEE HH:mm:ss"); System.out.println(formater2.format(date));//2020年05月31日 周日 14:30:52 try { // 实例化一个指定的格式对象 Date date2 = formater2.parse("2008年08月08日 星期一 08:08:08"); // 将指定的日期解析后格式化按指定的格式输出 System.out.println(date2.toString());//Fri Aug 08 08:08:08 CST 2008 } catch (ParseException e) { e.printStackTrace(); }
java.util.Calendar(日历)类
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
获取Calendar实例的方法 :
- 使用Calendar.getInstance()方法
- 调用它的子类GregorianCalendar的构造器
一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想要的时间信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、 MINUTE、SECOND
- public void get(int field,int value)
- public void set(int field,int value)
- public void add(int field,int amount)
- public final Date getTime()
- public final void setTime(Date date)
注意: 获取月份时:一月是0,二月是1,以此类推,12月是11;获取星期时:周日是1,周二是2 ,以此类推,周六是7
Calendar c = Calendar.getInstance(); int day = c.get(Calendar.DAY_OF_MONTH);//今天是这个月的第几天 int day1 = c.get(Calendar.DAY_OF_WEEK);//今天是这个周的第几天 int day2 = c.get(Calendar.DAY_OF_YEAR);//今天是这个周的第几天 c.set(Calendar.DAY_OF_MONTH,22);//把这个月第几天这个值,改成22号 c.add(Calendar.DAY_OF_MONTH,5);//在当前“这个月第几天”这个值的基础上加5天,负数即减几天 Date date = c.getTime();//Calendar转换为Date对象,输出 Wed May 27 21:08:10 CST 2020 c.setTime(date);//把Date对象转回Calendar对象
JDK8之后
新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间 (LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime) 和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法, 用于把 Date 转换成新的表示形式。这些新增的本地化时间日期API 大大简 化了日期时间和本地化的管理。
LocalDate、LocalTime、LocalDateTime
这三个类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。 它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区 相关的信息。
- LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期。
- LocalTime表示一个时间,而不是日期。
- LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。
方法 | 描述 |
---|---|
now() / * now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
of() | 静态方法,根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHour()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
LocalDateTime now = LocalDateTime.now();//实例化对象(现在是2020年5月31日 21:23) System.out.println(now.getDayOfMonth());//31 System.out.println(now.getHour()); //21 System.out.println(now.getYear()); //2020
Instant
时间线上的一个瞬时点。这可能被用来记录应用程序中的事件时间戳。
java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间 单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。 概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。(类似于Date,返回举例1970年1月1日0时0分0秒的秒数)
方法 | 描述 |
---|---|
now() | 静态方法,返回默认UTC时区的Instant类的对象 |
ofEpochMilli(long epochMilli) | 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒 数之后的Instant类的对象 |
atOffset(ZoneOffset offset) | 结合即时的偏移来创建一个 |
OffsetDateTime toEpochMilli() | 返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳 |
DateTimeFormatter
该类提供了三种格式化方法 ,用于格式化与解析日期或时间:
- 预定义的标准格式。如: ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
- 本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
- 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
方法 | 描 述 |
---|---|
ofPattern(String pattern), | 静态方法 , 返回一个指定字符串格式的 DateTimeFormatter |
format(TemporalAccessor t) | 格式化一个日期、时间,返回字符串 |
parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、时间 |
- Thinking in java学习笔记之String的不可变性
- 【Java学习笔记】String相关语句
- Java8学习笔记(九)--日期/时间(Date Time)API指南
- Java学习笔记(6): 时间与日期
- Java学习笔记——日期时间类
- JavaSE入门学习32:Java常用类之时间日期相关类
- openerp学习笔记 日期时间相关操作
- java学习笔记24——String类不可变性
- java笔记之Object,String,StringBuilder,StringBuffer,时间类和日期类以及包装类
- java学习笔记-String相关知识点
- Java基础学习笔记二十 时间处理相关类
- 【Java学习笔记】浅析字符串相关类:String、StringBuffer与StringBuilder
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
- JAVA学习笔记:编程常用类-日期时间Date类(java.util.Date)
- Java学习笔记-日期和时间
- openerp学习笔记 日期时间相关操作
- JAVA时间日期学习笔记
- JAVA String 不可变性 / Hibernate_Validator学习
- 【Java学习笔记】String对象的不变性和intern()方法——基于Java SE8
- java JDK8 学习笔记——第13章 时间与日期