5.1 String类和StringBuffer类
Java中定义了String和StringBuffer两个类来封装字符创, 并提供了一系列操作字符串的方法。它们都位于java.lang包中,因此不需要导包就可直接使用。
5.1.1 String类的初始化
操作String类之前,需要对String类进行初始化。通过两种方式对String类进行初始化。
1.使用字符串常量直接初始化一个String对象,语法格式
String 变量名 = 字符串;
String str1 = null;//初始化为空 String str2 = "";//初始化为空字符串 String str3 = "abc";//初始化为abc,其中abc为字符串常量
2.使用String的构造方法初始化字符串对象,语法格式
String 变量名 = new String(字符串);
上述语法中,字符串同样可以为空或是一个具体的字符串。当为具体字符串时,会使用String类的不同参数类型的构造方法来初始化字符串对象。
String类中包含多个构造方法,常用构造方法
方法声明 | 功能描述 |
---|---|
String() | 创建一个内容为空的字符串 |
String(String value) | 根据指定的字符串内容创建对象 |
String(char[] value) | 根据指定的字符数组创建对象 |
String类通过构造方法初始化字符串对象
public class Example01 {
public static void main(String[] args) {
//创建一个空的字符串
String str1 = new String();
//创建一个内容为abc的字符串
String str2 = new String("abc");
//创建一个内容为字符数组的字符串
char[] charArray = new char[]{'A','B','C'};
String str3 = new String(charArray);
System.out.println("a"+str1+"b");
//在Java中,如果+的两边操作数有一个为String类型,+就表示字符串连接运算符
System.out.println(str2);
System.out.println(str3);
}
}
5.1.2 String类的常见操作
String类的常用方法
方法声明 | 功能描述 |
---|---|
int indexOf(int ch) | 返回指定字符在此字符串中第一次出现处的索引 |
int lastIndexOf(int ch) | 返回指定字符在此字符串中最后一次出现处的索引 |
int indexOf(String str) | 返回指定子字符串在此字符串中第一次出现处的索引 |
int lastIndexOf(String str) | 返回指定子字符串在此字符串中最后一次出现处的索引 |
char charAt(int index) | 返回字符串中index位置上的字符,其中index的取值范围是:0-(字符串长度-1) |
boolean endsWith(String suffix) | 判断此字符串是否以指定的字符串结尾 |
int length() | 返回此字符串的长度 |
boolean equals(Object anObject) | 将此字符串与指定的字符串比较 |
boolean isEmpty() | 当且仅当字符串长度为0时返回true |
boolean startsWith(String prefix) | 判断此字符串是否以指定的字符串开始 |
boolean contains(CharSequence cs) | 判断此字符串中是否包含指定的字符序列 |
String toLowerCase() | 使用默认语言环境的规则将String中的所有字符都转换为大写 |
String toUpperCase() | 使用默认语言环境的规则将String中的所有字符都转换为小写 |
static String valueOf(int i) | 返回int参数的字符串表示形式 |
char[] toCharArray() | 将此字符串转换为一个字符数组 |
String replace(CharSequence oldstr,CharSequence newstr) | 返回一个新的字符串,它是通过用newstr替换此字符串中出现的所有oldstr得到的 |
String[] split(String regex) | 根据参数regex()(regex是一个正则表达式,用来限定分割规则)将字符串分割为若干个子字符串 |
String substring(int beginIndex) | 返回一个新字符串,它包含从指定的beginIndex起始角标处开始,直到此字符串末尾的所有字符 |
String substring (int beginIndex,int endIndex) | 返回一个新字符串,它包含从指定的beginIndex起始角标处开始,直到索引endIndex-1角标处的所有字符 |
String trim() | 返回一个新字符串,它祛除了原字符串首位的空格 |
1.字符串的基本操作
public class Example02 {
public static void main(String[] args) {
String s = "abcabcabcabcdba";
System.out.println("字符串的长度为"+s.length());
System.out.println("字符串的第一个字符"+s.charAt(0));
System.out.println("字符c第一次出现的位置"+s.indexOf('c'));
System.out.println("字符c最后一次出现的位置"+s.lastIndexOf('c'));
System.out.println("子字符串第一次出现的位置"+s.indexOf("ab"));
System.out.println("子字符串最后一次出现的位置"+s.lastIndexOf("ab"));
}
}
2.字符串的转换操作
public class Example03 {
public static void main(String[] args) {
String str = "java";
char[] charArray = str.toCharArray();
System.out.println("将字符串转为字符数组的遍历结果:");
for (int i = 0; i < charArray.length; i++) {
if(i != charArray.length-1){
System.out.print(charArray[i]+",");
}else{
System.out.println(charArray[i]);
}
}
System.out.println("将int值转换为String类型之后的结果:" +
String.valueOf(12));
System.out.println("将字符串转换成大写之后的结构:" +
str.toUpperCase());
}
}
3.字符串的替换和去除空格操作
public class Example04 {
public static void main(String[] args) {
String s = " http://lo calhos t:8080 ";
System.out.println("去除字符串两端空格后的结果"+s.trim());
System.out.println("去除字符串中所有空格后的结果"+s.replace(" ",""));
}
}
//注意trim()方法只能去除两端的空格,不能去除中间的空格
4.字符串的判断操作
public class Example05 {
public static void main(String[] args) {
String s1 = "Starter";
String s2 = "St";
System.out.println("判断是否以字符St开头:"+s1.startsWith("St"));
System.out.println("判断是够以字符串er结尾:"+s1.endsWith("er"));
System.out.println("判断是否包含字符串ar:"+s1.contains("ar"));
System.out.println("判断字符串是否为空:"+s1.isEmpty());
System.out.println("判断字两个字符串是否相等:"+s1.equals(s2));
}
}
String类中重写了父类Object类的equals()方法。
在程序中可以通过==和quals()两种方式对字符串进行比较,但区别在于,equals()方法用于比较两个字符串中的字符值是否相等,方法用于比较两个字符串对象的内存地址是否相同。所以使用==判断时,结果一定为false.
String str1 = new String("abc"); String str2 = new String("abc"); System.out.println(str1==str2); System.out.println(str1.equals(str2));
5.字符串的截取和分割
public class Example06 {
public static void main(String[] args) {
String str = "2018-01-24";
System.out.println("从第6个字符截取到末尾的结果:" +
str.substring(5));
System.out.println("从第6个字符截取到第7个字符的结果:"+
str.substring(5,7));
System.out.println("分割后的字符串数组中的元素一次为:");
String[] strArray = str.split("-");
for (int i = 0; i < strArray.length; i++) {
if(i != strArray.length-1){
System.out.print(strArray[i]+"、");
}else{
System.out.println(strArray[i]);
}
}
}
}
String字符串在获取某个字符时,会用到字符的索引,当访问字符串中的字符时,如果字符的索引不存在,就会发生StringIndexOutOfBoundsException(字符串角标越界异常)
public class Example07 {
public static void main(String[] args) {
String s = "abcde";
System.out.println(s.charAt(9));
}
}
5.1.3 StringBuffer类
在Java中,由于String类是final类型的,所以使用String定义的字符串是一个常量,一旦创建,内容和长度都不可更改。如需对一个字符串进行修改,则只能创建新的字符串。为了方便对字符串进行修改,JDK提供了一个StringBuffer类(也称字符串缓冲区)来操作字符串。StringBuffer类和String类最大的区别在于它的内容和长度都是可以改变的,类似一个字符容器,在其中田间或删除字符时,所操作的都这个字符容器,因此不会产生新的StringBuffer对象。
StringBuffer类常用方法
方法声明 | 功能描述 |
---|---|
StringBuffer append(char c) | 添加字符到StringBuffer对象中末尾 |
StringBuffer insert(int offset,String str) | 在StringBuffer对象中的offset位置插入字符串str |
StringBuffer deleteCharAt(int index) | 移除StringBuffer对象中指定位置的字符 |
StringBuffer delete(int start,int end) | 删除StringBuffer对象中指定范围的字符或字符串 |
StringBuffer replace(int start,int end,String s) | 将StringBuffer对象中指定范围的字符或字符串用新的字符串s进行替换 |
void setCharAt(int index,char ch) | 修改指定位置index处的字符 |
String toString() | 返回StringBuffer缓冲区中的字符串对象 |
StringBuffer reverse() | 将此StringBuffer对象用其反转形式取代 |
public class Example08 {
public static void main(String[] args) {
System.out.println("1.添加------------");
add();
System.out.println("2.修改------------");
update();
System.out.println("3.删除------------");
delete();
}
//添加
public static void add(){
StringBuffer sb = new StringBuffer();
sb.append("ABC");
System.out.println("append添加结果:"+sb);
sb.insert(3,"DE");
System.out.println("insert添加结果:"+sb);
}
//修改
public static void update(){
StringBuffer sb = new StringBuffer("ABAAA");
sb.setCharAt(2,'C');
System.out.println("修改指定位置字符结果:"+sb);
sb.replace(3,5,"DE");
System.out.println("替换指定位置字符(串)的结果:"+sb);
System.out.println("字符串翻转结果"+sb.reverse());
}
public static void delete(){
StringBuffer sb = new StringBuffer("ABCDEFG");
sb.delete(3,7);
System.out.println("删除指定位置结果:"+sb);
sb.deleteCharAt(2);
System.out.println("删除指定位置结果"+sb);
sb.delete(0,sb.length());
System.out.println("清空缓冲区结果:"+sb);
}
}
StringBuffer类和String类对比:
-
String类定义的字符串是常量,一旦创建后,内容和长度都是无法改变的,StringBuffer表示字符容器,内容和长度都可以随时修改。
-
String类重写了Object类的equals()方法,而StringBuffer类没有重写Object类的equals()方法,
String s1 = new String ("abc"); String s2 = new String ("abc"); System.out.println(s1.equals(s2)); //true StringBuffer sb1 = new StringBuffer("abc"); StringBuffer sb2 = new StringBuffer("abc"); System.out.println(sb1.equals(sb2)); //false
-
String类对象可以用操作符+进行连接,而StringBuffer对象之间不鞥能
String s1 = "a"; String s2 ="b"; String s3 = s1+s2; System.out.println(s3); StringBuffer sb1 = new StringBuffer("a"); StringBuffer sb2 = new StringBuffer("b"); StringBuffer sb3 = sb1 + sb2;//编译出错
除了使用StringBuffer外,JDK1.5之后提供了一个StringBuilder类同样可以操作字符串。StringBuilder与StringBuffer的功能相似,且两个类中提供的方法也基本相同,但是StringBuffer是线程安全的,而StringBuilder没有实现线程安全功能,所以性能略高。通常情况下,如果创建一个内容可变的字符串对象,应该优先考虑StringBuilder类。
StringBuilder类同样提供了一系列添加(append)、插入(insert)、替换(replace)和删除(delete)的方法。
5.2 System类与Runtime类
5.2.1 System类
System类定义了一些与系统相关的属性和方法,它所提供的属性和方法都是静态的。
System类的常用方法
方法声明 | 功能描述 |
---|---|
static void exit(int status) | 该方法用于终止当前正在远行的Java虚拟机,其中参数status表示状态码,若状态码非0,则表示异常终止 |
static void gc() | 运行垃圾回首器,并对垃圾进行回收 |
static native long curentTimeMills() | 返回以毫秒为单位的当前时间 |
static void arraycope(Object src,int srcPos,Object dest,int destPos,ine length) | 从src引用的指定源数组拷贝到dest引用的数组,拷贝从指定的位置开始,到目标数组的指定位置结束 |
static Properties getProperties() | 取得当前的 系统属性 |
static String getProperty(String key) | 获取指定键描述的系统属性 |
1.getProperties()方法
该方法用于获取当前系统的全部属性,会返回一个Properties对象,其中封装了系统的所有属性,这些属性都以键值对的形式存在
import java.util.*;
public class Example09 {
public static void main(String[] args) {
Properties properties = System.getProperties();
System.out.println(properties);
Set<String>propertyNames = properties.stringPropertyNames();
for(String key:propertyNames){
String value = System.getProperty(key);
System.out.println(key+"--->"+value);
}
}
}
系统属性包括: java.vm.version JVM的版本号 user.country 用户的国家 os.arch 操作系统的架构 os.name操作系统名称
2.currentTimeMillis()
返回一个long类型的值,该值表示当前时间与1970年1月1日0点0分0秒之间的时间差,单位是毫秒,通常也叫将该值称作时间戳。
public class Example10 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
int sum = 0;
for (int i = 0; i < 100000000; i++) {
sum +=i;
}
long endTime = System.currentTimeMillis();
System.out.println("程序的运行时间Wie:"+(endTime-startTime)+"毫秒");
}
}
3.arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
用于将一个数组中的元素快速拷贝到另一个数组,其中参数列表的参数:
-
src:表示源数组;
-
dest:表示目标数组:
-
srcPos:表示源数组中拷贝元素的起始位置;
-
destPos:表示拷贝到目标数组的起始位置;
-
length:表示拷贝元素的个数。
-
进行数组拷贝时,目标数组必须由足够的空间来存放拷贝的元素,否则发送角标越界异常
public class Example11 {
public static void main(String[] args) {
int[] srcArray = {101,102,103,104,105,106};
int[] destArray = {201,202,203,204,205};
System.arraycopy(srcArray,2,destArray,0,4);
for (int i = 0; i < destArray.length; i++) {
System.out.println(i+":"+destArray[i]);
}
}
}
使用arraycopy()方法进行数组拷贝时,要保证源数组元素类型和目标数组元素类型一致,否则会出现ArrayStoreException异常。另外,最后一个拷贝元素长度参数length既不能超过截取的源数组从指定位srcPos开始剩余元素的个数,也不能超过目标数组从指定位置destPos开始可容纳的元素个数,否则会出现ArrayIndexOutOfBoundsException异常。
5.2.2 Runtime类
Runtime类用于白氏Java虚拟机运行时的状态,用于封装Java虚拟机进程。每次使用java命令启动Java虚拟机时都会对应一个Runtime实例,并且只有一个实例,应用程序会通过该实例与其运行时的环境相连。应用程序不能创建自己的Runtime实例,若想在程序中获得一个Runtime实例,可以通过getRuntime()方法获取与之相关的Runtime对象
Runtime run = Runtime.getRuntime();
由于Runtime类封装了Java虚拟机进程,因此可以通过该类的实例对象来获取当前虚拟机相关信息
public class Example12 {
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime();
System.out.println("处理器的个数:"+
rt.availableProcessors()+"个");
System.out.println("空闲内存的大小:"+
rt.freeMemory()/1024/1024+"M");
System.out.println("最大可用内存大小:"+
rt.maxMemory()/1024/1024+"M");
}
}
Runtime类中提供了一个exec()方法,该方法用于执行一个DOS命令,从而实现和在命令行窗口中输入DOS命令同样的效果
案例:打开windos自带的记事本
public class Example13 {
public static void main(String[] args) throws Exception{
Runtime rt = Runtime.getRuntime();
rt.exec("notepad.exe");
}
}
Runtime类的exec()方法会返回一个Process对象,该对象表示操作系统的一个进程,此处为notead.exe进程,通过Process对象可以对产生的新进程进行管理,如关闭此进程,只需调用destry()方法即可。
public class Example14 {
public static void main(String[] args) throws Exception {
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("notepad.exe");
Thread.sleep(3000);
process.destroy();
}
}
5.3 Math类与Random类
5.3.1 Math类
Math类是一个工具类,主要用于完成复杂的数学运算。其构造方法被定义为private,因此无法创建Marh类的对象,Math类中所有方法都是静态方法,可以直接通过类名来调用它们。除静态方法外,Math类还有两个静态常量PI和E,分别代表数学中的π和e。
public class Example15 {
public static void main(String[] args) {
System.out.println("计算绝对值的结果:"+Math.abs(-1));
System.out.println("计算正弦的结果:"+Math.sin(1.57));
System.out.println("计算余弦的结果:"+Math.cos(2.0));
System.out.println("计算正切的结果:"+Math.tan(0.8));
System.out.println("计算平方根的结果:"+Math.sqrt(4));
System.out.println("计算立方根的结果:"+Math.cbrt(9));
System.out.println("计算乘方的结果:"+Math.pow(2,2));
System.out.println("求大于参数的最小整数:"+Math.ceil(4.6));
System.out.println("求小于参数的最大整数:"+Math.floor(4.6));
System.out.println("对小数进行四舍五入后的结果股:"+Math.round(-8.6));
System.out.println("求两个数的较大值:"+Math.max(5.1,5.7));
System.out.println("求两个数的较小值:"+Math.min(5.1,5.8));
System.out.println("生成一个大于0.0小于1.0的随机值"+Math.random());
}
}
注意:round()方法会用于对某个小数进行四舍五入,会将小数点后面的数字全部忽略,返回一个int类型的数而ceil()方法和floor()方法返回的都是double类型的数,这个数在数值上等于一个整数。
5.3.2 Random类
在JDK的java.util包中,有一个Random类。可以在指定的取值范围内随机产生数字。该类中提供了两个构造方法。
方法声明 | 功能描述 |
---|---|
Random() | 用于创建一个随机数生成器,每次实例化Random对象会产生不同的随机数 |
Ranfom(long seed) | 使用一个long型的seed(种子)创建伪随机数,当seed相同时,每次实例化Ranodm对象会生成 相同的随机数 |
其中,第一个构造方法是无参的,通过它创阿金的Radnom实例对象每次使用的种子是随机的,因此每个对象所产生的随机数不同,如果希望创建的多个Random实例对象产生相同序列的随机数,则可以在创建对象时掉员工第二个构造方法,传入相同的种子即可。
相比于Math类的random()方法,Random类提供了更多的方法来生成各种伪随机数,不仅可以生成整数类型的随机数,还可以生成浮点类型的随机数。。
Random类的常用方法
方法声明 | 功能描述 |
---|---|
boolean nextBoolean() | 随机生成boolean类型的随机数 |
fouble nextDouble() | 随机生成double类型的随机数 |
float nextFloat() | 随机生成float类型的随机数 |
int nextInt() | 随机生成int类型的随机数 |
int nextInt(int n) | 随机生成[0,n)之间int类型的随机数 |
long nextLong() | 随机生成long类型的随机数 |
next Double()方法返回的是0.0和1.0之间double类型的值,nextFlloat()返回的是0.0和1.0之间float类型的值,nextInt(int n)返回的是0(包括)和指定值n(不包括)之间的值,
import java.util.Random;
public class Example16 {
public static void main(String[] args) {
Random r = new Random();
System.out.println("生成boolean类型的随机数"
+r.nextBoolean());
System.out.println("生成double类型的随机数"
+r.nextDouble());
System.out.println("生成int类型的随机数"
+r.nextInt());
System.out.println("生成0-10之间int类型的随机数"
+r.nextInt(10));
System.out.println("生成long类型的随机数"
+r.nextLong());
}
}
5.4 包装类
虽然Java是面向对象的编程语言,但它提供的8种基本年数据类型却不支持面向对象的编程机制(没有属性和方法)。Java中,很多类的方法都需要接收引用类型的对象,此时就无法将一个基本数据类型的值传入。JDK提供了一系列的包装类,通过这些包装类可以将基本数据类型的值包装为引用数据类型的对象
基本数据类型对应的包装类
基本数据类型 | 对应的包装类 | 基本数据类型 | 对应的包装类 |
---|---|---|---|
byte | Byte | long | Long |
char | Character | float | Float |
int | Integer | double | Double |
short | Short | boolean | Boolean |
包装类和基本数据类型在进行转关时,引入了自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)的概念,其中自动装箱是指将包装类对象类型直接赋给一个对应的基本数据类型变量
public class Example17 {
public static void main(String[] args) {
int a = 20;
Integer b = a;
System.out.println(b);
int c = b;
System.out.println(c);
}
}
通过包装类和自动拆箱、装箱功能,开发人员可以把基本数据类型的变量转换为对象来使用,也可以把宝转给的实例转换为基本类型的变量来使用。
Java中除了支持基本数据类型与对应包装类之间进行转换外,还提供了其他方法来支持基本数据类型、基本数据包装类以及字符串之间的相互转换。
-
通过应用数据类型字符串String类valueOf()方法可以将8种基本数据类型转换为对应的字符串类型;
-
通过8种包装类的静态方法可以将变量内容匹配的字符串转换为对应的包装类(Character包装类除外);
-
通过8种包装类的有参构造方法同样既可以将对应的基本数据类型转换为包装类,也可以将变量内容匹配的字符串转换为对应的包装类Character包装类除外);
-
通过8种包装类的静态方法parseXxx()可以将变量内容匹配的字符串转换为对应的基本数据类型;
-
包装类都重写了Object类中的toString()方法,以字符串的形式返回被包装的基本数据类型的值。
public class Example18 {
public static void main(String[] args) {
int num = 123;
//1.通过String.valueOf()方法将基本类型转换为字符串
String string = String.valueOf(num);
System.out.println("将int变量转换为字符串的结果:"+string);
//2.通过包装类的valueOf()静态方法将基本类型和字符串转换为包装类
String str = "998";
Integer integer = Integer.valueOf(num);
Integer integer2 = Integer.valueOf(str);
System.out.println("将int变量转换为包装类的结果"+integer);
System.out.println("将字符串变量转换为包装类的结果"+integer2);
//3.通过包装类的有参构造方法将基本类型和字符串转换为包装类
Integer integer3 = new Integer(num);
Integer integer4 = new Integer(str);
System.out.println("通过构造器将int变量转换为包装类的结果"
+integer3);
System.out.println("通过构造器将字符串变量转换为包装类的结果"
+integer4);
//4.通过包装类的parseXxx()静态方法将字符串转换为基本数据类型
int parseInt = Integer.parseInt(str);
System.out.println("将字符串转换为基本类型的结果:"+
parseInt);
//5.通过包装类的toString()方法将包装类转换为字符串
String string2 = integer.toString();
System.out.println("将包装类转换为字符串的结果"
+string2);
}
}
注意:
-
除了Character外,包装类都有valueOf(String s)方法,可以根据String类型的参数创建包装类对象,但参数字符串s不能为null,而且字符串必须是可以解析为相应基本类型的数据,否则编译通过但运行报错。
Integer i = Integer.valueOf("123");//合法 Integer i = Integer.valueOf("12a");//不合法
-
除了Character外,包装类都有pareseXxx(String s)的静态方法,将字符串转换为对应的基本类型的数据。参数s不能为null,而且同样是可以解析为相应基本类型的数据,否则编译通过但运行报错。
int i = Integer.parseInt("123");//合法 int i = Integer.parseInt("itcast");//不合法
5.5 日期与时间类
5.5.1 Date类
JDK的java.utl包中,提供了一个Date类用于表示日期和时间,在JDK1.0时就已经开始使用。随着JDK版本的不断升级发展,该类中大部分构造方法和普通方法都已经不再推荐使用。JDK8中,Date类只有两个构造方法是可以使用的
-
Date():用来创建当前日期时间的Date对象;
-
Date(long date):用于创建指定时间的Date对象,其中date参数表示1970年1月1日0时0分0(成为历元)以来的毫秒数,即时间戳。
import java.util.Date;
public class Example19 {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date(System.currentTimeMillis()+1000);
System.out.println(date1);
System.out.println(date2);
}
}
由于Date类在设计之初没有考虑到国际化的问题,从JDK1.1开始,Date类相应的功能也被Calendar类中的方法取代。
5.5.2 Calendar类
用于完成日期和时间字段的操作,可以通过特定的方法设置和读取日期的特定部分。Calendar是一个抽象类,不可以被实例化,在程序中需要调用其静态方法getInstance()来得到一个Canlendar对象,然后才能调用其相应的方法。
Calendar calendar = Calendar.getInstance();
Calendar常用方法
方法声明 | 功能描述 |
---|---|
Int get(int field) | 返回指定日历字符安的值 |
void add(int field,int amount) | 根据日历规则,为指定的日历字段增加或减去指定的时间量 |
void set(int field,int value) | 为指定日历字符设置指定值 |
void set(int year,int month,int date) | 设置Canlendar对象的年、月、三个字段的值 |
void set(int year,int month,int date,int hourOfDay,int minute,int second) | 设置Canlendar对象的年、月、日、时、分、秒六个字段的值 |
int类型的参数field需要接收Calendar类中定义的常量值,这些常量值分别表示不同的字符安。
使用Calendar.MONTH字段时,月份的起始值是从0开始的,而不是从1开始,因此要获取当前月份要早Calendar.MONTH的基础上加1.
import java.util.Calendar;
public class Example20 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();//创建一个代表默认时区内当时间的Calendar对象
int year = calendar.get(Calendar.YEAR);//调用该兑现的get(int field)方法,通过传入不同的常量字段分别得到日期、时间各个字段的值。
int month = calendar.get(Calendar.MONTH)+1;
int date = calendar.get(Calendar.DATE);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
System.out.println("当前时间为:"+year+"年"+month+"月" +
date+"日"+hour+"时"+minute+"分"+second+"秒");
}
}
添加和修改时间的功能可以通过Calendar类中的add()和set()方法来是吸纳
import java.util.Calendar;
public class Example21 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(2019,1,1);
calendar.add(calendar.DATE,100);
int year = calendar.get(calendar.YEAR);
int month = calendar.get(calendar.MONTH);
int date = calendar.get(calendar.DATE);
System.out.println("计划竣工日期为"+year+"年"+month+"月"+date+"日");
}
}
Calendar.DATE表示的是天数,当天数累加到当月的最大是,继续累加一次就会从1开始计数,同时月份加1,这和算数运算中的进位有点类似。
Calendar日历容错模式(lenient)和非容错模式(non-lenient)
当Calendar处于lenient模式时,它的字段可以接收超过允许范围内的值,当调用get(int field)方法获取某个字段值时,Calendar会重新计算所有字段的值,将字段的值标准化。换句话说就是在lenient模式下,允许出现一些数值上的错误。而当Calendar处于non-lenient模式时,如果某个字段的值超出了它允许的范围,程序将会抛出异常。
import java.util.Calendar;
public class Example22 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH,13);
System.out.println(calendar.getTime());
calendar.setLenient(false);
calendar.set(Calendar.MONTH,13);
System.out.println(calendar.getTime());
}
}
Calendar类默认使用lenient模式,掉员工Calendar的set()方法将MONTH设为13时,会发生进位,调用Calendar的setLenient方法开启non-lenient模式后,同样设置MONTH为13就会因为超出字段范围而抛出异常。
Calendar的getTime()方法会返回一个表示Calendar时间值的Date对象,同时Calendar有一个setTime(Date date)方法,setTime()方法接受一个Date对象,将Date对象表示的时间值设置给Calendar对象,铜鼓哦这两个方法就可以完成Date和Calendar对象之间的转换。
5.5.3 JDK8的日期与时间类
JDK8的日期、时间常用类
类名 | 功能描述 |
---|---|
Clock | 用于获取指定时区的当前日期、时间 |
DayOfWork | 枚举类,定义了一周七天周一到周日的枚举值 |
Duration | 表示持续时间。该类提供的ofXxx()方法用于获取指定的时间的 小时、分钟、秒数等 |
Instant | 表示一个具体时间,可以精确到纳秒。该类提供了静态的now()方法来获取当前时刻,提供了静态的now(Clock clock)方法来获取clock对应的时间。同时还提供了一系列的plusXxx()方法在当前时刻基础上减去一段时间。 |
LocalDate | 表示不带时区的日期,如2018-01-27。该类提供了静态的now()方法来获取当前日期,提供了静态的now(Clock clock)方法来获取clock对应的时刻。同时还提供了一系列的plusXxx()方法在当前时间基础上加上几年、几月、几日等,以及一系列的minuxXxx()方法在当前时间基础上减去几年、几月、几日。 |
LocalTime | 表示不带时区的时间,如14:49:20。该类提供了静态的now()方法来获取当前时间,提供了静态的now(Clock clock)方法来获取clock对应的时间。同时还提供了一系列的plusXxx()方法在当前时间基础上加上几时、几分、几秒等,以及一系列的minuxXxx()方法在当前时间基础上减去几时、几分、几秒等。 |
LocalDateTime | 表示不带时区的日期、时间。该类提供了静态的now()方法来获取当前日期、时间、提供了静态的now(Clock clock)方法来获取clock对应的日期、时间。同时还提供了一系列的plusXxx()方法在当前时间基础上加上几年、几月、几日、几时、几分、几秒等,以及一系列的minuxXxx()方法在当前时间基础上减去几年、几月、几日、几时、几分、几秒等。 |
Month | 枚举类,定义了一月到十二月的枚举值 |
MonthDay | 表示月 日,如-01-27。该类提供了静态的now()方法来获取当前月 日,提供了静态的noew(Clock clock)方法来获取clock对应的月 日。 |
Year | 表示年。如2018。该类提供了静态的now()方法来获取当前年份,提供了静态的noew(Clock clock)方法来获取clock对应的年份。同时还提供了一系列的plusXxx()方法在当前时间基础上加上几年,以及一系列的minuxXxx()方法在当前时间基础上减去几年。 |
YearMonth | 表示年 月,如2018-01.该类提供了静态的now()方法来获取当前年月,提供了静态的noew(Clock clock)方法来获取clock对应的年 月。同时还提供了一系列的plusXxx()方法在当前时间基础上加上几年、几月,以及一系列的minuxXxx()方法在当前时间基础上减去几年、几月。 |
ZoneId | 表示一个时区。 |
ZoneDateTime | 表示一个时区化的日期、时间。 |
import java.time.*;
public class Example23 {
public static void main(String[] args) {
//1.clock的使用
Clock clock = Clock.systemUTC();
System.out.println("获取UTC时区转换的当前时间:"+clock.instant());
System.out.println("获取UTC时区转换的毫秒数:"+clock.millis());
//2.Duration的使用
Duration d = Duration.ofDays(1);
System.out.println("一天等于"+d.toHours()+"小时");
System.out.println("一天等于"+d.toMinutes()+"分钟");
System.out.println("一天等于"+d.toMillis()+"秒");
//3.Instant的使用
Instant instant = Instant.now();
System.out.println("获取UTC时区的当前时间为:"+instant);
System.out.println("当前时间后1小时的时间为:"+instant.plusSeconds(3600));
System.out.println("当前时间前1小时的时间为:"+instant.minusSeconds(3600));
//4.LocalDate的使用
LocalDate localdate = LocalDate.now();
System.out.println("从默认时区的系统始终获得当前日期"+localdate);
//5.LocalTime的使用
LocalTime localTime = LocalTime.now();
System.out.println("从默认时区的系统时钟中获取当前时间"+localTime);
//6.LocalDateTime的使用
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("从默认时区的系统时钟中获取当前日期、时间"+localDateTime);
LocalDateTime times = localDateTime.plusDays(1).plusHours(3).plusMinutes(30);
System.out.println("当前的日期、时间加上1天3小时30分之后"+times);
//7.Year、YRARMonth、Monthday的使用
Year year = Year.now();
System.out.println("当前年份为"+year);
YearMonth yearMonth = YearMonth.now();
System.out.println("当前年月为:"+yearMonth);
MonthDay monthDay = MonthDay.now();
System.out.println("当前月日为"+monthDay);
//8.获取系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println("当前系统默认时区为"+zoneId);
}
}
通过Clock.instant()和Instant.now()获取的当前时间与本地低筒显示时间有8个小时的视察,这是因为Instant默认使用的是UTC(universal Time Coordinated)世界协调时间,又称世界标准时间,UTC提供了一种与时区无关的时间,与CST(China Standard Time)中国标准时间(北京时间)有8个小时的时差。
5.6 格式化类
5.6.1 DateFormat类
使用Date类时,在程序中打印Date对象所输出的当前时间都是以默认的英文格式输出的,如果要将Date对象表示的日期以指定的格式输出,就需要用到DateFormat类。DateFormat类专门用于将日期格式化为字符串或者用特定格式显示的日期字符串转换成一个Date对象。DateFormat是一个抽象类,不能被直接实例化,但它提供了一系列的静态方法来获取DateFormat类的实例对象,并能调用其他响应的方法进行操作。
DateFormat类常用方法
方法声明 | 功能描述 |
---|---|
static DateFormat getDateInstance() | 用于创建默认语言格环境和格式化风格的日期格式器 |
static DateFormat getDateInstance(int style) | 用于创建默认语言环境和指定格式化风格的日期格式器 |
static DateFormat getDateTimeInstance() | 用于创建默认语言环境和格式化风格的日期/时间格式器 |
static DateFormat getDateTimeInstance(int dateStyle,int timeStyle) | 用于创建默认语言环境和指定格式化风格的日期/时间格式器 |
String format(Date date) | 将一个Date格式化为日期/时间字符串 |
Date parse(String source) | 将给定字符串解析成一个日期 |
DateFormat类的四个静态方法能用于获得DateFormat的实例对象,每种方法返回的对象都具有不同的作用,可以分别对日期或者时间部分进行格式化。
在DateFormat类中还定义了许多常量,其中有四个常量是用于作为参数传递给方法的,包括NULL、LONG、MEDIUM和SHORT。FULL常量用于表示完整格式,LONG常量用于表示长格式,MEDIUM常量用于表示普通格式,SHORT常量用于表示短格式。
import java.text.DateFormat;
import java.util.Date;
public class Example24 {
public static void main(String[] args) {
//创建Date对象
Date date = new Date();
//Full格式的日期格式器对象
DateFormat fullFormat =
DateFormat.getDateInstance(DateFormat.FULL);
//LONG格式的日期格式器对象
DateFormat longFormat =
DateFormat.getDateInstance(DateFormat.LONG);
//MEDIUM格式的日期格式器对象
DateFormat mediumFormat =
DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.MEDIUM);
//SHORT格式的日期格式器对象
DateFormat shortFormat =
DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT);
System.out.println("当前日期的完整格式为"+fullFormat.format(date));
System.out.println("当前日期的长格式为"+longFormat.format(date));
System.out.println("当前日期的普通格式为"+mediumFormat.format(date));
System.out.println("当前日期的完短格式为"+shortFormat.format(date));
}
}
DateFormat还提供了一个parse(String source)方法,能够将一个字符串解析成Date对象,但是要求字符串必须符合日期/时间的格式要求,否则抛出异常。
import java.text.DateFormat;
import java.text.ParseException;
public class Example25 {
public static void main(String[] args) throws ParseException {
//创建DateFormat对象
DateFormat dt1 = DateFormat.getDateInstance();
//创建Long格式的DateFormat对象
DateFormat dt2 = DateFormat.getDateInstance(DateFormat.LONG);
//定义两个日期格式的字符串
String str1 = "2018-01-27";
String str2 = "2018年01月27日";
//输出对应格式的字符串解析春Date对象后的结果
System.out.println(dt1.parse(str1));
System.out.println(dt2.parse(str2));
}
}
5.6.2 SimpleDateFormat类
在使用DateFormat对象的parse()方法将字符串解析为日期时,需要输入固定格式的字符串,这显然不够灵魂。为了能更好地格式化日期、解析字符串,Java中提供了一个SimpleDateFormat类。
SimpleDateFormat类是DateFormat类的子类,可以使用new关键字创建实例对象。在创建实例对象时,它的构造方法需要接收一个表示日期格式模板的字符串参数。
import java.text.SimpleDateFormat;
import java.util.Date;
public class Example26 {
public static void main(String[] args) {
//创建一个SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("Gyyy年MM月dd日:今天是yyy年的第D天,E");
//按SimpleDateFormat对象的日期模板格式化Date对象
System.out.println(sdf.format(new Date()));
}
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class Example27 {
public static void main(String[] args) throws ParseException {
//创建一个SimpleDateFormat对象,并指定日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyy/MM/dd");
//定义一个日期格式的字符串
String str = "2018/01/27";
//将字符串解析成Date对象
System.out.println(sdf.parse(str));
}
}
5.6.3 DateTimeFormat类
JDK8在ava.time.format包下还提供了一个DateTimeFormatter类,该类也是一个格式化类,其功能相当于DateFormat和SimpleDateFormat的合体,它不仅可以将日期、时间对象格式化为字符串,还能将特定格式的字符串解析成日期、时间对象。
要使用DateTimeFormatter类进行格式化或解析,就必须先获得DateTimeFormatter对象。三种方式:
-
使用静态常量创建DateTimeFormatter格式器。在DateTimeFormatter中包含大量静态常量,如BASIC_ISO_DATE,ISO_LOCAL_DATE,ISO_LOCAL_TIME等,通过这些静态常量都可以获取DateTimeFormatter实例;
-
使用不同风格的枚举值来创建DateTimeFormatter格式器。在FormatStyle类中定义了FULL、LONG、MEDIUM和SHORT四个枚举值,表示日期和时间的不同风格;
-
根据模式字符串创建DateTimeFormatter格式器。
1.完成日期、时间格式化
使用DateTimeFormatter将日期、时间格式化为字符串,可以通过:
-
调用DateTimeFormatter的format(TemporalAccessor temporal)方法执行格式化,其中参数temporal是衣蛾TemporalAcxessor类型接口,其主要实现类有LocalDate、LocalDateTime;
-
调用LocalDate、LocalDateTime等日期、时间对象的format(DateTimeFormatter formatter)方法执行格式化
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class Example28 {
public static void main(String[] args) {
LocalDateTime date = LocalDateTime.now();
//1.使用常量创建DateTimeFormatter
System.out.print("使用常量创建DateTimeFormatter:");
DateTimeFormatter dtf1 = DateTimeFormatter.ISO_DATE_TIME;
System.out.println(dtf1.format(date));
//2.使用MEDIUM类型风格的DateTimeFormatter
System.out.print("使用MEDIUM类型风格的DateTimeFormatter");
DateTimeFormatter dtf2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
System.out.println(dtf2.format(date));
//3.根据模式字符串来创建DateTimeFormatter格式器
System.out.print("根据模式字符串来创建DateTimeFormatter格式器");
DateTimeFormatter dtf3 = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss");
System.out.println(dtf3.format(date));
}
}
2.解析字符串
要使用DateTimeFormatter将指定格式的字符串解析成日期、时间对象,可以通过日期、时间对象所提供的的parse(CharSequence text,DateTimeFormatter formatter)方法来实现
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Example29 {
public static void main(String[] args) {
//定义两种日期格式的字符串
String str1 = "2018-01-27 12:38:36";
String str2 = "2018年01月27日 12时38分36秒";
//定义解析所用的格式器
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
//使用LocalDateTime的parse()方法执行解析
LocalDateTime localDateTime1 = LocalDateTime.parse(str1, formatter1);
LocalDateTime localDateTime2 = LocalDateTime.parse(str2, formatter2);
System.out.println(localDateTime1);
System.out.println(localDateTime2);
}
}