第七章.Java基础类库
运行Java程序的参数:
//Java程序入口:
public static void main(String[] args){...}
public修饰符:Java类由JVM调用为了让JVM可以自由调用这个main()方法,所以使用public修饰符把这个方法暴露出来
static修饰符:JVM调用这个方法时,JVM直接通过该类来调用主方法,因此使用static修饰该主方法
void返回值:因为主方法被JVM调用,该方法的返回值返回给JVM,没有意义,因此main()方法没有返回值
args参数:运行的Java命令参数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class ArgsTest{ 2 public static void main(String[] args){ 3 //输出args数组的长度 4 System.out.println(args.length); 5 //遍历args数组的每个元素 6 for(String arg : args){ 7 System.out.println(arg); 8 } 9 } 10 }
使用Scanner获取键盘输入:
Scanner类可以很方便的获取用户键盘输入,Scanner是一个基于正则表达式的文本扫描器,可从文件、输入流、字符串中解析出类型值和字符串值。
Scanner提供两个方法来扫描输入:
1.hasNextXxx():是否还有下一个输入项。若只是判断是否包含下一个字符串,则直接使用hasNext()
2.nextXxx():获取下一个输入项。
Scanner使用空白(包括空格、Tab空白、回车)作为输入项之间的分隔符
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Scanner; 2 3 public class ScannerKeyBoardTest{ 4 public static void main(String[] args){ 5 //System.in代表标准输入,就是键盘输入 6 Scanner sc = new Scanner(System.in); 7 //增加下面一行将只把回车作为分隔符 8 //sc.useDelimiter("\n"); 9 //判断是否还有下一个输入项 10 while(sc.hasNext()){ 11 //输出输入项 12 System.out.println("键盘输入的内容是:" + sc.next()); 13 } 14 } 15 }
Scanner提供两个方法逐行读取:
1.boolean hasNextLine():返回输入源中是否还有下一行
2.String nextLine():返回输入源中下一行的字符串
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Scanner; 2 3 public class ScannerKeyBoardTest{ 4 public static void main(String[] args){ 5 //System.in代表标准输入,就是键盘输入 6 Scanner sc = new Scanner(System.in); 7 //增加下面一行将只把回车作为分隔符 8 //sc.useDelimiter("\n"); 9 //判断是否还有下一个输入项 10 while(sc.hasNextLine()){ 11 //输出输入项 12 System.out.println("键盘输入的内容是:" + sc.nextLine()); 13 } 14 } 15 }
Scanner读入文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Scanner; 2 import java.io.File; 3 4 public class ScannerFileTest{ 5 public static void main(String[] args) throws Exception{ 6 //将一个File对象作为Scanner的构造器参数,Scanner读取文件内容 7 Scanner sc = new Scanner(new File("ScannerFileTest.java")); 8 System.out.println("ScannerFileTest.java文件内容如下:"); 9 //判断是否还有下一行 10 while(sc.hasNextLine()){ 11 //输出文件中的下一行 12 System.out.println(sc.nextLine()); 13 } 14 } 15 }
系统相关:
System类:
System类代表当前java程序的运行平台,程序不能创建System类的对象,System类提供了一些类变量和类方法,允许直接通过System类来调用这些类变量和类方法。
System类提供了代表标准输入、标准输出和错误输出的类变量,并提供了一些静态方法用于访问环境变量、系统属性的方法,还提供了加载文件和动态链接库的方法。
下面程序通过System类来访问操作的环境变量和系统属性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileOutputStream; 2 import java.util.Map; 3 import java.util.Properties; 4 5 public class SystemTest{ 6 public static void main(String[] args) throws Exception{ 7 //获取系统所有的环境变量 8 Map<String, String> env = System.getenv(); 9 for(String name : env.keySet()){ 10 System.out.println(name + " ---> " + env.get(name)); 11 } 12 //获取指定环境变量的值 13 System.out.println(System.getenv("JAVA_HOME")); 14 //获取所有的系统属性 15 Properties props = System.getProperties(); 16 //将所有的系统属性保存到props.txt文件中 17 props.store(new FileOutputStream("props.txt"), "System Properties"); 18 //输出特定的系统属性 19 System.out.println(System.getProperty("os.name")); 20 } 21 }
结果太多,没办法截图,自己运行一遍。
identityHashCode(Object x)方法,返回指定对象的精确hashCode值,即根据该对象的地址计算得到的hashCode值:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class IdentityHashCodeTest{ 2 public static void main(String[] args){ 3 //下面程序中s1和s2是两个不同的对象 4 String s1 = new String("Hello"); 5 String s2 = new String("Hello"); 6 //String重写了hashCode()方法——改为根据字符序列计算hashCode值 7 //因为s1和s2的字符序列相同,所以它们的hashCode()方法返回值相同 8 System.out.println(s1.hashCode() + " ---- " + s2.hashCode()); 9 //s1和s2是不同的字符串对象,所以它们的identityHashCode值不同 10 System.out.println(System.identityHashCode(s1) + " ---- " + System.identityHashCode(s2)); 11 String s3 = "java"; 12 String s4 = "java"; 13 //s3和s4是相同的字符串对象,所以它们的identityHashCode值相同 14 System.out.println(System.identityHashCode(s3) + " ---- " + System.identityHashCode(s4)); 15 } 16 }
Runtime类:
Runtime类代表Java程序的运行时环境,每个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与其运行时环境相连。应用程序不能创建自己的Runtime实例
但是可以getRuntime()方法获取与之关联的Runtime对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class RuntimeTest{ 2 public static void main(String[] args){ 3 //获取Java程序关联的运行时对象 4 Runtime rt = Runtime.getRuntime(); 5 System.out.println("处理器数量:" + rt.availableProcessors()); 6 System.out.println("空闲内存数:" + rt.freeMemory()); 7 System.out.println("总内存数:" + rt.totalMemory()); 8 System.out.println("可用最大内存数:" + rt.maxMemory()); 9 } 10 }
Runtime类还可以单独启动一个进程来运行操作系统命令:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class ExecTest{ 2 public static void main(String[] args) throws Exception{ 3 Runtime rt = Runtime.getRuntime(); 4 //运行记事本程序 5 rt.exec("notepad.exe"); 6 } 7 }
常用类:
Object类:
Object类时所有类、数组、枚举类的父类,默认继承Object父类
Object类常用方法:
1.boolean equals(Object obj):判断指定对象和该对象是否相等。此处相等标准是,两个对象是同一个对象。
2.protected void finalize():系统中没有引用变量引用该对象时,垃圾回收器调用此方法来清理该对象的资源
3.Class<?> getClass():返回该对象的运行时类。
4.int hashCode():返回该对象的hashCode()值。默认情况下,Object类的hashCode()方法根据该对象的地址来计算。
5.String toString():返回该对象的的字符串表示,当程序使用System.out.println()方法输出一个对象,或者把某个对象和字符串进行连接运算时,系统会自动调用该
对象的toString()方法返回该对象的字符串表示。Object类的toString()方法返回“运行时类名@十六进制hashCode值”格式的字符串。
6.Object clone():帮助其他对象实现“自我克隆”,得到当前对象的一个副本,而且两者之间完全隔离。由于Object类的clone()方法使用了protected修饰,所以只能被
子类重写或调用
自定义类实现“克隆”的步骤
1.自定义类实现Cloneable接口,接口里没有任何方法。
2.自定义类实现自己的clone()方法
3.实现clone()方法时通过super.clone(); 调用Object实现的clone()方法得到该对象的副本,并返回该副本。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Address { 2 String detail; 3 public Address(String detail){ 4 this.detail = detail; 5 } 6 } 7 8 //实现Cloneable接口 9 class User implements Cloneable{ 10 int age; 11 Address address; 12 13 public User(int age){ 14 this.age = age; 15 address = new Address("广东天河"); 16 } 17 18 //通过调用super.clone()来实现clone()方法 19 public User clone() throws CloneNotSupportedException{ 20 return (User) super.clone(); 21 } 22 } 23 24 public class CloneTest{ 25 public static void main(String[] args) throws CloneNotSupportedException{ 26 User u1 = new User(29); 27 //clone得到u1对象的副本 28 User u2 = u1.clone(); 29 //判断u1、u2是否相同 30 System.out.println(u1 == u2); 31 //判断u1、u2的address是否相同 32 System.out.println(u1.address == u2.address); 33 } 34 }
上面程序User类实现了Cloneable接口,而且实现了clone()方法。克隆出来的对象只是原有对象的副本,所以u1 == u2为false
Object类提供的Clone机制只对对象里各实例进行“简单复制”,若实例变量类型是引用类型,Object的Clone机制也只是简单的复制这个引用变量,这样原有对象的
引用类型的实例变量与克隆对象的引用类型的实例变量依然指向内存中的同一个实例。所以u1.address == u2.address为true
Java7新增的Objects类:
Objects工具类,提供一些工具方法来操作对象,这些工具大多是“空指针”安全的。如:若不能确定一个引用变量是否为null,贸然调用该变量的toString()方法,则可能引
发NullPointerException异常。但若使用Objects类的toString(Object o)方法就不会引发空指针异常,当o为null时,程序将返回一个“null”字符串。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Objects; 2 3 public class ObjectsTest{ 4 //定义了一个obj变量,它的默认值是null 5 static ObjectsTest obj; 6 public static void main(String[] args){ 7 //输出一个null对象的hashCode值,输出0 8 System.out.println(Objects.hashCode(obj)); 9 //输出一个null对象的toString,输出null 10 System.out.println(Objects.toString(obj)); 11 //要求obj不能为null,若obj为null则引发异常 12 System.out.println(Objects.requireNonNull(obj, "obj参数不能为null!")); 13 } 14 }
String、StringBuffer和StringBuilder类:
String类是不可变类,即一旦一个String对象被创建,包含在这个对象的字符序列是不可以被改变的,直至这个对象被销毁。
StringBuffer对象则代表一个字符序列可变得字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等
方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
JDK1.5新增了StringBuilder类,也代表字符串对象,实际上,StringBuilder和StringBuffer基本相似,StringBuffer是线程安全的,StringBuilder没有实现线程安全。一般优先
考虑使用StringBuilder类。
三者都实现了CharSequence接口。
String类的方法:
1.char charAt(int index):获取字符串中指定位置的字符。字符串序数从0到length() - 1;
2.int compateTo(String anotherString):比较两个字符串的大小。若两个字符串字符序列相等,返回0;不相等,从两个字符串第0个字符开始比较,返回第一个不相
等的字符差。另一种情况,较长字符串的前面部分恰巧是较短的字符串,则返回它们的长度差:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class StringCompareTest{ 2 public static void main(String[] args){ 3 String s1 = new String("abcdefghijklmn"); 4 String s2 = new String("abcdefghij"); 5 String s3 = new String("abcdefghijalmn"); 6 System.out.println("s1.compareT(s2):" + s1.compareTo(s2));//返回长度差 7 8 System.out.println("s1.compareTo(s3):" + s1.compareTo(s3));//返回'k' - 'a'的差 9 } 10 }
3.String concat(String str):将该String对象与str连接在一起。
4.boolean contentEquals(StringBuffer sb):将该String对象与StringBuffer对象sb进行比较,当它们包含的字符序列相同时返回true
5.static String copyValueOf(char[] data):将字符数组连缀成字符串。
6.static String copyValueof(char[] data, int offset, int count):将char数组的子类数组中的元素连缀成字符串。
7.boolean endsWith(String suffix):返回该String对象是否以suffix结尾
8.boolean equals(Object anObject):将该字符串与指定对象比较,若二者包含字符序列相等,则返回true,否则返回false
9.boolean equalsIgnoreCase(String str):与前一个基本相似,只是忽略大小写。
10.byte[] getBytes():将该String对象转换成byte数组
11.void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):该方法将字符串中从srcBegin开始,到srcEnd结束的字符复制到dst字符数组中,其中dstBegin
为目标字符数组的起始复制位置。
12.int indexOf(int ch):找出ch字符在该字符串中第一次出现的位置
13.int indexOf(int ch, int fromIndex):找出ch字符在该字符串中从fromIndex开始后第一次出现的位置
14.int indexOf(String str):找出str子字符在该字符串中第一次出现的位置
15.int indexOf(String str, int fromIndex):找出str子字符串在该字符串中从fromIndex开始后第一次出现的位置
16.int lastIndexOf(int ch):找出ch字符在该字符串中最后一次出现的位置
17.int lastIndexOf(int ch, int fromIndex):找出ch字符在该字符串中从fromIndex开始后最后一次出现的位置
18.int lastIndexOf(String str):找出str子字符在该字符串中最后一次出现的位置
19.int lastIndexOf(String str, int fromIndex):找出str子字符串在该字符串中从fromIndex开始后最后一次出现的位置
20.int length():返回当前字符串长度
21.String replace(char oldChar, char newChar):将字符串中的第一个oldChar替换成newChar
22.boolean startsWith(String prefix):该String对象是否以prefix开始
23.boolean startsWith(String prefix, String toffset):该String对象从toffset位置算起,是否以prefix开始
24.subString(int beginIndex):获取从beginIndex位置开始到结束的子字符串
25.subString(int beginIndex, int endIndex):获取从beginIndex位置开始到endIndex位置的子字符串
26.char[] toCharArray():将该String对象转换成char数组
27.String toLowerCase():将字符串转换成小写
28.String toUpperCase():将字符串转换成大写
29.static String valueOf(X x):一系列用于将基本类型转换为String对象的方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class StringBuilderTest{ 2 public static void main(String[] args){ 3 StringBuilder sb = new StringBuilder(); 4 //追加字符串 5 sb.append("java");//sb = "java" 6 //插入 7 sb.insert(0, "hello ");//sb = "hello java" 8 //替换 9 sb.replace(5, 6, ",");//sb = "hello,java" 10 //删除 11 sb.delete(5, 6);//sb = "hellojava" 12 //反转 13 sb.reverse();//sb = "avajolleh" 14 System.out.println(sb); 15 System.out.println(sb.length());//输出9 16 System.out.println(sb.capacity());//输出16 17 //改变StringBuilder的长度,将只保留前面部分 18 sb.setLength(5);//sb = "avajo"; 19 System.out.println(sb); 20 } 21 }
Math类:
Math类构造器被定义成private的,因此无法创建Math类的对象;Math类的所有方法都是类方法,可以通过类名调用。
Math类提供了两个类变量:PI和E,值分别是圆周率和log底数e
自行查阅API。
Java7的ThreadLocalRandom和Random
Random类专门生成为随机数,有两个构造器,一个构造器使用默认的种子(以当前时间为种子),另一个构造器需要程序员显示传入一个long型整数的种子。
ThreadLocalRandom类是Java7新增的类,是Random类的增强版。在并发访问的环境下,使用TreadLocalRandom来代替Random可以减少多线程资源竞争,最终保证
系统具有更好的线程安全
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Random; 2 import java.util.Arrays; 3 4 public class RandomTest{ 5 public static void main(String[] args){ 6 Random rand = new Random(); 7 System.out.println("rand.nextBoolean():" + rand.nextBoolean()); 8 byte[] buffer = new byte[16]; 9 rand.nextBytes(buffer); 10 System.out.println(Arrays.toString(buffer)); 11 //生成0.0~1.0之间的伪随机double数 12 System.out.println("rand.nextDouble():" + rand.nextDouble()); 13 //生成0.0~1.0之间的伪随机float数 14 System.out.println("rand.nextFloat():" + rand.nextFloat()); 15 //生成平均值是0.0,标准差是1.0的伪随机数 16 System.out.println("rand.nextGaussian():" + rand.nextGaussian()); 17 //生成一个处于int整数取值范围的伪随机整数 18 System.out.println("rand.nextInt():" + rand.nextInt()); 19 //生成0~26之间的伪随机整数 20 System.out.println("rand.nextInt(26):" + rand.nextInt(26)); 21 //生成一个处于long整数取值范围的伪随机整数 22 System.out.println("rand.nextLong():" + rand.nextLong()); 23 } 24 }
为了避免Random对象产生相同的数字序列,通常推荐使用当前时间作为Random对象的种子:
Random rand = new Random(System.currentTimeMillis());
ThreadLocalRandom的用法:
ThreadLocalRandom rand = ThreadLocalRandom.current();//获取一个ThreadLocalRandom对象
//生成一个4~20之间的为随机数
int val1 = rand.nextInt(4, 20);
//生成一个2.0~10.0之间的伪随机浮点数
int val2 = rand.nextDouble(2.0, 10.0);
BigDecimal类:
为了精确表示、计算浮点数,Java提供了BigDecimal类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.math.BigDecimal; 2 3 public class BigDecimalTest{ 4 public static void main(String[] args){ 5 BigDecimal f1 = new BigDecimal("0.05"); 6 BigDecimal f2 = BigDecimal.valueOf(0.01); 7 BigDecimal f3 = new BigDecimal(0.05); 8 9 System.out.println("使用String作为BigDecimal构造器参数:"); 10 System.out.println("0.05 + 0.01 = " + f1.add(f2)); 11 System.out.println("0.05 - 0.01 = " + f1.subtract(f2)); 12 System.out.println("0.05 * 0.01 = " + f1.multiply(f2)); 13 System.out.println("0.05 / 0.01 = " + f1.divide(f2)); 14 15 System.out.println("使用double作为BigDecimal构造器参数:"); 16 System.out.println("0.05 + 0.01 = " + f3.add(f2)); 17 System.out.println("0.05 - 0.01 = " + f3.subtract(f2)); 18 System.out.println("0.05 * 0.01 = " + f3.multiply(f2)); 19 System.out.println("0.05 / 0.01 = " + f3.divide(f2)); 20 } 21 }
通常建议使用基于String的构造器,若必须使用double浮点数作为BigDecimal构造器参数时,通过BigDecimal.valueOf(double value)静态方法来创建BigDecimal对象。
若程序中要求对double浮点数进行加、减、乘、除基本运算,则需要先将double类型包装成BigDecimal对象,调用BigDecimal的方法执行运算后再将结果转换成double型
变量。这是比较繁琐的过程,可以考虑以BigDecimal为基础定义一个Arithmetic工具类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.math.BigDecimal; 2 3 public class Arith{ 4 //默认除法运算精度 5 private static final int DEF_DIV_SCALE = 10; 6 //构造器私有,让这个类不能实例化 7 private Arith(){} 8 //提供精确的加法运算 9 public static double add(double v1, double v2){ 10 BigDecimal b1 = BigDecimal.valueOf(v1); 11 BigDecimal b2 = BigDecimal.valueOf(v2); 12 13 return b1.add(b2).doubleValue(); 14 } 15 16 //提供精确的减法运算 17 public static double sub(double v1, double v2){ 18 BigDecimal b1 = BigDecimal.valueOf(v1); 19 BigDecimal b2 = BigDecimal.valueOf(v2); 20 21 return b1.subtract(b2).doubleValue(); 22 } 23 24 //提供精确的乘法运算 25 public static double mul(double v1, double v2){ 26 BigDecimal b1 = BigDecimal.valueOf(v1); 27 BigDecimal b2 = BigDecimal.valueOf(v2); 28 29 return b1.multiply(b2).doubleValue(); 30 } 31 32 //提供(相对)精确的除法运算,当发生除不尽的情况时 33 //精确到小数点以后10位的数字四舍五入 34 public static double div(double v1, double v2){ 35 BigDecimal b1 = BigDecimal.valueOf(v1); 36 BigDecimal b2 = BigDecimal.valueOf(v2); 37 38 return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue(); 39 } 40 41 public static void main(String[] args){ 42 System.out.println("0.05 + 0.01 = " + Arith.add(0.05, 0.01)); 43 System.out.println("1.0 - 0.42 = " + Arith.sub(1.0, 0.42)); 44 System.out.println("4.015 * 100 = " + Arith.mul(4.015, 100)); 45 System.out.println("123.3 / 100 = " + Arith.div(123.3, 100)); 46 } 47 }
Java8的日期、时间类:
Date类:一般不用了,只举一个例子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Date; 2 3 public class DateTest{ 4 public static void main(String[] args){ 5 Date d1 = new Date(); 6 //获取当前时间之后100ms的时间 7 Date d2 = new Date(System.currentTimeMillis() + 100); 8 System.out.println(d2); 9 System.out.println(d1.compareTo(d2)); 10 System.out.println(d1.before(d2)); 11 } 12 }
Calendar类:
Calendar类本身是一个抽象类,它是所有日历类的模板,并提供了一些所有日历通用的方法;但它本身不能直接实例化,程序只能创建Calendar子烈的实例。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //创建一个默认的Calendar对象 2 Calendar calendar = Calendar.getInstance(); 3 //从Calendar对象中取出Date对象 4 Date date = calendar.getTime(); 5 //通过Date对象获得对应的Calendar对象 6 //因为Calendar/GregorianCalendar没有构造器函数可以接收Date对象 7 //所以必须先获得一个Calendar实例,然后调用其setTime()方法 8 Calendar calendar2 = Calendar.getInstance(); 9 calendar2.setTime(date);
Calendar类中的方法:
1.void add(int field, int amount);根据日历的规则,为给定的日历字段添加或减去指定的时间量
2.int get(int field):返回指定日历字段的值
3.int getActualMaximum(int field):返回指定日历字段可能拥有的最大值。如:月,最大值为11
4.int getActualMinimum(int field):返回指定日历字段可能拥有的最小值。如:月,最小值为0
5.void roll(int field, int amout):与add()方法类似,区别在于加上amount后超过了该字段所能表示的最大范围时,也不会向上一个字段进位。
6.void set(int field, int value):将给定的日历字段设置为给定值
7.void set(int year, int month, int date):设置Calendar对象的年、月、日三个字段的值
8.void set(int year, int month, int date, int hourOfDay, int minute, int second):设置年、月、日、时、分、秒6个字段的值
Calendar.YEAR、Calendar.MONTH等分别代表年、月、日、小时、分钟、秒等。Calender.MONTH:月份的起始值是0,所以设置8月时,用7
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Calendar; 2 3 public class CalendarTest{ 4 public static void main(String[] args){ 5 Calendar c = Calendar.getInstance(); 6 //取出年 7 System.out.println(c.get(Calendar.YEAR)); 8 //取出月份 9 System.out.println(c.get(Calendar.MONTH)); 10 //取出日 11 System.out.println(c.get(Calendar.DATE)); 12 //分别设置年月日时分秒 13 c.set(2003, 10, 23, 12, 32, 23);//2003-11-23 12:32:23 14 System.out.println(c.getTime()); 15 //将Calendar的年前推1年 16 c.add(Calendar.YEAR, -1);//2002-11-23 12:32:23 17 System.out.println(c.getTime()); 18 //将Calendar的月前推12个月 19 c.roll(Calendar.MONTH, -13);//2002-10-23 12:32:23 20 System.out.println(c.getTime()); 21 } 22 }
Calendar类的容错性:
调用Calendar对象的set()方法改变指定时间字段的值时,有可能传入一个不合法的参数,如:为MONTH字段设置13:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Calendar; 2 3 public class LenientTest{ 4 public static void main(String[] args){ 5 Calendar cal = Calendar.getInstance(); 6 //结果是YEAR字段加1,MONTH字段为1(2月) 7 cal.set(Calendar.MONTH, 13); 8 System.out.println(cal.getTime()); 9 //关闭容错性 10 cal.setLenient(false); 11 //运行时导致异常 12 cal.set(Calendar.MONTH, 13); 13 System.out.println(cal.getTime()); 14 } 15 }
set()方法延迟修改:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Calendar; 2 3 public class LazyTest{ 4 public static void main(String[] args){ 5 Calendar cal = Calendar.getInstance(); 6 cal.set(2003, 7, 31);// 2003-08-31 7 //将月份设为9,但9月31日不存在 8 //若立即修改,系统将会把查了自动调整到10月1日 9 cal.set(Calendar.MONTH, 8); 10 //下面代码输出10月1日 11 //System.out.println(cal.getTime()); 12 //设置DATE字段为5 13 cal.set(Calendar.DATE, 5); 14 System.out.println(cal.getTime()); 15 } 16 }
set(f, value)方法将日历字段f更改为value,尽管f立即更改,但该Calendar所代表的时间不会立即修改,知道下次调用get()、getTime()、getTimeInMillis()、
add()或roll()时才会重新计算日历时间
Java8新增的日期、时间包:
Java8专门新增了一个java.time包,该包下有如下类:
1.Clock:该类用于获取指定时区的当前日期、时间。该类可取代System类的currentTimeMillis()方法,且提供了更多方法来获取当前日期、时间。
2.Duration:该类代表持续时间。很方便获取一段时间
3.Instant:代表一个具体的时刻,可以精确到纳秒。该类提供了静态的now()方法来获取当前时刻,也提供了静态的now(Clock clock)方法获取clock对应的日期。除此
之外,提供了minusXxx()方法在当前时刻基础上减去一段时间,plusXxx()方法在当前时刻基础上加上一段时间。
4.LocalDate:该类代表不带时区的日期,如:2017-08-08.
5.LocalTime:该类代表不带时区的时间,如:10:15:30.
6.LocalDateTime:该类代表不带时区的日期、时间,如:2017-08-08 10:15:30.
7.MonthDay:该类仅代表月日,如:--08-08.
8.Year:该类仅代表年,如:2017.
9.YearMonth:该类仅代表年月,如:2017-08
10.ZonedDateTime:该类代表一个时区化的日期、时间。
11.ZoneId:该类代表一个时区。
12.DayOfWeek:这是一个枚举类,定义了周一到周日的枚举值
13.Month:这也是一个枚举类,定义了一月到十二月的枚举值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.time.*; 2 3 public class NewDatePackageTest{ 4 public static void main(String[] args){ 5 //------下面是关于Clock的用法------ 6 //获取当前Clock 7 Clock clock = Clock.systemUTC(); 8 //通过Clock获取当前时刻 9 System.out.println("当前时刻为:" + clock.instant()); 10 //获取clock对应的毫秒数,与System.currentTimeMillis()输出相同 11 System.out.println(clock.millis()); 12 System.out.println(System.currentTimeMillis()); 13 14 //------下面是关于Duration的用法------ 15 Duration d = Duration.ofSeconds(6000); 16 System.out.println("6000秒相当于" + d.toMinutes() + "分"); 17 System.out.println("6000秒相当于" + d.toHours() + "小时"); 18 System.out.println("6000秒相当于" + d.toDays() + "天"); 19 //在clock基础上增加6000秒,返回新的Clock 20 Clock clock2 = Clock.offset(clock, d); 21 //可以看到clock2与clock1相差1小时40分 22 System.out.println("当前时刻加6000秒为:" + clock2.instant()); 23 24 //------下面是关于Instant的用法------ 25 //获取当前时间 26 Instant instant = Instant.now(); 27 System.out.println(instant); 28 //instant添加6000秒(即100分钟),返回新的Instant 29 Instant instant2 = instant.plusSeconds(6000); 30 System.out.println(instant2); 31 //根据字符串解析Instant对象 32 Instant instant3 = Instant.parse("2014-02-23T10:12:35.342Z"); 33 System.out.println(instant3); 34 //在instant3的基础上添加5小时4分钟 35 Instant instant4 = instant.plus(Duration.ofHours(5).plusMinutes(4)); 36 System.out.println(instant4); 37 //获取instant4的5天以前的时刻 38 Instant instant5 = instant4.minus(Duration.ofDays(5)); 39 System.out.println(instant5); 40 41 //------下面是关于LocalDate的用法------ 42 LocalDate localDate = LocalDate.now(); 43 System.out.println(localDate); 44 //获得2014年的第146天 45 localDate = LocalDate.ofYearDay(2014, 146); 46 System.out.println(localDate);//2014-05-26 47 //设置为2014年5月21日 48 localDate = LocalDate.of(2014, Month.MAY, 21); 49 System.out.println(localDate);//2014-05-21 50 51 //------下面是关于LocalTime的用法------ 52 //获取当前时间 53 LocalTime localTime = LocalTime.now(); 54 //设置为22点33分 55 localTime = LocalTime.of(22, 33); 56 System.out.println(localTime);//22:33 57 //返回一天中的第5503秒 58 localTime = LocalTime.ofSecondOfDay(5503); 59 System.out.println(localTime);//01:31:43 60 61 //------下面是关于localDateTime的用法------ 62 //获取当前日期、时间 63 LocalDateTime localDateTime = LocalDateTime.now(); 64 //当前日期、时间加上25小时3分钟 65 LocalDateTime future = localDateTime.plusHours(25).plusMinutes(3); 66 System.out.println("当前日期、时间的25小时3分钟之后:" + future); 67 68 //------下面是关于Year、YearMonth、MonthDay的用法------ 69 Year year = Year.now();//获取当前年份 70 System.out.println("当前年份:" + year); 71 year = year.plusYears(5);//当前年份加5年 72 System.out.println("当前年份再过5年:" + year); 73 //根据指定月份获取YearMonth 74 YearMonth ym = year.atMonth(10); 75 System.out.println("year年10月:" + ym);//输出XXXX-10,XXXX代表当前年份 76 //当前年月再加5年、减3个月 77 ym = ym.plusYears(5).minusMonths(3); 78 System.out.println("year年10月再加5年、减3个月:" + ym); 79 MonthDay md = MonthDay.now(); 80 System.out.println("当前月日:" + md);//输出--XX-X,代表几月几日 81 //设置为5月23日 82 MonthDay md2 = md.with(Month.MAY).withDayOfMonth(23); 83 System.out.println("5月23日为:" + md2);//输出--05-23 84 } 85 }
正则表达式:
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。
String类中也提供了以下几个特殊方法:
1.boolean matches(String regex):判断该字符串是否匹配指定的正则表达式
2.String replaceAll(String regex, String replacement):将该字符串中所有匹配regex的子串替换成replacement。
3.String replaceFirst(String regex, String replacement):将该字符串中第一个匹配regex的子串替换成replacement
4.String[] split(String regex):以regex作为分隔符,把该字符串分割成多个子串
java还提供了Pattern类和Matcher类专门用于提供正则表达式支持
d是digit的意思,代表数字;s是space的意思,代表空白;w是Word的意思,代表单词。
使用正则表达式:
可以导入Pattern类和Matcher类,使用正则表达式
Pattern对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译为Pattern对象,然后再利用该Pattern对象创建对应的Matcher对象。执
行匹配所涉及的状态保留在Matcher对象中,多个Match而对象可共享同一个Pattern对象
1 //将一个字符串编译成Pattern对象 2 Pattern p = Pattern.compile("a*b"); 3 //使用Pattern对象创建Matcher对象 4 Matcher m = p.matcher("aaaaab"); 5 boolean b = m.matches();//返回true
Pattern是不可变类,可供多个并发线程安全使用
Matcher类提供了几个常用方法:
1.find():返回目标字符串中是否包含与Pattern匹配的子串
2.group():返回上一次与Pattern匹配的子串
3.start():返回上一次与Pattern匹配的子串在目标字符串中开始的位置
4.end():返回上一次与Pattern匹配的子串在目标字符串中的结束位置加1
5.lookingAt():返回目标字符串前面部分与Pattern是否匹配
6.matches():返回整个目标字符串与Pattern是否匹配
7.reset():将现有的Matcher对象应用于一个新的字符序列
通过Matcher类的find()和group()方法可以从目标字符串中依次取出特定子串:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.regex.Pattern; 2 import java.util.regex.Matcher; 3 4 public class FindGroup{ 5 public static void main(String[] args){ 6 //使用字符串模拟从网络上得到的网页源码 7 String str = "我想求购译本《疯狂Java讲义》,尽快联系我13500006666" + "交朋友,电话号码是13611125565" + "出售二手电脑,联系方式15899903312"; 8 //创建一个Pattern对象,并用它建立一个Matcher对象 9 //该正则表达式只抓取13X和15X段的手机号 10 //实际要抓取哪些电话号码,只要修改正则表达式即可 11 Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}").matcher(str); 12 //将所有符合正则表达式的传(电话号码)全部输出 13 while(m.find()){ 14 System.out.println(m.group()); 15 } 16 } 17 }
从运行结果看,find()方法依次查找字符串中与Pattern匹配的子串,一旦找到对应的子串,下次调用find()方法时将接着向下查找。
find()方法还可以传入一个int类型的参数,带int参数的find()方法将从该int索引处向下搜索。
start()和end()方法主要用于确定子串在目标字符串中的位置:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.regex.Pattern; 2 import java.util.regex.Matcher; 3 4 public class StartEnd{ 5 public static void main(String[] args){ 6 //创建一个Pattern对象,并用它建立一个Matcher对象 7 String regStr = "Java is very easy!"; 8 System.out.println("目标字符串是:" + regStr); 9 Matcher m = Pattern.compile("\\w+").matcher(regStr); 10 while(m.find()){ 11 System.out.println(m.group() + "子串的起始位置:" + m.start() + ",其结束位置:" + m.end()); 12 } 13 } 14 }
matches()和lookingAt()方法相似,matches()方法要求整个字符串和Pattern完全匹配时才返回true,而lookingAt()只要字符串以Pattern开头就会返回true。
reset()方法可将现有的Matcher对象应用于新的字符序列。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.regex.Pattern; 2 import java.util.regex.Matcher; 3 4 public class MatchesTest{ 5 public static void main(String[] args){ 6 String[] mails = { 7 "kongyeeku@163.com", 8 "kongyeeku@gmail.com", 9 "ligang@crazyit.org", 10 "wawa@abc.xx" 11 }; 12 String mailRegEx = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov)"; 13 Pattern mailPattern = Pattern.compile(mailRegEx); 14 Matcher matcher = null; 15 for(String mail : mails){ 16 if(matcher == null){ 17 matcher = mailPattern.matcher(mail); 18 }else{ 19 matcher.reset(mail); 20 } 21 String result = mail + (matcher.matches() ? "是" : "不是") + "一个有效的邮件地址!"; 22 System.out.println(result); 23 } 24 } 25 }
利用正则表达式对目标字符串进行分割、查找、替换等操作:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.regex.Pattern; 2 import java.util.regex.Matcher; 3 4 public class ReplaceTest{ 5 public static void main(String[] args){ 6 String[] msgs = { 7 "Java has regular expressions in 1.4", 8 "regular expressions now expressing in Java", 9 "Java represses oracular expressions" 10 }; 11 Pattern p = Pattern.compile("re\\w*"); 12 Matcher matcher = null; 13 for(int i = 0; i < msgs.length; i++){ 14 if(matcher == null){ 15 matcher = p.matcher(msgs[i]); 16 }else{ 17 matcher.reset(msgs[i]); 18 } 19 System.out.println(matcher.replaceAll("哈哈:)")); 20 } 21 } 22 }
String类也提供了replaceAll()、replaceFirst()、split()方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.regex.Pattern; 2 import java.util.regex.Matcher; 3 import java.util.Arrays; 4 5 public class StringReg{ 6 public static void main(String[] args){ 7 String[] msgs = { 8 "Java has regular expressions in 1.4", 9 "regular expressions now expressing in Java", 10 "Java represses oracular expressions" 11 }; 12 for(String msg : msgs){ 13 System.out.println(msg.replaceFirst("re\\w*", "哈哈:)")); 14 System.out.println(Arrays.toString(msg.split(" "))); 15 } 16 } 17 }
国际化与格式化:
Java国际化的思路:
Java程序的国际化主要通过如下三个类完成:
1.java.util.ResourceBundle:用于加载国家、语言资源包
2.java.util.Locale:用于封装特定的国家/区域、语言环境
3.java.text.MessageFormat:用于格式化带占位符的字符串
Java支持的国家和语言:
若需要获取Java所支持的国家和语言,则调用Locale类的getAvailableLocales()方法,该方法返回一个Locale数组,该数组中包含了Java所支持的国家和语言
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.Locale; 2 3 public class LocaleList{ 4 public static void main(String[] args){ 5 //返回Java所支持的全部国家和语言的数组 6 Locale[] localeList = Locale.getAvailableLocales(); 7 //遍历数组的每个元素,获取所支持的国家和语言 8 for(int i = 0; i < localeList.length; i++){ 9 //输出所支持的国家和语言 10 System.out.println(localeList[i].getDisplayCountry() + "=" + localeList[i].getCountry() + " " + localeList[i].getDisplayLanguage() + "=" + localeList[i].getLanguage()); 11 } 12 } 13 }
书中的完成程序国际化不知道该怎样做,等我上网搜索之后,在修改。
使用MessageFormat处理包含占位符的字符串: