在实际的项目开发中,经常借助于一些类来帮助完成特定的功能,例如进行数学运算、字符串运算、日期运算等等,这些类由Sun公司提供,放在Java 2 Platform软件包内,不需要用户再次编写而直接使用,我们称这些类叫“Java工具类”,这里将会学习这些工具类的部分内容,在将来的项目中我们就可以通过它们的帮助,来完成很多特定的任务,达到快速开发的目的。所有这些类的详细信息均可以通过查询API规范获得。
在基础库部分,Sun公司提供了极其丰富的功能类,为了便于区分,根据类的功能大致把这些类放在了不同的包内,例如java.lang包、java.util包、java.io包、java.sql包、java.text包等等。这里主要讲解java.lang包及java.text包中的部分类,对于其他的三个包,将会在后续单独讲解。
对于初学者来说,最为常用的工具类有封装类、String、StringBuffer、Random、Date、Calendar、SimpleDateFormat及Math静态类等等;但是,Java学习之路漫长也曲折,Sun公司提供的支持类成千上万,很难一次掌握,即便是本章内容,也拥有众多类和方法的介绍,在后续的学习、工作过程中,也会遇到自己不会甚至没有见过的新类,你会发现,这众多的类和方法之间,其实充满了联系与区别,是有规律可循的,类的名字、方法的名字,也非常便于记忆。只要各位从容面对,勤加练习,善于归纳总结,多多翻阅JDK API帮助文档,那么学好这部分内容是不困难的。
我们知道,java中的基本数据类型是在堆栈上创建的,而所有的对象类型都是在堆上创建的(对象的引用在堆栈上创建)。比如String s=new String(“good luck!”); 其中new String()是在堆上创建的,而它的引用String s是在堆栈上。
很显然,栈内存上的数据比堆内存上的数据速度要快很多,不过,虽然在堆栈上分配内存效率高,不过在堆栈上分配内存有内存泄露的问题,而这并不是任意一个程序员都能解决的问题。并且,对于基本数据类型来说,早在一学期我们就知道它是按值传递的。所以,如果各位想把一个基本数据类型的数据按引用传递,那么是办不到的。包装类(Wrapper Class)的出现,正是为了解决这个问题,包装类把基本数据类型的数据封装为引用类型的对象,而且提供了很多有用的方法。
对于Java的基本数据类型,Sun公司均提供了对应的包装类,如下表所示,各位可以通过查阅API文档来获得这些包装类的详细信息。值得注意的是,所有的包装类均位于java.lang包下,而这个包会由JVM编译器在编译时自动导入我们的程序,所以可以不用手工导入该包下的类而直接使用。
基本数据类型 |
对应包装类 |
boolean |
Boolean |
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
char |
Character |
float |
Float |
double |
Double |
大多包装类均具有如下方法:
·带有基本值参数并创建包装类对象的构造方法,如可以利用Integer包装类创建对象,Integer obj=new Integer(145) 1aD>Zn
·带有字符串参数并创建包装类对象的构造方法,如new Integer("-45.36") A =:(IcM#
d9G{S9X
·生成字符串表示法的toString()方法,如obj.toString()
·:%^D,MGi ·· 对同一个类的两个对象进行比较的equals()方法,如obj1.eauqls(obj2) 6=Hxw$6u0U
·生成哈稀表代码的hashCode方法,如obj.hasCode() w_+c$E i+b ?Zt
·将字符串转换为基本值的 parseType方法,如Integer.parseInt(args[0]) (i' a 4
·可生成对象基本值的typeValue方法,如obj.intValue()
下以int基本类型的包装类Integer和Character为例,带领各位了解包装类。
Integer是int基本类型的包装类,下面我们一起来看看Integer类有哪些特点,从介绍封装类的属性、构造器和方法展开。
属性名称 |
描述 |
static int MAX_VALUE |
返回最大的整型数 |
static int MIN_VALUE |
返回最小的整型数 |
static Class TYPE |
返回当前类型 |
示例:
System.out.println("Integer.MAX_VALUE:"+Integer.MAX_VALUE); |
构造器 |
描述 |
Integer(int value) |
通过一个int的类型构造对象 |
Integer(String s) |
通过一个String的类型构造对象 |
注:本书对类的构造方法、方法的列表如无特殊说明,均指public方法。
示例:
//生成了一个值为1234的Integer对象 Integer i = new Integer(1234); Integer i = new Integer("1234"); |
说明:
1. 所有方法均为public
2. 书写格式:[修饰符] <返回类型> <方法名([参数列表])>
方法名称 |
描述 |
byteValue() |
取得用byte类型表示的整数 |
int compareTo(Integer anotherInteger) |
比较两个整数。相等时返回0;小于时返回负数;大于时返回正数 |
int compareTo(Object o) |
将该整数与其他类进行比较。其中o必须为Integer类实例,否则,抛出ClassCastException异常 |
static Integer decode(String nm) |
将字符串转换为整数 |
double doubleValue() |
取得该整数的双精度表示 |
boolean equals(Object obj) |
比较两个对象 |
float floatValue() |
取得该整数的浮点数表示 |
static Integer getInteger(String nm) |
根据指定名确定系统特征值 |
int hashCode() |
返回该整数类型的哈希表码 |
int intValue() |
返回该整型数所表示的整数 |
long longValue() |
返回该整型数所表示的长整数 |
static int parseInt(String s) |
将字符串转换成整数。 s必须是十进制数组成,否则抛出NumberFormatException异常 |
static int parseInt(String s, int radix) |
以radix为基数radix返回s的十进制数。所谓的基数,就是“几进制” |
short shortValue() |
返回该整型数所表示的短整数 |
static String toBinaryString(int i) |
将整数转为二进制数的字符串 |
static String toHexString(int i) |
将整数转为十六进制数的字符串 |
static String toOctalString(int i) |
将整数转为八进制数的字符串 |
String toString() |
将该整数类型转换为字符串 |
static String toString(int i) |
将该整数类型转换为字符串。不同的是,此为类方法 |
static String toString(int i, int radix) |
将整数i以基数radix的形式转换成字符串 |
static Integer valueOf(String s) |
将字符串转换成整数类型 |
static Integer valueOf(String s, int radix) |
将字符串以基数radix的要求转换成整数类型 |
以下示例使用了compareTo方法对两个Integer对象进行大小比较,比较的内容为Integer对象对应的int值,根据大小相等的不同,返回结果分别为大于、小于、等于0的数字:
Integer i = new Integer(1234); System.out.println("i.compareTo: " + i.compareTo(new Integer(123))); //输出结果为:i.compareTo: 1 |
以下示例返回一个整数的16进制形式字符串:
int i = 54321; System.out.println("Integer.toString(int i, int radix): " + Integer.toString(i,16)); //结果为:Integer.toString(int i, int radix): d431 |
Character 类在对象中包装一个基本类型 char 的值。Character 类型的对象包含类型为 char 的单个字段。
此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,反之亦然。
属性名称 |
属性描述 |
static char MIN_VALUE |
此字段的常量值是 char 类型的最小值,即 '\u0000' |
static char MAX_VALUE |
此字段的常量值是 char 类型的最大值,即 '\uFFFF' |
static Class TYPE |
表示基本类型 char 的 Class 实例 |
Character(char value):以char参数构造一个Character对象
说明:
1. 所有方法均为public;
2. 书写格式:[修饰符]<返回类型> <方法名([参数列表])>
具体方法请查看API文档
示例:
package com.lesson4; /** * Character包装类的用法 */ public class CharacterDemo { public static void main(String[] args) { Character ch1 = new Character('a'); Character ch2 = new Character('A'); // ch1的char值 System.out.println("char value of ch1 : " + ch1.charValue()); // 对比ch1和ch2的大小 System.out.println("ch1 compare to ch2 : " + ch1.compareTo(ch2)); // 表示范围的最小值 System.out.println("min value(int) : " + (int) Character.MIN_VALUE); // 表示范围的最大值 System.out.println("max value(int) : " + (int) Character.MAX_VALUE);
// 判断一个字符是否是数字形式 System.out.println("is digit '1' : " + Character.isDigit('1')); // 判断一个字符是否是大写形式 System.out.println("is upper case 'a' : " + Character.isUpperCase('a')); // 判断一个字符是否是空格 System.out.println("is space char ' ' : " + Character.isSpaceChar(' ')); // 判断一个字符是否是字母 System.out.println("is letter '1' :" + Character.isLetter('1')); // 判断一个字符是否是字母或数字 System.out.println("is letter or digit '好' :" + Character.isLetterOrDigit('好')); // 把字母转化为大写形式 System.out.println("to upper case 'a' :" + Character.toUpperCase('a')); } } |
运行后结果如下:
字符串大量用于我们的程序中,Java提供了String类专门用于表示字符串,内有大量实用的方法,大家要牢牢掌握。
构造器 |
描述 |
String() |
构造一个空字符串对象 |
String(byte[] bytes) |
通过byte数组构造字符串对象 |
String(char[] chars) |
通过字符数组构造字符串对象 |
String(String original) |
构造一个original的副本,即拷贝一个original |
String(StringBuffer buffer) |
通过StringBuffer数组构造字符串对象 |
示例演示String类构造方法的使用:
byte[] b = {'a','b','c','d','e','f','g','h','i','j'}; char[] c = {'0','1','2','3','4','5','6','7','8','9'}; String sb = new String(b); String sb_sub = new String(b,3,2); String sc = new String(c); String sc_sub = new String(c,3,2); String sb_copy = new String(sb); System.out.println("sb: " + sb ); System.out.println("sb_sub: " + sb_sub ); System.out.println("sc: " + sc ); System.out.println("sc_sub: " + sc_sub ); System.out.println("sb_copy: " + sb_copy ); 输出结果为: sb: abcdefghij sb_sub: de sc: 0123456789 sc_sub: 34 sb_copy: abcdefghij |
示例
String s = new String("abcdefghijklmnopqrstuvwxyz"); System.out.println("s.charAt(5): " + s.charAt(5) ); 本例从字符串中提取字符,运行结果为:s.charAt(5): f |
示例:
String s1 = new String("abcdefghijklmn"); String s2 = new String("abcdefghij"); String s3 = new String("abcdefghijalmn"); System.out.println("s1.compareTo(s2): " + s1.compareTo(s2) ); System.out.println("s1.compareTo(s3): " + s1.compareTo(s3) ); 本例对两个字符串进行对比,运行结果为: s1.compareTo(s2): 4 s1.compareTo(s3): 10 |
示例:
String s1 = new String("abcdefghij"); String s2 = new String("ghij"); System.out.println("s1.endsWith(s2): " + s1.endsWith(s2) ); 本例判断一个字符串是否是另外一个字符串的结尾,运行结果为:s1.endsWith(s2): true |
示例:
char[] s1 = {'I',' ','l','o','v','e',' ','h','e','r','!'}; String s2 = new String("you!"); s2.getChars(0,3,s1,7); //s1=I love you! System.out.println( s1 ); 运行结果为:I love you! |
示例:
String s = new String("write once, run anywhere!"); String ss = new String("run"); System.out.println("s.indexOf('r'): " + s.indexOf('r') ); System.out.println("s.indexOf('r',2): " + s.indexOf('r',2) ); System.out.println("s.indexOf(ss): " + s.indexOf(ss) ); 本例在一个字符串中查找某段字符串的位置,注意indexOf方法的不同形式,运行结果为: s.indexOf('r'): 1 s.indexOf('r',2): 12 s.indexOf(ss): 12 |
示例:
String s = new String ("write once, run anywhere!"); String ss = new String("write"); String sss = new String("once"); System.out.println("s.startsWith(ss): " + s.startsWith(ss) ); System.out.println("s.startsWith(sss,6): " + s.startsWith(sss,6) ); 本例判断一个字符串是否是另外一个字符串的开始,运行结果为: s.startsWith(ss): true s.startsWith(sss,6): true |
示例:
String s = new String("java.lang.Class String"); System.out.println("s.toUpperCase(): " + s.toUpperCase() ); System.out.println("s.toLowerCase(): " + s.toLowerCase() ); 本例把一个字符串转换为对应的大写、小写形式,运行结果为: s.toUpperCase(): JAVA.LANG.CLASS STRING s.toLowerCase(): java.lang.class string |
字符串与字符数组关系密切,而且它们可以互相转换,通过String构造方法可以将一个字符数组构造为一个字符串,而通过String类的toCharArray()方法也可以将一个字符串转换为字符数组。其实,通过查看String类的源代码可以知道(多看源码长见识),String类的本质就是由字符数组构建的,String类的第一行就定义到:
/** The value is used for character storage. */ private final char value[]; |
这个值数组是private final类型的,这也说明一个问题,那就是一旦这个数组被赋值,那么它就不能再被修改了,到底是不是这样呢?请看下一节。
首先来看一个示例,示例中使用String类的concat()方法,试图将第二个字符串连接在第一个字符串的后面,使用replace()方法,试图将字符串中的某些字符替换掉。
示例:
package com.lesson4; /** * String类的字符串不变性 */ public class StringDemo { public static void main(String[] args) { String s1 = new String("hello "); //将svse连接在s1的后面 s1.concat("abc"); System.out.println("s1 = " + s1); // 使用replace方法把字符串s2中的字符o替换为u String s2 = new String("good morning!"); s2.replace('o', 'u'); System.out.println("s2 = " + s2); } } |
运行程序,查看结果如下:
可以看到字符串s1、s2虽然尝试进行了修改,但是,它们并没有发生任何变化,这是为什么呢?其实,一个字符串对象一但创建,那么这个字符串对象内容存放地址里面的内容就不能改变,对于s1来说,我们尝试在其后连接上abc,因不能对s1进行直接修改,所以将会创建一个新的字符串对象,而新创建的对象的引用,我们并未将其赋给s1,结果导致s1的值没有变化。对于s2来说,也是一样的道理。
那么如何解决这个问题呢?很简单,把新的字符串的引用,赋给s1、s3即可。
//其余部分省略 s1 = s1.concat("abc"); s2 = s2.replace('o', 'u'); |
由于在对String字符串进行修改的过程中,将会创建新的字符串对象,如果因为需要而反复修改字符串,将大大浪费系统资源,创建一大堆无用的对象。为了避免这种情况出现,我们需要能直接修改的字符串对象,这就是StringBuffer。
在实际应用中,经常会遇到对字符串进行动态修改。这时候,String类的功能受到限制,而StringBuffer类可以完成字符串的动态添加、插入和替换等操作(注意有些中文API上说的是“不能修改”,是误译,英文原版为“can be modified”),对StringBuffer的修改,是直接的,不会创建多余的对象。
构造器名称 |
描述 |
StringBuffer() |
构造一个没有任何字符的StringBuffer类 |
StringBuffer(int length) |
构造一个没有任何字符的StringBuffer类,并且,其长度为length |
StringBuffer(String str) |
以str为初始值构造一个StringBuffer类 |
以下示例演示了对StringBuffer对象进行字符串追加和插入操作。StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
package com.lesson4;
/** * StringBuffer,带有缓冲区的字符串 */ public class StringBufferDemo { public static void main(String[] args) { String question = new String("1+1="); int answer = 3; boolean result = (1 + 1 == 3); StringBuffer sb = new StringBuffer(); sb.append(question); sb.append(answer); sb.append(result); sb.insert(5, ','); System.out.println(sb); } } 结果为: 1+1=3,false |
以下示例调整了StringBuffer的容量,这将会给StringBuffer对象分配更多的空间。其实,如果容量不够,那么编译器将会自动分配更高的容量。
package com.lesson4; /** * 调整StringBuffer对象的容量 */ public class StringBufferDemo { public static void main(String[] args) { StringBuffer sb1 = new StringBuffer(5); StringBuffer sb2 = new StringBuffer(5); sb1.ensureCapacity(6); sb2.ensureCapacity(100); System.out.println( "sb1.Capacity: " + sb1.capacity() ); System.out.println( "sb2.Capacity: " + sb2.capacity() ); } } 结果为: sb1.Capacity: 12 sb2.Capacity: 100 |
以下示例演示了将字符数组复制到字符串:
package com.lesson4; /** *把字符数组放入StringBuffer */ public class StringBufferDemo { public static void main(String[] args) { StringBuffer sb = new StringBuffer("I love her!"); char[] i = {'I',' ','l','o','v','e',' ','y','o','u'}; sb.getChars(7,10,i,7); System.out.println( "sb: " + sb ); } } 结果为:sb: I love her! |
以下示例对字符串进行反转:
package com.svse.lesson4; /** * 反转字符串 */ public class StringBufferDemo { public static void main(String[] args) { StringBuffer sb = new StringBuffer("0123456789"); System.out.println( "sb.reverse(): " + sb.reverse() ); } } 结果为:sb.reverse(): 9876543210 |
以下示例设置字符序列的长度。序列将被更改为一个新的字符序列,新序列的长度由参数指定。
package com.lesson4; /** * 截断字符串 */ public class StringBufferDemo { public static void main(String[] args) { StringBuffer sb = new StringBuffer("0123456789"); sb.setLength(5); System.out.println( "sb: " + sb ); } } 结果为:sb: 01234 |
此类用来产生随机数,位于java.util包中,所以需要手工导包。
构造器 |
描述 |
Random() |
创建一个新的随机数发生器 |
Random(long seed) |
用一个种子(长整型)创建一个随机数发生器 |
说明:
1. 所有方法均为public;
2. 书写格式:[修饰符]<返回类型> <方法名([参数列表])>
请注意nextInt(int n)的取值范围及其和nextInt()方法的区别。
Random这个类的对象使用一个48位的种子,如果这个类的两个实例是用同一个种子创建的,并且,各自对它们以同样的顺序调用方法,则它们会产生相同的数字序列。
下面就对上面的介绍做一个演示,尤其注意相同种子时的结果,如果用默认的构造函数构造对象,它们是属于同一个种子的;演示代码如下所示:
示例
package com.lesson4;
import java.util.Random; /** * 根据随机种子获得随机序列 */ public class RandomDemo { public static void main(String[] args) { Random r1 = new Random(50); System.out.println("第一个种子为50的Random对象"); System.out.println("r1.nextBoolean():\t" + r1.nextBoolean()); System.out.println("r1.nextInt():\t\t" + r1.nextInt()); System.out.println("r1.nextDouble():\t" + r1.nextDouble()); System.out.println("r1.nextGaussian():\t" + r1.nextGaussian()); System.out.println("---------------------------"); Random r2 = new Random(50); System.out.println("第二个种子为50的Random对象"); System.out.println("r2.nextBoolean():\t" + r2.nextBoolean()); System.out.println("r2.nextInt():\t\t" + r2.nextInt()); System.out.println("r2.nextDouble():\t" + r2.nextDouble()); System.out.println("r2.nextGaussian():\t" + r2.nextGaussian()); System.out.println("---------------------------"); Random r3 = new Random(100); System.out.println("种子为100的Random对象"); System.out.println("r3.nextBoolean():\t" + r3.nextBoolean()); System.out.println("r3.nextInt():\t\t" + r3.nextInt()); System.out.println("r3.nextDouble():\t" + r3.nextDouble()); System.out.println("r3.nextGaussian():\t" + r3.nextGaussian()); System.out.println("结果一目了然!"); } } 结果: 第一个种子为50的Random对象 r1.nextBoolean(): true r1.nextInt(): -1727040520 r1.nextDouble(): 0.6141579720626675 r1.nextGaussian(): 2.377650302287946 --------------------------- 第二个种子为50的Random对象 r2.nextBoolean(): true r2.nextInt(): -1727040520 r2.nextDouble(): 0.6141579720626675 r2.nextGaussian(): 2.377650302287946 --------------------------- 种子为100的Random对象 r3.nextBoolean(): true r3.nextInt(): -1139614796 r3.nextDouble(): 0.19497605734770518 r3.nextGaussian(): 0.6762208162903859 |
Java在日期类中封装了有关日期和时间的信息,类 Date 表示特定的瞬间,精确到毫秒。用户可以通过调用相应的方法来获取系统时间或设置日期和时间。
构造器名称 |
描述 |
Date() |
创建的日期类对象的日期时间被设置成创建时刻相对应的日期时间 |
Date(long date) |
long型的参数date可以通过调用Date类中的static方法parse(Strings)来获得 |
示例:
package com.svse.lesson4;
import java.util.Date;
/** * Date类的基本用法 * @author svse * */ public class DateDemo { public static void main(String[] args) { Date date1 = new Date(); Date date2 = new Date(1233997578421L); //输出date1、date2对象所对应的毫秒数 System.out.println(date1.getTime()); System.out.println(date2.getTime()); //查看date1是否在date2后 boolean isAfter = date1.after(date2); System.out.println("is date1 after date2:"+isAfter); date1.setTime(1133997578421L); isAfter = date1.after(date2); System.out.println("is date1 after date2:"+isAfter); } } |
运行结果如下:
Date类的方法
在历史上有着许多种纪元的方法,它们的差异实在太大了,不同的开发商也会开发出不同的日历计算方式。比如说一个人的生日是“八月八日” 那么一种可能是阳(公)历的八月八日,但也可以是阴(农)历的日期。所以为了计时的统一,必需指定一个日历的选择。那现在最为普及和通用的日历就是 “Gregorian Calendar”——格里高利历。也就是我们在讲述年份时常用 “公元几几年”。Calendar 抽象类定义了足够的方法,让我们能够表述Gregorian Calendar的规则。它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。
注意,由于Calendar类是一个抽象类,所以不能直接通过new关键字创建Calendar类的实例,可以借助于该类提供的静态方法getInstance()来获得一个Calendar对象。正像Date类的默认构造方法一样,该对象所代表的日期正是当前系统日期:
Calendar rightNow = Calendar.getInstance();
Calendar抽象类有一个具体子类:GregorianCalendar。
字段名称 |
描述 |
static int AM |
指示从午夜到中午之前这段时间的 AM_PM 字段值。 |
static int AM_PM |
get 和 set 的字段数字,指示 HOUR 是在中午之前还是在中午之后。 |
static int DATE |
get 和 set 的字段数字,指示一个月中的某天。 |
static int DAY_OF_MONTH |
get 和 set 的字段数字,指示一个月中的某天。 |
static int DAY_OF_WEEK |
get 和 set 的字段数字,指示一个星期中的某天。 |
static int DAY_OF_WEEK_IN_MONTH |
get 和 set 的字段数字,指示当前月中的第几个星期。 |
static int AY_OF_YEAR |
get 和 set 的字段数字,指示当前年中的天数。 |
static int HOUR |
get 和 set 的字段数字,指示上午或下午的小时。 |
static int HOUR_OF_DAY |
get 和 set 的字段数字,指示一天中的小时。 |
static int MILLISECOND |
get 和 set 的字段数字,指示一秒中的毫秒。 |
static int MINUTE |
get 和 set 的字段数字,指示一小时中的分钟。 |
static int MONTH |
指示月份的 get 和 set 的字段数字。 |
static int PM |
指示从中午到午夜之前这段时间的 AM_PM 字段值。 |
static int SECOND |
get 和 set 的字段数字,指示一分钟中的秒。 |
protected long time |
日历的当前设置时间,以毫秒为单位,表示自格林威治标准时间 1970 年 1月 1 日 0:00:00 后经过的时间。 |
static int WEEK_OF_MONTH |
get 和 set 的字段数字,指示当前月中的星期数。 |
static int WEEK_OF_YEAR |
get 和 set 的字段数字,指示当前年中的星期数。 |
static int YEAR |
指示年的 get 和 set 的字段数字。 |
请各位观察API中Calendar类常见的字段和方法,可以发现,这些方法,有的是抽象的,有的是最终方法(final),还有的是静态方法,这体现了程序设计的严谨性:在不同的环境下,不同的需求将导致不同的方法设计。
可能有同学会想不通,该类是一个抽象类,其中有一个抽象方法add(),那么add()方法能不能使用呢?我们慢慢来分析,由于Calendar类是抽象类,我们在获得Calendar实例时,使用的是getInstance()方法,其实,该方法返回的是Calendar类的子类对象,该子类为GregorianCalendar,也就是说,“Calendar ca = Calendar.getInstance()”其实是让ca引用了子类GregorianCalendar的对象,相当于Calendar ca = new GregorianCalendar(),这在语法上是允许的,并且前面的课程中也做过相应介绍。对于GregorianCalendar类来说,其内部实现了抽象的add()方法,所以,我们如果让ca调用add()方法,事实上是调用了GregorianCalendar类的add()方法,是没有任何问题的。
示例:
package com.lesson4;
import java.util.Calendar; import java.util.Date;
/** * Calendar类的常见方法 */ public class CalendarDemo { public static void main(String[] args) { //创建Calendar实例 Calendar ca = Calendar.getInstance(); //获得ca所包含的年份。注意写法 System.out.println("year is :"+ca.get(Calendar.YEAR)); //为年份增加2 ca.add(Calendar.YEAR, 2); System.out.println("year is :"+ca.get(Calendar.YEAR)); //设置ca的年份 ca.set(Calendar.YEAR,2009); System.out.println("year is :"+ca.get(Calendar.YEAR)); //今天是今年的第几天 System.out.println("day of year:"+ca.get(Calendar.DAY_OF_YEAR)); //今天是本周的第几天,注意默认情况下周日是第一天 System.out.println("day of week : "+ca.get(Calendar.DAY_OF_WEEK)); //获得对应的Date对象 Date date = ca.getTime(); System.out.println("date time : "+date.getTime()); System.out.println("calendar time : "+ca.getTimeInMillis()); } }
|
执行程序,运行结果如下:
SimpleDateFormat类可以对Date及字符串进行分析,并在它们之间相互转换,它允许格式化 (date -> text)、语法分析 (text -> date)和标准化。它的继承关系如下:
java.lang.Object
+----java.text.Format
+----java.text.DateFormat
+----java.text.SimpleDateFormat
示例演示了该类在JavaBean内提供日期时间服务的通常用法:
package com.lesson4;
import java.text.SimpleDateFormat; import java.util.Date; /** * SimpleDateFormat对日期和时间进行格式化 */ public class FormatDateTime { /** 长日期格式*/ public static String toLongDateString(Date dt) { SimpleDateFormat myFmt = new SimpleDateFormat( "yyyy年MM月dd日 HH时mm分ss秒 E "); return myFmt.format(dt); } /** 短日期格式*/ public static String toShortDateString(Date dt) { SimpleDateFormat myFmt = new SimpleDateFormat("yy年MM月dd日 HH时mm分"); return myFmt.format(dt); } /** 长时间格式*/ public static String toLongTimeString(Date dt) { SimpleDateFormat myFmt = new SimpleDateFormat("HH mm ss SSSS"); return myFmt.format(dt); } /**短时间格式*/ public static String toShortTimeString(Date dt) { SimpleDateFormat myFmt = new SimpleDateFormat("yy/MM/dd HH:mm"); return myFmt.format(dt); } /**main方法进行测试*/ public static void main(String[] args) { Date now = new Date(); System.out.println(FormatDateTime.toLongDateString(now)); System.out.println(FormatDateTime.toShortDateString(now)); System.out.println(FormatDateTime.toLongTimeString(now)); System.out.println(FormatDateTime.toShortTimeString(now)); } } |
运行效果如下:
Math类中的静态方法帮助我们完成基本的数学运算,它的定义形式为:
public final class Math extends Object
可以看出,Math类是一个最终类,也就是说,它不能被继承,更不能被重写,Sun公司的牛人们不乐意看到它被别人改动,Math类中的方法全部为静态方法,直接使用就行。
示例:
package com.lesson4;
/** * Math类的用法 */ public class MathDemo { public static void main(String[] args) { // 绝对值 System.out.println("abs of -1 : " + Math.abs(-1)); // 比这个数大的最小整数 System.out.println("ceil of 9.01 : " + Math.ceil(9.01)); // 比这个数小的最大整数 System.out.println("floor of 9.99 :" + Math.floor(9.99)); // 取较大者 System.out.println("the max is : " + Math.max(101, 276.001)); // 随机数,区间为[0.0,1.0) System.out.println("random number : " + Math.random()); // 四舍五入 System.out.println("round value of 9.49 :" + Math.round(9.49)); // 返回正确舍入的 double 值的正平方根 System.out.println("square root of 225 : " + Math.sqrt(225)); } }
|
运行后结果如下: