本篇博客中我们来介绍几种常用的工具类,分为两部分,一部分是包含在java.lang包中的工具类,包括Sysgtem、Runtime、Process以及Math;另一部分是,包含在java.util包中的工具类,包括Date、Calendar和Random。
1. System工具类
该工具类位于Java标准类库中的java.lang包中。
首先来看该类的API文档描述:“System类包含一些有用的类字段和方法。它不能被实例化”。这是符合工具类的特点的,无法创建对象,那么通常就会对外提供静态的方法和字段。下面简单介绍System类的一些常用字段和方法。
1.1 System类字段
(1) out
out字段代表了“标准”输出流,是System类的字段中最被我们熟知的,因为打印语句(System.out.println(data))中就会使用到该字段。而之所以out可以用于打印是因为,该字段或者静态成员变量指向的是一个称为打印流的对象——PrintStream,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。如果我们再继续查阅PrintStream类的API文档,就可知该类中定义了大量的打印方法,包括我们常用的println和print方法。那么System工具类、System的字段out以及out指向的PrintStream的println方法就组成了一个完整的打印输出语句。
(2) in
in字段代表“标准”输入流,它可以用于键盘录入,可以接收到用户键盘所输入的所有指令。
1.2 System类方法
篇幅所限,不再对该类的所有方法进行一一说明和演示,感兴趣的朋友可自行查阅API文档并尝试。
1.2.1getProperties——获取所有系统属性信息
Property的意思是属性。Java虚拟机在运行的同时会加载一些默认的系统属性信息,那么通过该方法就可以获取到这些属性信息。
方法说明:
public static PropertiesgetProperties():确定当前的系统属性。该方法的返回值类型是Properties类,该类就是用于描述系统属性信息的。查阅Properties类的API文档可知,该类位于Java标准类库的java.util包中,其直接父类是Hashtable,虽然前面我们说过Hashtable类已经被HashMap集合所替代,但是其子类还是可以使用的。那么从Hashtable的特点可知,Properties同样是一个双列集合,也就是说,可以通过Map集合的方法来获取存储于其中的键值对。该集合中每个键及其对应值都是字符串,但没有定义泛型,因此只能通过Object变量接收键和值。
方法演示:
代码1:
import java.util.*;
class SystemDemo
{
public static void main(String[] args)
{
//获取系统属性信息对象
Properties prop = System.getProperties();
//获取Properties集合中的属性值,通过Foreach
//由于未使用泛型,因此通过Object临时变量来接收键
for(Objectobj : prop.keySet())
{
/*
通过Properties类的get方法,由键获取值
由于不涉及String类的特有方法
这里同样可以直接使用Object变量来接收值
*/
String value = (String)prop.get(obj);
System.out.println(obj+"="+value);
}
}
}
执行结果为:
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=D:\jdk1.7.0_25\jre\bin
java.vm.version=24.65-b04
java.vm.vendor=Oracle Corporation
………
内容较多,篇幅所限不再全部列出。
小知识点1:
该段代码的执行结果较多,可以在命令行中输入“java SystemDemo > 指定路径\文件名.txt”的方式,将结果存入一个文本文件中,方便查看。
小知识点2:
以上系统属性信息是随着系统的不同而发生变化的,因此在不同运行环境下的执行结果将会有所不同。并且Java虚拟机在启动的时候就会将整个系统属性信息进行一次扫描。
我们简单介绍以上执行结果其中几个属性的意义。
java.runtime.name:表示Java虚拟机运行时环境,其值表示Java标准版运行环境。
sun.boot.library.path:表示Java类库的所在路径。
java.vm.version:表示Java虚拟机的版本。
user.country:表示用户所在国家。CN代表中国。
user.dir:表示用户目录。也就是当前所执行的class文件所在目录。
os.name:表示计算机操作系统名称。
file.encoding:表示文件编码。GBK表示中文编码表。
java.home:表示虚拟机所在目录。
user.language:表示用户语言。zh表示中文。
此外,Properties类中也提供了专门用于打印所有系统属性信息的方法——stringPropertyNames(),该方法返回存有全部键的Set集合。
1.2.2 getProperty——查看指定系统属性信息
如果不需要获取全部系统属性信息,而是查看单个信息,可以通过getProperty方法实现。
方法说明:
public static StringgetProperty(String key):获取指定键指示的系统属性。
方法演示:
代码2:
import java.util.*;
class SystemDemo2
{
public static void main(String[] args)
{
Properties prop = System.getProperties();
//获取单一的系统属性键值对
String value = System.getProperty("os.name");
System.out.println("os.name="+value);
}
}
执行结果为:
os.name=Windows 7
上述代码的执行会随着所在操作系统的不同而发生变化,那么该方法的应用情形就是当该程序执行时对所在操作系统进行判断,并根据不同的操作系统采取不同的执行内容。比如,软件的安装程序,一种软件通常会为不同的操作系统开发不同的版本,因此在执行安装程序以前,应首先进行操作系统版本的判断,如果所在操作系统为未知操作系统,那么安装程序就应终止。
1.2.3 setProperty——设置系统属性
通过Properties类,我们不仅可以获取并查看系统属性信息,还可以自定义一些属性信息,并为其赋值,而setProperty方法便能够帮助我们实现该功能。
方法说明:
public Object setProperty(Stringkey,String value):调用Hashtable的方法put。使用getProperty方法提供并行性。强制要求为属性的键和值使用字符串。返回值是Hashtable调用put的结果。参数列表中的key表示键,value表示值,它们的变量类型均为String。
方法演示:
代码3:
import java.util.*;
class SystemDemo3
{
public static void main(String[] args)
{
//获取系统属性信息对象
Properties prop = System.getProperties();
//添加自定义系统属性信息
System.setProperty("mykey","myvalue");
//获取Properties集合中的属性值
//由于未使用泛型,因此通过Object临时变量来接收键
for(Objectobj : prop.keySet())
{
/*
通过Properties类的get方法,由键获取值
由于不涉及String类的特有方法
这里同样可以直接使用Object变量来接收值
*/
String value = (String)prop.get(obj);
System.out.println(obj+"="+value);
}
}
}
执行结果为:(有省略)
java.runtime.name=Java(TM) SE RuntimeEnvironment
sun.boot.library.path=D:\jdk1.7.0_25\jre\bin
java.vm.version=24.65-b04
………….
user.dir=D:\java_samples\18th_day
mykey=myvalue
java.runtime.version=1.7.0_67-b01
………….
sun.cpu.endian=little
sun.desktop=windows
sun.cpu.isalist=pentium_pro+mmx pentium_pro pentium+mmxpentium i486 i386 i86
结果显示,通过setProperty方法成功设置了自定义属性。通过这一方法我们可以设置编码格式,或者自定义一个用于存储程序配置文件的临时目录,那么启动一些程序时可以设置从这个临时目录读取配置文件。
1.2.4 动态设置系统属性
通过setProperty方法设置系统属性信息的方式是一种相对静态的方式,因为属性键值对在编辑程序代码时就需要定义,而如果我们需要获取的系统属性只有在程序运行时由调用者指定的话,也就是说需要动态的设置系统属性时,就需要使用Java虚拟机的功能。
在命令行中输入“java”来启动虚拟机,并列出java虚拟机所支持各种命令及使用方法。其中有一项功能的格式为:-D<名称>=<值>,该功能可以用于动态设置系统属性。其中,名称表示属性的键,值就是表示属性的值,我们以下面的代码为例,
代码4:
import java.util.*;
class SystemDemo4
{
public static void main(String[] args)
{
Properties prop = System.getProperties();
//并没有在代码中设置key键对应的属性值
String value = System.getProperty("key");
System.out.println("key="+value);
}
}
对以上代码进行编译以后,输入如下命令:
java –Dkey=value SystemDemo4
则执行结果为:
key=value
当我们在启动虚拟机执行上述程序时,指定了key的值为value,因此获取到了该键值对,如果不指定key的值,那么打印结果将是null。
2. Runtime工具类
2.1 Runtime工具类简介
该工具类同样位于Java标准类库中的java.lang包中。Runtime的意思是运行时,该类的API文档描述为:每个Java应用程序都有一个Runtime类实例,使应用程序能够与其中运行的环境相连接。由于Java语言的跨平台性,当由Java语言编写的程序在运行时,就需要由Runtime类实例来封装这个进程,并将这个程序与运行环境进行连接。换句话说,Runtime对象是不需要程序员手动创建的,只要Java程序一执行就会自动创建一个与之相关的Runtime对象。
2.2 Runtime工具类方法介绍
(1) getRuntime
从API文档这知,该工具类并没有定义构造方法,因此无法通过new关键字创建对象。但另一方面,该类也并没有像System类那样对外提供大量的静态方法,相反几乎全部都是需要由对象调用的非静态方法。由此,我们推测,Runtime类一定定义了一个返回值类型为Runtime的静态方法,由该方法获取到本类对象,该方法就getRuntime方法。
方法说明:
public staticRuntime getRuntime():返回与当前Java应用程序相关的运行时对象。实际上,该方法的设计思想就是单例设计模式。因为一个进程对应的Runtime对象有且只能有一个,那么为了保证它的唯一性,就规定只能通过一个静态方法获取到唯一的本类对象。
我们结合其他方法来演示getRuntime方法的使用。
(2) exec
方法说明:
public Processexec(String command) throws IOException:在单独的进程中执行指定的字符串命令。exec其实是execute单词的简写,意思是执行,而参数列表中的参数名称command意思就是命令。
方法演示:
代码5:
//由于需要抛出IOException异常,因此需要导入io包
import java.io.*;
class RuntimeDemo
{
public static void main(String[] args)throws IOException
{
Runtime runtime = Runtime.getRuntime();
//通过exec方法,执行Windows自带的扫雷程序
runtime.exec("C:\\ProgramFiles\\Microsoft Games\\Minesweeper\\MineSweeper.exe");
}
}
执行以上Java代码将会启动扫雷游戏。我们可以将传递的参数指定为任意目录中的任意可执行程序,这里不再一一演示。举例说明该方法的一个实际应用,通常网吧的电脑中都会将各种软件分门别类的使用一些小程序封装了起来,一个图表对应一个小程序,比如打开“游戏”图表,就会弹出一个面板,面板中又包含了各种游戏的图表,点击图表就可执行指定的游戏程序。
进行两点说明:
1. 该方法抛出了IOException异常。因此需要对其进行处理,要么将其声明到主函数,要么在主函数内进行try-catch处理。这里为演示方便将其声明到主函数。实际上,调用exec方法其实就是在读取指定路径中的一个exe文件,当该指定的路径错误时,将无法正确启动指定程序,因此就将这种情况下可能发生的问题封装为了一个异常对外进行声明。由于IOException异常位于Java标准类库中的java.io包中,因此需要在代码开头将进行导包动作。
2. 我们将扫雷程序所在路径作为参数传递到exec方法时,使用两个反斜杠“\\”作为每个目录层级之间的分隔符。而实际上,在Java语言中一个反斜杠本身就表示了一个分隔符,只是单个反斜杠在字符串中存在时,将被默认为是反义字符,因此在一个“\”前再加一个“\”表示将反义字符再反义为其原本的作用。
exec方法不仅可以执行某个程序,还可以将使用程序打开一些文件,比如通过记事本程序打开文本文档,如下代码所示,
代码6:
import java.io.*;
class RuntimeDemo3
{
public static void main(String[] args)throws IOException
{
Runtime runtime = Runtime.getRuntime();
//通过exec方法,通过记事本程序打开一个文本文件
runtime.exec("C:\\Windows\\System32\\notepad.exeDemo.txt");
}
}
依然向exec方法中传递字符串形式的命令,以空格分隔,空格前为应用程序名及其地址,空格后为文件名、格式,如果需要也可以指定文件所在路径。
3. Process类
以上exec方法的返回值类型为Process,意思是进程。查阅其API文档,对Process类的描述为:ProcessBuilder.start()和Runtime.exec方法创建的一个本机进程。这里我们先暂且不要管前两个方法,只需要知道该类对象用于封装进程即可。并且该类是一个抽象类,其方法摘要中的方法也均是抽象方法,但其继承体系中却并没有定义子类。这是因为,一个Java程序执行,对应的进程就已经由所在系统的底层创建好了,不需要手动创建,而由底层创建的进程实例就是Process抽象类的子类对象。
对于Process类的方法,这里我们仅介绍其中一个——destroy。
方法说明:
public abstract voiddestroy():杀掉子进程。强制终止此Process对象表示的子进程。
方法演示:
代码6:
import java.io.*;
class RuntimeDemo2
{
public static void main(String[] args)throws IOException
{
Runtime runtime = Runtime.getRuntime();
//通过exec方法,执行Windows自带的扫雷程序
Processpro =
runtime.exec("C:\\ProgramFiles\\Microsoft Games\\Minesweeper\\MineSweeper.exe");
//为了看到明显的效果,将该线程冻结4s钟
try{Thread.sleep(4000);}catch(InterruptedExceptione){}
pro.destroy();
}
}
执行上述代码,将会观察到扫雷程序执行了一段时间后,被关闭。
如果不冻结主线程,将观察不到任何现象,因为子进程(扫雷)一被执行,就马上被“杀掉”,而这一过程速度很快,将不会发生任何现象。
可能有朋友回想到,既然destroy方法可以用于关闭子进程,那么是不是可以用于关闭任意进行呢?答案是否定的。因为,Process对象的destroy方法只能关闭该对象所对应的进程,或者说是由Runtime类exec方法启动的进程,除此以外的进程由于我们无法获取到对应的Process对象而无法关闭。当然,我们可以通过编写C/C++程序时可以实现的。
4. Math类
顾名思义,Math主要就是用于数学计算,该类包含于Java标准类库java.lang包中。其API文档描述为:Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。由于是典型的工具类,因此该类的字段以及方法全部为静态。
4.1 Math类字段
Math类中定义了两个静态字段,分别是表示自然对数的底数e和圆周率π。当我们需要使用到这两个常数参与计算时,只需要通过Math类名调用即可。
4.2 Math类方法
(1) ceil、floor、round
public static doubleceil(double a):返回最小的(最接近负无穷大)double值,该值大于等于参数,并等于某个整数,简单理解就是取得大于指定数字的最小整数。ceil的意思就是天花板,也就是说向上取整。
public static doublefloor(double a):返回最大的(最接近无穷大)double值,该值小于等于参数,并等于某个整数。简单理解就是取得小于指定数字的最大整数。floor的意思就是地板,也就是说向下取整。
public static longround(double a):返回最接近参数的long值。简单理解就是四舍五入。它的原理是:(long)Math.floor(a+0.5d)。
方法演示:
代码7:
class MathDemo
{
public static void main(String[] args)
{
//ceil
System.out.println(Math.ceil(12.3));
System.out.println(Math.ceil(-12.3));
//floor
System.out.println(Math.floor(12.3));
System.out.println(Math.floor(-12.3));
//roud
System.out.println(Math.round(12.3));
System.out.println(Math.round(-12.3));
System.out.println(Math.round(12.8));
System.out.println(Math.round(-12.8));
}
}
执行结果为:
13.0
-12.0
12.0
-13.0
12
-12
13
-13
(2) pow
public static doublepow(double a,double b):返回第一个参数的第二个参数次幂。a表示底数,b表示指数,返回值就是a的b次方。
方法演示:
代码8:
class MathDemo2
{
public static void main(String[] args)
{
int a = 2,b = 3;
System.out.println(a+"^"+b+"= "+Math.pow(a,b));
}
}
执行结果为:
2 ^ 3 = 8.0
(3) random
public static doublerandom():返回带正号的double值,该值大于等于0.0且小于1.0。返回值是一个伪随机选择的数,在该范围内(近似)均匀分布。第一次调用该方法时,它将创建一个新的伪随机数生成器,也就是new java.util.Random()(下面的内容中将详细说明)。这里之所以称之为伪随机数,是因为这些所谓随机数的生成实际是通过底层的一些算法实现的,那么一旦涉及了算法就不再是纯粹意义上的随机数了,因为只要将某种算法多次调用就有可能找到规律。
方法演示:
代码8:
package test28;
class MathDemo3
{
public static void main(String[] args)
{
for(int x = 0; x<10; x++)
{
System.out.println(Math.random());
}
}
}
执行结果为:
0.9572171773197102
0.22295095125786757
0.803316594234924
0.22976768654775892
0.3189566020512852
0.7124567903694518
0.28032054351281566
0.2526437479171978
0.9680317737860484
0.6066807575405444
多次运行以上代码的结果将会有所不同。以上结果默认只能获取到0到1之间的小数(不包括1),如果想要获取1到10之间的整数可以将以上代码做如下修改,
代码9:
class MathDemo4
{
public static void main(String[] args)
{
for(int x = 0; x<10; x++)
{
//强转为整型数,舍掉小数点后的数
int value = (int)(Math.random()*10+1);
System.out.println(value);
}
}
}
执行结果为:
5
2
7
7
7
4
8
2
5
7
5. Date类
Date类位于Java标准类库中的java.util包中。在实际开发过程中,程序员经常需要操作时间,那么Date类就是专门用于操作时间的一个工具类。我们首先通过以下代码,来对Date类作一个初步了解。
代码10:
import java.util.*;
class DateDemo
{
public static void main(String[] args)
{
Date date = new Date();
System.out.println(date);
}
}
上述代码的运行结果为:
Sun Oct 05 15:35:56 CST 2014
第一行导包就不多说了,直接在主函数中创建一个Date对象,接着打印这个Date对象。这个输出结果表示中国标准时间2014年,十月5日,15点35分56秒,星期日。通过输出结果我们发现,虽然经过一番研究可以大概看懂表示的时间,但是不够直观,也不符合大多数人的习惯。为了使得输出的时间更为直观,需要调整一下显示格式。但是由于新版的JDK中Date类的大多数方法已经过时了,现在通常通过“SimpleDateFormat”(简单日期格式)这个类来调整日期和时间的格式,而“SimpleDateFormat”类包含在Java标准类库java.text包中,因此需要在代码开头进行导包。
通过查看SimpleDateFormat类的API文档得知,该类的构造函数需要传入一个字符串类的模式pattern,具体代码为:
SimpleDateFormat(String pattern)
这个模式,指的就是将来显示时间的格式,比如“yyyy-MM-dd”,其中y表示年份,大写M表示年中的月份,d表示月份中的天数。字母重复几次就表示这个日期有几位。这些字母的写法及其组合方式是有严格限制的,具体表示方式请参见API文档。将代码1稍作修改。
代码11:
import java.util.*;
import java.text.*;
class DateDemo2
{
public static void main(String[] args)
{
Date date = new Date();
//将日期的显示模式封装到SimpleDateFormat对象中
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
//通过format方法,根据上面的模式,返回指定的Date对象的格式化表现形式(字符串表示)
String formatTime = sdf.format(date);
System.out.println(formatTime);
}
}
上面代码的运行结果为:
2014年10月05日
上述代码就是SimpleDateFormat类最简单的使用方法,当然也可以显示时分秒和星期,有兴趣的朋友可以自行查阅API文档。
6. Calendar类
6.1 Calendar类简介
上一篇我们讲到了Date和SimpleDateFormat实现了时间与日期的格式化显示。那么,如果我们只想单独获取年份、月份、日期、星期等等时间又该如何做呢?可能有朋友想到了下面的方法,
代码12:
import java.util.*;
import java.text.*;
class CalendarDemo
{
public static void main(String[] args)
{
Date date = new Date();
//传入的格式只有4位年份
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年");
String year = sdf.format(sdf);
System.out.println(year);
}
}
上述的运行结果是:
2014年
从结果来看,是可以的。但是通过调用format方法获取的时间是字符串类型变量,如果想要对时间进行加减等操作,就会比较麻烦(Integer.parseInt()方法)。因此,这里我们就要介绍一个新的时间工具类——Calendar(日历),这个类可以在java.util包中找到,下面我们介绍几个常用的方法
Calendar类常用方法介绍:
1) public static Calendar getInstance()
API文档中的解释是“使用默认时区和语言环境获得一个日历”,实际上就是获取封装有当前时间所有信息的一个Calendar(日历)对象,这些信息包括年月日、星期、时区等等。实际上,Calendar是抽象类,所以上述对象其实是Calendar类的子类GregorianCalendar
的对象。
2) public int get(int field)
field表示Calendar类中定义的很多静态整型字段,比如YEAR表示年,MOMTH表示月份,DAY_OF_MONTH表示月份中的日期,通过将这些字段传入get方法获取这些字段对应的时间项的当前值。
3) public final void set(int year, int month, int date)
该方法通过向该方法传入年月日等时间项的整型数来设置时间。该方法和get方法结合,可以用于时间推算,比如可以解决去年的今天是星期几等问题
4) publiv abstract void add(int field, int mount)(GregorianCalendar
类
)
该方法可以对某个时间项进行增减运算,而且自动的适配相应的年月日,比如2010年12月22日加1个月,就是2011年1月22日等等。
需要注意的是,Calendar类中认为月份从0开始直到11月,而一个星期从星期日开始,以星期六结束。而且,所有的时间值都是用整型数表示的,这显然不符合日常的阅读习惯。下面我们通过代码来说说如何使用这些方法,并作出一些改善便于阅读。
6.2 时间的获取
代码13:
import java.util.*;
import java.text.*;
class CalendarDemo2
{
public static void main(String[] args)
{
/*
由于Calendar类中定义的月份和星期不符合日常阅读习惯,因此将字符串形式的月份和星期存储于数组中,将get方法返回的整型数作为序号获取对应的时间值
*/
int[] months = {"一月", "二月", "三月","四月",
"五月","六月", "七月", "八月",
"九月","十月", "十一月", "十二月"};
String[] weeks = {"","星期日", "星期一", "星期二", "星期三","星期四","星期五", "星期六"};
//获取当前时间的日历对象
Calendar c = Calendar.getInstance();
//调用日历对象的get方法,并传入Calendar内定义的字段获取时间
int year = c.get(Calendar.YEAR);//年份
int month = months[c.get(Calendar.MONTH)];//月份,结合查表法
int date = c.get(Calendar.DAY_OF_MONTH);//月中的日期
String day = weeks[c.get(Calendar.DAY_OF_WEEK)];//星期中的日期,结合查表法
System.out.println(year+"年"+month+"月"+date+"日"+day);
}
}
上述代码的运行结果为:
2014年十月5日星期日
这里我们使用查表法来解决。预先定义两个数组,分别表示月份和星期,使用时,将通过get获取的int型日期作为序号获取序号对应的时间值。由于通过get获得的星期没有0,因此定义星期数组时,第一位定义为空字符串,并从星期日开始(这是因为,西方国家认为一个星期从星期日开始)。这样就解决了时间显示不符合日常的阅读习惯的问题。
6.3 时间的设置与增减
上面的内容主要讲了获取当前时间的方法,而在实际开发过程中,可能还需要对时间进行计算、修改或者设置,比如推算去年的今天是星期几,20天前是几号等等问题,那么这一节就来学习如何对时间进行设置与计算。
1) 时间的设置
代码14:
class CalendarDemo3
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
//设置时间
c.set(2010,11, 22);
calculate(c);
}
public static void calculate(Calendar c)
{
//定义符合阅读习惯的星期和月份数组
String[] months = {"一月", "二月", "三月","四月",
"五月","六月", "七月", "八月",
"九月", "十月","十一月", "十二月"};
String[] weeks = {"", "星期日", "星期一","星期二", "星期三",
"星期四","星期五", "星期六"};
//调用日历对象的get方法,并传入Calendar内定义的字段获取时间
int year = c.get(Calendar.YEAR);//年份
String month = months[c.get(Calendar.MONTH)];//月份
int date = c.get(Calendar.DAY_OF_MONTH);//月中的日期
String day = weeks[c.get(Calendar.DAY_OF_WEEK)];//星期中的日期
System.out.println(year+"年"+month+"月"+date+"日"+day);
}
}
上述代码的运行结果为:
2010年十二月月22日星期三
上面的代码唯一与代码4不同就是,在获取当前日历对象以后,对这个日历对象的时间进行了自定义设置,最终通过底层代码的计算得到了2010年12月22日那天是星期三。注意,调用set方法设置时间时,不要忘记月份从0开始,星期从星期日开始。
2) 时间的增减
时间的增减通过Calendar类的add方法实现,具体代码如下,以年的增减为例:
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR, 4);
上述代码表示,在当前时间基础上加4年,第一个参数表示需要修改的时间项,第二个参数表示偏移量。具体的代码就不一一赘述了,希望大家自己实践。
6.4 练习
这一部分的前两个练习比较简单,因此只提供思路,具体代码希望大家可以自行完成。第三题用代码体现。
1) 练习1
题干:获取任一年二月的天数。
思路:
a) 根据用户输入的年份,通过set方法设置一个年份——xxxx年,3月,1日。
b) 在上述日期基础上,向前偏移一天,就是当年2月的最后一天。
c) 获取当年2月最后一天的日期,就是2月的天数。
2) 练习2
题干:获取昨天现在这个时刻
思路:
a) 获取当前时间的Calendar日历对象。
b) 通过add方法向前偏移一天。
c) 获取偏移一天后的年月日、星期、时分秒等信息,并打印。
3) 练习3
题干:获取指定两天之间的工作日的天数(不考虑法定节日)。
思路:
a) 开启键盘录入,输入起止时间。
b) 将字符串形式的起止时间分割为年月日,并转换成整型数组。
c) 创建起始时间对应的日历对象。
d) 事先定义一个表示天数的变量,从0开始。
e) 开启while循环,循环条件为:起止时间的年月日都不相同。
f) 在while循环内进行判断,如果是星期六或者星期日,天数就不增加,判断完成后,通过add方法向后偏移一天,直到起止时间年月日全部相同。
g) 输出计算出的天数。
下述代码仅供参考。
代码15:
import java.io.*;
import java.util.*;
class CalendarTest
{
public static void main(String[] args)
{
counter();
}
//计算日期的主体方法
public static void counter()
{
//分别定义了起止时间变量和带缓存的字符读取流(键盘录入)
String start = null;
String end = null;
BufferedReader bufr = null;
try
{
bufr= new BufferedReader(new InputStreamReader(System.in));
//由用户输入起止时间
System.out.print("请输入起始时间:");
start= bufr.readLine();
System.out.print("请输入结束时间:");
end= bufr.readLine();
}
catch(IOException e)
{
throw new RuntimeException("键盘录入失败!");
}
//为开始时间创建一个日历对象
Calendarstart Cal = setCalendar(splitTime(start));
//为了简化代码,结束时间只以整型数组形式表示
int[] endCal = splitTime(end);
//开始计算天数
int day = calculate(startCal, endCal);
//将计算得到的天数打印到控制太
System.out.println("从"+start+"到"+end+"共有工作日"+day+"天");
}
//将字符串形式的时间分割为年月日,再转换为整型数组返回
private static int[] splitTime(String time)
{
String[] strTime = time.split("-");
int[] intTime = new int[3];
for(int x=0; x<intTime.length; x++)
{
intTime[x]= Integer.parseInt(strTime[x]);
}
return intTime;
}
//返回开始时间对应的日历对象
public static Calendar setCalendar(int[] time)
{
Calendar c = Calendar.getInstance();
c.set(time[0],time[1]-1, time[2]);
return c;
}
//计算天数的方法
public static int calculate(Calendar start, int[] end)
{
//事先定义好结束时间的年月日
int endYear = end[0];
int endMonth = end[1]-1;
int endDate = end[2];
//事先定义天数,从0开始
int count = 0;
//开始循环,循环条件为起止时间的年月日完全不同
while(start.get(Calendar.YEAR)!= endYear || start.get(Calendar.MONTH) != endMonth ||start.get(Calendar.DAY_OF_MONTH) != endDate)
{
//获取开始时间对应的星期
int startDay = start.get(Calendar.DAY_OF_WEEK);
//只要不是星期六和星期日,天数就自增
if(startDay!= 1 && startDay != 7)
count++;
//完成一次循环前,将开始时间向后偏移一天
start.add(Calendar.DAY_OF_MONTH,1);
}
//返回最终的计算结果
return count;
}
}
假设起始时间为2013年1月9号,结束时间为2013年1月13号,则计算结果为:
从2013-01-09到2013-01-13共有工作日3天。大家也可以自行尝试其他时间段。
7. Random类
在前述Math类random方法的说明中,提到了伪随机数生成器——Random类。该类专门用于生成伪随机数,位于Java标准类库中的java.util包中。对于该类我们重点介绍nextInt方法。
方法说明:
public intnextInt(int n):返回0到指定值n范围内均匀分布的随机int值。
方法演示:
代码14:
import java.util.*;
class RandomDemo
{
public static void main(String[] args)
{
Random rand = new Random();
for(int x=0; x<10; x++)
{
//为取到1到10之间的数,在nextInt返回值上再加1
System.out.println(rand.nextInt(10)+1);
}
}
}
执行结果为:
1
7
7
9
2
1
8
2
7
10
多次运行结果将会有所不同。