Java是一种面向对象语言,Java中的类把方法与数据连接在一起,构成了自包含式的处理单元。为了提升Java程序的开发效率,Java的类包中提供了很多常用类以方便开发人员使用。正所谓,术业有专攻,在常用类中主要包含可以将基本数据类型封装起来的包装类、解决常见数学问题的Math类、生成随机数的Random类,以及处理日期时间的相关信息。
本章的知识架构及重难点如下。表示重点内容,⭐表示难点内容
Java是一种面向对象语言,但在Java中不能定义基本数据类型的对象,为了能将基本数据类型视为对象进行处理,Java提出了包装类的概念,它主要是将基本数据类型封装在包装类中,如int型的包装类Integer、boolean型的包装类Booleandeng,这样便可以把这些基本数据类型转换为对象进行处理Java中的包装类及其对应的基本数据类型如下表所示:
包装类 | 对应基本数据类型 | 包装类 | 对应基本数据类型 |
Byte | byte | Short | short |
Integer | int | Long | long |
Float | float | Double | double |
Character | char | Boolean | Boolean |
说明:Java是可以直接处理基本数据类型的,但在有些情况下需要将其作为对象来处理,这时就需要将其转换为包装类了,这里的包装类相当于基本数据类型与对象类型之间的一个桥梁。由于包装类和基本数据类型间的转换,引入了装箱和拆箱的概念:装箱就是将基本数据类型转换为包装类,而拆箱就是将包装类转换为基本数据类型,这里只需要简单了解这两个概念即可。
java.lang包中的Integer类、Byte类、Short类和Long类,分别将基本数据类型int、byte、short和long封装成一个类,由于这些类都是Number类的子类,区别就是封装不同的数据类型,其包含的方法基本相同,所以本节以Integer类为例讲解整数包装类。
Integer类在对象中包装了一个基本数据类型int的值,该类的对象包含一个int型的字段。此外,该类提供了多个方法,能在int类型和String类型之间互相转换,同时还提供了其他一些处理int类型时非常有用的常量和方法。Integer类的常用方法如下表所示。
方法 | 功能描述 |
valueOf(String str) | 返回保存指定的String值的Integer对象 |
parseInt(String str) | 返回包含在由str指定的字符串中的数字的等价整数值 |
toString() | 返回一个表示该Integer值的String对象(可指定进制基数) |
toBinaryString(int i) | 以二进制无符号整数型式返回一个整数参数的字符串表示形式 |
toHexString(int i) | 以十六进制无符号整数型式返回一个整数参数的字符串表示形式 |
toOctalString(int i) | 以八进制进制无符号整数型式返回一个整数参数的字符串表示形式 |
equals(Object IntegerObj) | 比较此对象与指定的对象是否相等 |
intValue() | 以int型返回此Integer对象 |
shortValue() | 以short型返回此Integer对象 |
byteValue() | 以byte型返回此Integer对象 |
compareTo(Integer anotheger) | 在数字上比较两个Integer对象。如果这两个值相等,则返回0;如果调用对象的数值小于anotherInteger的数值,则返回负值;如果调用对象的数值大于antherInteger的数值,则返回正值 |
下面通过一个实例演示Integer类的常用方法的使用。
例题1:Integer类的常用方法
创建一个IntegerDemo类,其中首先使用Integer类的parseInt()方法将一个字符串转换为int数据;任何创建一个Integer对象,并调用其equals()方法与转换的int数据进行比较;最后演示使用Integer类的toBinaryString()方法、toHexString()方法、toOctalString()方法和toString()方法将int数据转换为二进制、十六进制、八进制和不常使用的十五进制表示形式。
Integer类提供了以下4个常量:
MAX_VALUE:表示int类型可取的最大值,即。
MIN_VALUE:表示int类型可取的最小值,即。
SIZE:用来以二进制补码形式表示int值的位数。
TYPE:表示基本类型int的Class实例。
例题2:查看Integer类的常量值
在项目中创建GetCon类,在主方法中实现将Integer类的常量值输出。
Double类和Float类是对double、float基本类型的封装,它们都是Number类的子类,都是对浮点数进行操作,所以常用方法基本相同。
Double类在对象中包装一个基本数据类型为double的值,每个Double类的对象都包含一个double类型的字段。此外,该类还提供多个方法,可以将double类型转换为String类型,将String类型转换为double类型,也提供了其他一些处理double类型时有用的常量和方法。Double类的常用方法如下表所示。
方法 | 功能描述 |
valueOf(String str) | 返回保存用参数字符串str表示的double值得Double对象 |
parseDouble(String s) | 返回一个新的double值,该值被初始化为用指定String表示的值,这与Double类的valueOf方法一样 |
doubleValue() | 以double形式返回此Double对象 |
isNaN() | 如果此double值是非数字(NaN)值,则返回true;否则返回false |
intValue() | 以int形式返回double值 |
byteValue() | 以byte形式返回Double对象值(通过强制转换) |
longValue() | 以long形式返回此double的值(通过强制转换为long类型) |
compareTo(Double d) | 对两个Double对象进行数值比较。如果两个值相等,则返回0;如果调用对象的数值小于d的数值,则返回负值;如果调用对象的数值大于d的值,则返回正值 |
equals(Object obj) | 将此对象与指定的对象相比较 |
toString() | 返回此Double对象的字符串表示形式 |
toHexString(double d) | 返回double参数的十六进制字符串表示形式 |
下面通过一个实例演示Double类常用方法的使用。
例题:Double类的常用方法
创建一个DoubleDemo类,首先使用Double类的valueOf()方法创建一个Double对象,然后使用Double类的常用方法对该对象进行操作,并查看它们的显示结果。
Double类主要提供了以下常量:
MAX_EXPONENT:返回int值,表示有限double变量可能具有的最大指数。
MIN_EXPONENT:返回int值,表示标准化double变量可能具有的最小指数。
NEGATIVE_INFINITY:返回double值,表示保存double类型的负无穷大值的常量。
POSITIVE_INFINITY:返回double值,表示保存double类型的正无穷大值的常量。
Boolean类将基本类型为boolean的值包装在一个对象中。一个Boolean类型的对象只包含一个类型为boolean的字段。此类还为boolean类型和String类型的相互转换提供了许多方法,并提供了处理boolean类型时非常有用的其他一些常量和方法。Boolean类的常用方法如下表所示。
方法 | 功能描述 |
booleanValue() | 将Boolean对象的值以对应的boolean值返回 |
equals(Object obj) | 判断调用该方法的对象与obj是否相等。当且仅当参数不是null,而且与调用该方法的对象一样都表示同一个boolean值得Boolean对象时,才返回true |
barseBoolean(String s) | 将字符串参数解析为boolean值 |
toString() | 返回表示该boolean值得String对象 |
valueOf(String s) | 返回一个用指定的字符串表示的boolean值 |
例题:Boolean类的常用方法
在项目中创建BooleanDemo类,在主方法中以不同的构造方法创建Boolean对象,并调用booleanValue()方法将创建的对象重新转换为boolean类型数据输出。
Boolean提供了以下3个常量:
TRUE:对应基值true的Boolean对象。
FALSE:对应基值false的Boolean对象。
TYPE:基本类型boolean的Class对象。
Character类在对象中包装一个基本类型为char的值,该类提供了多种方法,以确定字符的类别(小写字母、数字等),并可以很方便地将字符从大写转换为小写,反之亦然。Character类提供了很多方法来完成对字符串地操作,常用的方法如下表所示。
方法 | 功能描述 |
valueOf(char a) | 返回保存指定char值的Character对象 |
compareTo(Character anotherCharacter) | 根据数字比较两个Character对象,若这两个对象相等则返回0 |
equals(Object obj) | 将调用该方法的对象与指定的对象相比较 |
toUpperCase(char ch) | 将字符参数转换为大写 |
toLowerCase(char ch) |
将字符参数转换为小写 |
toString() |
返回一个表示指定char值的String对象 |
charValue() | 返回此Character对象的值 |
isUpperCase(char ch) | 判断指定字符是否为大写字符 |
isLowerCase(char ch) | 判断指定字符是否为小写字符 |
isLetter(char ch) | 判断指定字符是否为字母 |
isDigit(char ch) | 判断指定字符是否为数字 |
下面通过实例演示Character类的大小写转换方法的使用,其他方法的使用与其类似。
例题:Character类的常用方法
在项目中创建UpperOrLower类,在主方法中创建Character类的对象,通过判断字符的大小写状态确认将其转换为大写还是小写。
Character类提供了大量表示特定字符的常量,例如:
CONNECTOR_PUNCTUATION:返回byte型值,表示Unicode规范中的常规类别“Pc”。
UNASSIGNED:返回byte型值,表示Unicode规范中的常规类别“Cn”。
TITLECASE_LETTER:返回byte型值,表示Unicode规范中的常规类别“Lt”。
说明:Character类提供的常量有很多,详细列表可查看JavaAPI文档。
前面介绍了Java中的包装类,对于数值型的包装类,它们有一个共同的父类——Number类,该类是一个抽象类,它是Byte、Integer、Short、Long、Float和Double类的父类,其子类必须提供将表示的数值转换为byte、int、short、long、float和double的方法。例如,doubleValue()方法返回双精度浮点值,floatValue()方法返回大单精度浮点值,这些方法如下表所示。
方法 | 功能描述 |
bytevalue() | 以byte形式返回指定的数值 |
intValue() | 以int形式返回指定的数值 |
floatValue() | 以float形式返回指定的数值 |
shortValue() | 以short形式返回指定的数值 |
longValue() | 以long形式返回指定的数值 |
doubleValue() | 以double形式返回指定的数值 |
Number类的方法分别被其各子类所实现,也就是说,在Number类的所有子类中都包含以上这几种方法。
在Java语言中,提供了一个执行数学基本运算的Math类,该类包括常用的数学运算方法,如三角函数方法、指数函数方法、对数函数方法、平方根函数方法等一些常用数学函数方法。除此之外还提供了一些常用的数学常量,如PI、E等。本章将讲解Math类以及其中的一些常用方法。
在实际开发中,随机数的使用是很普遍的,所以要掌握生成随机数的操作。在Java中主要提供了两种生成随机数的方式,分别为调用Math类的random()方法生成随机数和调用Random类生成各种数据类型的随机数。
在Java中,还提供了大数字的操作类,即java.math.BigInteger类与java.math.BigDecimal类。这两个类用于高精度计算,其中BigInteger类是针对大整数的处理类,而BigDecimal类则是针对大小数的处理类。
数字格式化在解决实际问题时应用非常普遍,如表示某超市的商品价格,需要保留两位有效数字。数字格式化操作主要针对的是浮点型数据,包括double型和float型数据。在Java中使用java.text.DecimalFormat格式化数字,本节将着重讲解DecimalFormat类。
在Java中,没有格式化的数据遵循以下原则:
如果数据绝对值大于0.001并且小于10000000,使以常规小数形式表示。
如果数据绝对值小于0.001或者大于10000000,使用科学记数法表示。
由于上述输出格式不能满足解决实际问题的要求,通常将结果格式化为指定形式后输出。在Java中,可以使用DecimalFotmat类进行格式化操作。
DecimalFormat类是NumberFormat的一个子类,用于格式化十进制数字。它可以将一些数字格式化为整数、浮点数、百分数等。通过使用该类可以为要输出的数字加上单位或控制数字的精度。一般情况下,可在实例化DecimalFormat对象时传递数字格式化,也可以通过DecimalFormat类中的applyPattern()方法来实现数字格式化。
当格式化数字时,可在DecimalFormat类中使用一些特殊字符构成一个格式化模板,使数字按照一定的特殊字符规则进行匹配。下表列举了格式化模板中的特殊字符及其所代表的含义。
字符 | 说明 |
0 | 代表阿拉伯数字,使用特殊字符“0”表示数字的一位阿拉伯数字,如果该为不存在数字,则显示0 |
# | 代表阿拉伯数字,使用特殊字符“#”表示数字的一位阿拉伯数字,如果该为存在数字,则显示字符;不存在则不显示 |
. | 小数分隔符或货币小数分隔符 |
- | 负号 |
, | 分组分隔符 |
E | 分割科学计数法中的尾数和指数 |
% | 放置在数字的前缀或后缀,将数字乘以100显示为百分数 |
\u | 放置在数字的前缀或后缀,将数字乘以1000显示为千分数 |
\u | 放置在数字的前缀或后缀,作为货币记号 |
' | 单引号,当上述特殊字符出现在数字中时,应为特殊符合添加单引号,系统会将此符合视为普通符合处理 |
例题:DecimalFormat类的常用方法
在项目中创建DecimalFormatSimpleDemo类,在类中分别定义SimgleFormat()方法和UseApplyPatternMethodFormat()方法实现两种格式化数字的方式。
在本实例中可以看出,代码的第一行使用import关键字将java.text.DecimalFormat这个类导入,这是告知系统下面的代码将使用到DecimalFormat类。然后定义了两个格式化数字的方法,这两个方法的参数都为两个,分别代表数字格式化模板和具体需要格式化的数字。虽然这两个方法都可以实现数字的格式化,但采用的方式有所不同,SimgleFormat()方法是在实例化DecimalFormat对象时设置数字格式化模板,而UseApplyPatternMethodFormat()方法是在实例化DecimalFormatd对象对象后调用applyPattern()方法设置数字格式化模板。最后,在主方法中根据不同形式模板格式化数字。在结果中可以看到以“0”特殊字符构成的模板进行格式化时,当数字某位不存在时,将显示0;而以“#”特殊字符构成的模板进行格式化操作时,格式化后的数字位数与数字本身的位数一致。
在DecimalFormat类中,除了可通过格式化模板来格式化数字,还可以使用一些特殊方法对数字进行格式化设置。例如:
DecimalFormat myFormat = new DecimalFormat();//实例化DecimalFormat类对象
myFormat.setGroupingSize(2);//设置将数字分组的大小
myFormat.setGroupingUsed(false);//设置是否支持分组
在上述代码中,setGroupingSize()方法设置格式化数字的分组大小,setGroupingUsed()方法设置是否可以对数字进行分组操作。为了使读者更好地理解这两个方法的使用,来看下面地实例。
在项目中创建DecimalMethod类,在类地主方法中调用setGroupingSize()与setGroupingUsed()方法实现数字地分组。
import java.text.DecimalFormat;
public class DecimalMethod{
public static void main(String[] args){
DecimalFormat myFormat = new DecimalFormat();
myFormat.setGroupingSize(2); //设置将数字分组为2
String output = myFormat.format(123456.789);
System.out.println("将数字以每两个数字分组"+output);
myFormat.setGroupingUsed(false); //设置不允许数字进行分组
String output2 = myFormat.format(123456.789);
System.out.println("不允许数字分组"+output2);
运行结果:
将数字以每两个数字分组 12,34,56.789
不允许数字分组 123456.789
Math类提供了众多数学函数方法,主要包括三角函数方法,指数函数方法,取整函数方法,取最大值、最小值,以及平均值函数方法。这些方法都被定义为static形式,所以在程序中应用比较简便。可以使用如下形式调用:
Math.数学方法
在Math类中,除函数方法外还存在一些常用数学常量,如PI、E等。这些数学常量作为Math类地成员变量出现,调用起来也很简单。可以使用如下形式调用:
Math.PI
Math.E
Math类中地常用数学运算方法较多,大致可以将其分为四大类别,分别为三角函数方法,指数函数方法,取整函数方法,以及取最大值、最小值、绝对值函数方法。
(1)三角函数方法
Math类中包含的三角函数方法如下:
public static double sin(double a):返回的三角正弦。
public static double cos(double a):返回角的三角余弦
public static double tan(double a):返回的三角正切。
public static double asin(double a):返回一个值的反正弦。
public static double acos(double a):返回的三角反余弦。
public static double atan(double a):返回的三角反正切。
public static double toRadians(double a):将角度转换为弧度。
public static double toDegrees(double a):将弧度转换为角度。
以上每个方法的参数和返回值都是double型的。将这些方法的参数的值设置为double型是有一定道理的,参数以弧度代替角度来实现,其中1°等于Π/180弧度,所以180°可以使用Π弧度来表示。除了可以获取角的正弦、余弦、正切、反正弦、反余弦、反正切,Math类还提供了角度和弧度相互转换的方法toRadians()和toDegreess()。但需要注意的是,角度与弧度的转换通常是不精确的。
例题:在Java代码中进行三角函数运算
在项目中创建TrigonmetricFunction类,在本类的主方法中调用Math类提供的各种三角函数运算方式,并输出结果。
通过运行结果可以看出,90°的正弦值为1,0°的余弦值为1,60°的正切与Math.sqrt(3)的值应该是一致的,也就是取3的平方根。在结果中可以看到,第4~6行的值是基本相同的,这个值换算后正是45°,也就是获取的Math.sqrt(2)/2反正弦、反余弦值与1的反正切值都是45°。最后两行打印语句实现的是角度和弧度的转换,其中Math.toRadians(120.0)语是获取120°的弧度值,而Math.toDegress(Math.PI/2)语句是获取Π/2的角度值。读者可以将这些具体的值使用Π的形式表示出来与状结果应该是基本一致的,这些结果不能做到十分精确,因为Π本身也是一个近似值。
(2)指数函数方法
Math类中与指数相关的函数方法如下。
public static double exp(double num):用于获取e的a次方。
public static double log(double num):用于取自然对数,即取lna的值。
public static double log10(double num):用于取底数为10的a的对数。
public static double sqrt(double num):用于取num的平方根,其中a的值不能为负值。
public static double cbrt(double num):用于取a的立方根。
public static double pow(double num1,double num2):用于取a的b次方。
指数运算包括求方根、取对数以及求n次方的运算。
例题:在Java代码中进行指数函数运算
在项目中创建ExponetFunction类,在类的主方法中调用Math类中的方法实现指数函数的运算,并输出运算结果。
在本实例中可以看到,使用Math类中的方法比较简单,直接使用Math类名调用相应的方法即可。
(3)取整函数方法
在具体的问题中,取整操作使用也很普遍,所以Java在Math类中添加了数字取整方法。Math类中主要包括以下几种取整方法:
public static double ceil(double num):返回大于等于参数的最小整数(向上取整)。
public static double floor(double num):返回小于等于参数的最大整数(向下取整)。
public static double rint(double num):返回与参数最接近的整数,如果存在两个相同接近的整数,则结果取偶数。
public static int round(float num):将参数加上0.5后返回与参数最近的整数。
public static long round(double num):将参数加上0.5后返回与参数最近的整数,然后强制转换为长整型。
例题:各创建下取整函数的运算结果
在项目中创建IntFunction类,在类的主方法中调用Math类中的方法实现取整函数的运算,并输出运算结果。
(4)取最大值、最小值、绝对值函数方法
在程序中最常用的方法就是最大值、最小值、绝对值等,Math类中包括的操作方法如下:
public static double max(double a,double b):取a,b中的最大值。
public static int min(int a,int b):取a,b中的最小值,参数为整形。
public static long min(long a,long b):取a,b中的最小值,参数为长整型。
public static float min(float a,float b):取a,b中的最小值,参数为单精度浮点型。
public static double min(double a,double b):取a,b中的最小值,参数为双精度浮点型。
public static int abs(int a):返回整形参数的绝对值。
public static long abs(long a):返回长整型参数的绝对值。
public static float abs(float a):返回单精度浮点型参数的绝对值。
public static double abs(double a):返回双精度浮点型参数的绝对值。
在项目中创建AnyFunction类,在类的主方法中调用Math类中的方法实现求两数的最大值、最小值和取绝对值的运算,并输出运算结果。
Random类是JDK中随机数生成器,可以通过实例化一个Random对象创建一个随机数生成器,语法如下:
Random r = Random();
以这种方式实例化对象时,Java编译器将以系统当前时间作为随机生成器的种子。因为每时每刻的时间不可能相同,所以产生的随机数不同。但是如果运行速度太快,也会产生两个运行结果相同的随机数。
用户也可以在实例化Random类对象时,设置随机生成器的种子。语法如下:
Random r = new Random(seedValue);
r:Random类对象。
seedValue:随机数生成器的种子。
在Random类中,提供了获取各种数据类型随机数的方法,下面例举几个常用的方法:
public int nextInt():返回一个随机整数。
public int nextInt(int n):返回大于等于0且小于n的随机整数。
public int nextLong():返回一个随机长整数。
public boolean nextBoolean():返回一个随机布尔型值。
public float nextFloat():返回一个随机单精度浮点型值。
public double nextDouble():返回一个随机双精度浮点型值
public double nextGaussian():返回一个概率密度为高斯分布的双精度浮点型值。
例题:获取不同取值范围、不同类型的随机数
在项目中创建RandomDemo类、在类的主方法中创建Random类的对象,使用该对象生成各种类型的随机数,并输出结果。
注意:
random()方法返回的值实际上是伪随机数,它通过复杂的运算而得到一系列的数。该方法是通过当前时间作为随机数生成器的参数,所以每次执行程序都会产生不同的随机数。
BigInteger类的数字范围较Integer类的数字范围要大得多。前文介绍过Integer类是int的包装类,int的最大值为2³¹-1,如果要计算更大的数字,使用Integer类就无法实现了,所以Java中提供了BigInteger类来处理更大的数字。BigInteger类支持任意精度的整数,也即是说,在运算中BigInteger类可以准确地表示任何大小的整数值而不会丢失信息。
在BigInteger类中封装了多种操作,除了基本的加、减、乘、除操作,还提供了绝对值、相反数、最大公约数以及判断是否为质数等操作。
使用BigInteger类,可以实例化一个BigInteger对象,并自动调用相应的构造函数。BigInteger类具有很多构造函数,但最直接的一种方式是参数以字符串形式代表要处理的数字。
例如,将2转换为BigIntege类型,可以使用以下语句进行初始化操作:
BigInteger twoInstance = new BigInteger("2");
注意:参数2的双引号不能省略,因为参数是以字符串的形式存在的。
一旦创建了对象实例,就可以调用BigInteger类中的一些方法进行运算操作,包括基本的数学运算和位运算以及一些取相反数、取绝对值等操作。下面列举了BigInteger类中常用的几种运算方法:
public BigInterger add(BigInteger val):做加法运算。
public BigInteger subtract(BigInteger val):做减法运算。
public BigInteger muItiply(BigInteger val):做乘法运算。
public BigInteger divide(BigInteger val):做除法运算。
public BigInteger renmainder(BigInteger val):做取余操作。
public BigInteger[] divideAndRemainder(BigInteger va):用数组返回余数和商,结果数组中第一个值位商,第二个值位余数。
public BigInteger pow(int exponet):进行取参数的exponent次方操作。
public BigInteger negate():取相反数。
public BigInteger shiftLeft(int n):将数字左移n位,如果n为负数,做右移操作。
public BigInteger shiftRight(int n):将数字右移n位,如果n位负数,做左移操作。
public BigInteger and(Bigteger val):做与操作。
public BigInteger or(Bigteger val):做或操作。
public int compareTo(Bigteger val):做数字比较操作
public boolean equals(Object x):当参数x是Bigteger类型的数字并且数值与对象实例的数值相等时,返回true。
public BigInteger min(Bigteger val):返回较小的数值。
public BigInteger max(Bigteger val):返回较大的数值。
例题:使用BigInteger类进行数学运算
在项目中创建BigIntegerDemo类,在类的主方法中创建两个BigInteger类对象,对两个对象进行加、减、乘、除和其他运算,并输出结果。
BigDecimal类和BigInteger类都能实现大数字的运算,不同的是BigDecimal类加入了小数的概念。一般的float型和double型数据只可以用来做科学计算或工程计算,但由于在商业计算中要求数字精度比较高,所以要用到BigDecimal类。BigDecimal类支持任何精度的定点数,可以用它来精确计算货币值。在BigDecimal类中,常用的两个构造方法如下表所示。
构造方法 | 功能说明 |
BigDecimal(double val) | 实例化时将双精度浮点型转换为BigDecimal类型 |
BigDecimal(String val) | 实例化时将字符串形式转换为BigDecimal类型 |
BigDecimal类型的数字可以用来做超大的浮点数的运算,如加、减、乘、除等,但是在所有的运算符中除法是最复杂的,因为在除不尽的情况下商小数点后的末位的处理是需要考虑的。BigDecimal类实现的加、减、乘、除的方法如下表所示。
方法 | 功能说明 |
add(BigDecimal augend) | 做加法操作 |
subtract(BigDecimal subtrahend) | 做减法操作 |
multiply(BigDecimal multiplicand) | 做乘法操作 |
divide(BigDecimal divisor,int scale,RoundingMode roundingMode) | 做除法操作,方法中3个参数分别代表除数、商的小数点后的位数、近似处理模式 |
在上述方法中,BigDecimal类中divide()方法有多种设置,用于返回商小数点后的末位的处理,这些模式的名称与含义如下表所示。
模式 | 含义 |
RoundingMode.up | 商的最后一位如果大于0,则向前进位,正负数都如此 |
RoundingMode.DOWN | 商的最后一位无论是什么数字都省略 |
RoundingMode.CEILING | 商如果是正数,按照UP模式处理;如果是负数,按照DOWN模式处理。这种模式的处理都会使近似值大于等于实际值 |
RoundingMode.FLOOR | 与CEILING模式相反,商如果是正数,按照DOWN模式处理;商如果是负数,则按照UP模式处理。这种模式的处理都会使近似值小于等于实际值 |
RoundingMode.HALF_DOWN | 对商进行四舍五入操作,如果商的最后一位小于等于5,则做舍弃操作;如果最后一位大于5,则做进位操作,如7.5≈7 |
RoundingMode.HALF_UP | 对商进行四舍五入操作,如果商的最后一位小于等于5,则做舍弃操作;如果大于等于5,则做进位操作,如7.5≈8 |
RoundingMode.HALF_EVEN | 如果商的倒数第二位为奇数,则按照HALF_UP模式处理;如果为偶数,则按照HALF_DOWN模式处理,如7.5≈8,8.5≈8 |
下面设计一个类,这个类包括任意两个BigDecimal类型数字的加、减、乘、除运算方法。
例题:使用BigDeciaml类进行数学运算
在项目中创建BigDecimalDemo类,在类的主方法中创建两个BigDecimal类对象,对两个对象进行加、减、乘、除运算,并输出运算结果。
System类是JDK中提供的系统类,该类是用final修饰的,所以不允许被继承。System类提供了很多系统层面的操作,并且这些方法全部都是静态的。System类提供的较常用方法如下表所示。本节重点讲解利用System类控制台输出和计时这两个操作。
方法 | 功能描述 |
currentTimeMillis() | 返回以毫秒为单位的当前时间 |
exit(int status) | 通过启动虚拟机的关闭序列,终止当前正在运行的Java虚拟机。此方法从不正常返回。可以将变量作为一个状态码。根据惯例,非零的状态码表示非正常终止;0表示正常终止 |
Map |
返回一个不能修改的当前系统环境的字符串映射视图 |
getenv(String name) | 获取指定的环境变量值 |
getProperties() | 确定当前的系统属性 |
getProperty(String key) | 获取用指定键描述的系统属性 |
setIn(InputStream in) | 重新分配“标准”输入流 |
System类提供了标准输入、标准输出和错误输出流,也就是说,System类提供了3个静态对象:in、out和err。本书中的代码多次使用了这些对象,最常见的就是out对象。在控制台输出字符串,输出的方法有两种,下面分别进行讲解。
(1)不会自动换行的print()方法
print()方法的语法如下:
System.out.print("Hello!");
此方法输出“Hello”文字,输出完毕后,光标会停留在“Hello”文字末尾,不会自动换行。
(2)可以自动换行的println()方法
println()方法在print后面加上了“ln”后缀(就是line的简写),语法如下:
System.out.println("书籍是人类进步的阶梯!");
此方法输出“书籍是人类进步的阶梯!”后会自动换行。光标停留在下一行的开头。
print()方法与println()方法输出的对比效果如下表所示。
Java语法 | 运行结果 | Java语法 | 运行结果 |
System.out.println("左"); System.out.println("中"); System.out.println("右"); |
左中右 | System.out.println("上"); System.out.println("中"); System.out.println("下"); |
上 中 下 |
综上所述,Java输出换行的方法有以下两种:
System.out.print("\n");//利用换行符\n实现换行
System.out.println();//空参数即可实现换行
误区警示:
使用这两个输出方法时还要注意以下两点:
(1)“System.out.println("\n");”会打印两个空行。
(2)“System.out.print();”无参数会报错。
System.currentTimeMillis()方法可以获取自1970年1月1日零点至今的毫秒数。虽然Date日期类也有类似的方法,但代码会比System类多,所以System.currentTimeMillis()方法是为获取当前毫秒数最常用的方法。因为该方法的返回值精确到毫秒,所以可以利用该方法来记录程序的运行时间。
例题:查看执行一万次字符串拼接所消耗的时间
创建字符串对象,循环一万次对该字符串做拼接操作,利用System.currentTimeMillis()方法记录循环消耗的时间,具体代码如下:
因为性能强的处理器计算时间短,性能差的处理器计算时间长,所以该实例在不同电脑上的结果是会发生变化的,笔者写稿时的运行结果如上图。
与c语言不同,Java从控制台中读出用户输入的值,用到的不是一行可以直接使用的代码,而是由一个叫Scanner的类来实现的。Scanner英文直译就是扫描仪,它的用途就和现实生活的扫描仪一样,可以把数字化信息转为人类可识别的文字。控制台输出内容用到了System.out就表示向控制台输出,System.in就表示从控制台输入,让Scanner扫描System.in就可以获取用户输入的值了。
使用Scanner类首先要引入该类,其语法如下:
import java.util.Scanner; //引入Scanner类
Scanner类提供了如下表所示的几种常用的方法,通过这些方法可以获取控制台中输入的不同类型的值。
方法名 | 返回类型 | 功能说明 | 方法名 | 返回类型 | 功能说明 |
next() | String | 查看并返回此扫描器获取的下一个完整标记 | nextInt() | int | 扫描一个值返回int类型 |
nextBoolean() | boolean | 扫描一个布尔值标记并返回 | nextLine() | String | 扫描一个值返回String类型 |
nextByte() | byte | 扫描一个值返回byte类型 | nextLong | long | 扫描一个值返回long类型 |
nextDouble() | double | 扫描一个值返回double类型 | nextShort | short | 扫描一个值返回short类型 |
nextFloat() | float | 扫描一个值返回float类型 | close() | void | 关闭此扫描器 |
误区警示:
nextLine()方法扫描的内容是从第一个字符开始到换行符为止,而next()、nextInt()等方法扫描的内容是从第一个字符开始到这段完整内容结束。
使用Scanner类扫描控制台的代码如下:
Scanner sc = new Scanner(System.in);
System.in表示控制台输入流,在创建Scanner对象时把System.in作为参数,这样创建出的扫描器对象扫描的目标就是用户在控制台中输入的内容,再通过表中列出的方法将用户输入的内容转为Java的数据类型,就可以对数据进行加工了、显示了。
例题:猜数字游戏
创建ScannerDemo类,首先在主方法中创建一个随机数,然后再创建一个while循环不断获取用户输入的数字,让用户输入的数字与随机数比较,给出“大于”或“小于”的提示,直到用户输入的数字与随机数相等才结束循环。
Date类用于表示日期时间,使用该类表示时间需要使用其构造方法创建对象,其构造方法及其说明如下表所示。
构造方法 | 说明 |
Date() | 分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒) |
Date(long date) | 分配Date对象并初始化此对象,以表示自标准基准时间起经指定毫秒数date后的时间 |
例如,使用Date类的第二种构造方法创建一个Date类的对象,代码如下:
long timeMillis = System.currentTimeMillis();//当前系统时间所经历的毫秒数
Date date = new Date(timeMillis);
上述代码中的System类的currentTimeMillis()方法主要用来获取当前系统时间距标准基准时间的毫秒数。另外,这里需要注意的是,创建Date对象时使用的是long型整数,而不是double型,这主要是因为double类型可能会损失精度。Date类的常用方法及其说明如下表所示。
方法 | 说明 |
after(Date when) | 测试当前日期是否在指定的日期之后 |
before(Date when) | 测试当前日期是否在指定的日期之前 |
getTime() | 获取自1970年1月1日00:00:GMT开始到现在所经过的毫秒数 |
setTime(long time) | 设置当前Date对象所表示的日期时间值,该值用以表示1970年1月1日00:00:00GMT以后time毫秒的时间点 |
例题:获取当前的日期和时间
创建Date对象获取当前日期和时间并输出。
运行此代码后,将在控制台输出日期及自1970年1月1日00:00:00GMT开始至本程序运行时所经历过的毫秒数,结果如上图。
误区警示:
在本节介绍的Date类在java.util包下,但java.sql包下也有一个Date类,不要将两者搞混。
因为代码执行的时间不同,所以每次“获取的当前时间”得到的结果都会不一样。
如果在程序中直接输出Date对象,显示的是“MonFeb 29 17:39:50 CST 2016”这种格式的日期时间,那么应该如何将其显示为“2016-02-29”或者“17:39:50”这样的日期时间格式呢?Java中提供了DateFormat类来实现类似的功能。
DateFormat类是日期时间格式化子类的抽象类,可以按照指定的格式对日期或时间进行格式化。DateFormat类提供了很多方法,以获得基于默认或给定语言环境和多种格式化风格的默认日期时间Formatter,格式化风格主要包括SHORT、MEDIUM、LONG和FULL4种:
SHORT:完全为数字,如12.13.52或3:30pm。
MEDIUM:较长,如jan12,1952。
LONG:更长,如January12,1952或3:30:32pm。
FULL:完全指定,如Tuesday、April12、1952AD或3:30:42pm PST。
另外,使用DateFormat类还可以自定义日期时间的格式。要格式化一个当前语言环境下的日期,首先需要创建DateFormat类的一个对象,由于它是抽象类,因此可以使用其静态方法getDateInstance()进行创建,语法如下:
DateFormat df = DateFormat.getDateInstance();
使用getDateInstance()方法获取的是所在国家或地区的标准日期格式。另外,DateFormat类还提供了一些其他静态方法。例如,使用getTimeInstance()方法可获取所在国家或地区的时间格式,使用getDateTimeInstance()方法可获取日期和时间格式。DateFormat()类的常用方法及其说明如下表所示。
方法 | 说明 |
format(Date date) | 将一个Date对象实例格式化为日期/时间字符串 |
getCalendar() | 获取与此日期/时间格式器关联的日历 |
getDateInstance() | 获取日期默认格式 |
getDateTimeInstance() | 获取日期/时间默认格式 |
getInstance() | 获取为日期和时间使用SHORT风格的默认日期/时间格式器 |
getTimeInstance() | 获取默认时间格式 |
parse(String source) | 将字符串解析成一个日期,并返回这个日期的Date对象 |
例如,将当前日期按照DateFormat类默认格式输出:
DateFormat df = DateFormat.getInstance();
System.out.println(df.format(new Date()));
结果如下:
2023/5/19 下午 15:32
输出长类型格式的当前时间:
DateFormat df = DateFormat.getTimeInstance(DateFormat.LONG);
System.out.println(df.format(new Date()));
结果如下:
CST 下午 15:41:00
输出长类型格式的当前日期:
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
System.out.println(df.format(new Date()));
结果如下:
2023 年 5 月 19 日
输出长类型格式的当前时间和当前日期:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
System.out.println(df.format(new Date()));
结果如下:
2023 年 5 月 19 日 CST 上午 10:01:12
由于DateFormat类是一个抽象类,不能用new创建实例对象。因此,除了使用getXXXInstance()方法创建其对象,还可以使用子类,如SimpleDateFormat类,该类是一个以语言环境相关的方式来格式化和分析日期的具体类,它允许进行格式化(日期→文本)、分析(文本→日期)和规范化。
SimpleDateFormat类提供了19个格式化字符,可以让开发者随意编写日期格式,这19个格式化字符表如下所示。
字母 | 日期或时间元素 | 类型 | 示例 |
G | Era标志符 | Text | AD |
y | 年 | Year | 1999;96 |
M | 年中的月份 | Month | July;Jul;07 |
w | 年中的周数 | Number | 27 |
W | 月份中的周数 | Number | 2 |
D | 年中的天数 | Number | 189 |
d | 月份中的天数 | Number | 10 |
F | 月份中的星期 | Number | 2 |
E | 星期中的天数 | Text | Tuesday;Tue |
a | Am/pm标记 | Text | PM |
H | 一天中的小时数(0~23) | Number | 0 |
h | am/pm中的小时数(1~12) | Number | 12 |
k | 一天中的小时数(1~24) | Number | 24 |
K | am/pm中的小时数(0~11) | Number | 0 |
m | 小时中的分钟数 | Number | 30 |
s | 分钟中的秒数 | Number | 55 |
S | 毫秒数 | Number | 978 |
z | 时区 | General time zone | PST;GMT-08:00 |
Z | 时区 | RFC 822 time zone | -800 |
通常表中的字符出现的数量会影响数字的格式。例如,yyyy表示4位年份,这样输入会显示2023;yy表示两位,这样输入会显示23;只有一个y的话,会按照yyyy显示;如果超过4个y,如yyyyy,会在4位年份左侧补0,结果为02023。一些常用的日期时间格式如下表示所示。
日期时间 | 对应的格式 |
2021/10/25 | yyyy/MM/dd |
2021.10.25 | yyyy.MM.dd |
2021-09-15 13:30:25 | yyyy-MM-dd HH:mm:ss |
2021年10月24日 10时25分07秒 星期日 | yyyy年MM月dd日 HH时mm分ss秒 EEEE |
下午3时 | ah时 |
今年已经过去了297天 | 今年已经过去了D天 |
例题:以中文形式打印当前的日期和时间
创建DateForamatDemo类,在主方法中创建日期格式化对象,格式设定为“某年某月某日星期几某时某分某秒”,以新闻开头的方法播报当前时间。
DateForamt类提供的Date parse(String source)方法可以将字符串转为其字面日期对应的Date对象,整个过程相当于日期格式化的逆操作。
例如,将“2023-05-19”这个字符串转成Date对象,可以使用如下代码:
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("2023-05-19");
注意:如果日期字符串不符合格式,则会抛出java.text.ParseException异常。
打开JavaAPI文档可以看到java.util.Date类提供的大部分方法都已经过时了,因为Date类在设计之初没有考虑到国际化,而且很多方法也不能满足用户需求,比如需要获取指定时间的年月日时分秒信息,或者想要对日期时间进行加减运算等复杂的操作,Date类已经不能胜任,因此JDK提供了新的时间处理类一Calendar日历类。
Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期)提供了一些方法。另外,该类还为实现包范围外的具体日历系统提供了其他字段和方法,这些字段和方法被定义为 protected。
Calendar 提供了一个类方法 getInstance(),以获得此类型的一个通用的对象。Calendar 类的getlinstance0方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化,其使用方法如下:
Calendar rightNow = Calendar.gerInstance();
说明
由于Calendar 类是一个抽象类,不能用new创建实例对象,因此除了使用getinstance()方法创建其对象,如果需要创建其对象,必须使用其子类,如 GregorianCalendar类。
Calendar类提供的常用字段及其说明如下图所示。
从上图可以看到,add()方法和roll()方法都用来为给定的日历字段添加或减去指定的时间量,它们的主要区别在于:使用add()方法时会影响大的字段,像数学里加法的进位或错位,而使用roll()方法设置的日期字段只是进行增加或减少,不会改变更大的字段。
例题:今天离中华人民共和国成立100周年差多少天
创建CountDown类,通过Calendar类和Date类计算出2049年10月1日距今相差的毫秒数,根据毫秒数计算出相差的天数。
最后对Calendar类的使用做出几点总结:
c.set(Calendar.DAY_OF_MONTH,0)获取的是上个月的最后一天,所以调用前需要将月份往后加一个月。
Calendar.MONTH的第一个月是使用0记录的,所以在获得月份数字后要加1。年和日是从1开始记录的,不需要加1。
Calendar.DAY_OF_WEEK的第一天是周日,周一是第二天,周六是最后一天。
Runtime类是JDK提供的运行时类,该类为Java程序提供了与当前运行环境相连接的一个通道,Java程序可以利用该类对当前的运行环境执行一些简单的操作。Runtime类不能使用new关键字创建实例,只能通过Runtime.getRuntime()方法获取实例。
Runtime类的常用方法如下表所示,本节将重点讲解利用Runtime类执行本地命令和查看Java虚拟机所占内存这两个操作。
方法 | 功能描述 |
getRuntime() | 返回与当前Java应用程序相关的运行时对象 |
exec(String command) | 在单独的进程中执行指定的字符串命令 |
exec(String[] cmdarray) | 在单独的进程中执行指定命令和指定参数 |
totalMemory() | 返回Java虚拟机中的内存总量 |
freeMemory() | 返回Java虚拟机中的空闲内存量 |
load(String filename) | 加载作为动态库的指定文件名 |
loadLibrary(String libname) | 加载具有指定库名的动态库 |
本地命令指的是操作系统的命令。例如,在Linux系统下就表示shell命令,在Windows系统下就表示cmd命令。
Runtime类提供exec()方法让Java代码可以执行系统的命令,exec()方法有很多重载的形式,例如:
Process exec(String command)
Process exec(String[] cmdarray)
command:要执行的系统命令,字符串类型。
cmdarray:要执行的命令和相应的命令参数,字符串数组类型。
其实这两个重载方式很类似,如执行“javac hello.java”这行命令,使用第一种重载方式的代码如下:
Runtime.getRuntime().exec("javac hello.java");
使用第二种重载方式的代码如下:
String command[] = {"javac","hello.java"};
Runtime.getRuntime().exec(command);
exec()方法会返回一个Process对象。Process类是Java中进程类,该类是抽象类,不能使用new关键字创建实例。Process类的常用方法如下表所示,开发可以使用getInputStream()方法获取进程返回的信息。
方法 | 功能描述 | 方法 | 功能描述 |
destroy() | 结束进程 | getInputStream() | 获取进程的输入流 |
getErrorStream() | 获取进程的错误流 | getOutputStream() | 获取进程的输出流 |
例题:让Java程序执行Windows系统的help命令
创建Runtime对象,执行help命令,利用Process进程对象获取进程信息输入流,将信息打印在控制台中,具体代码如下:
运行结果如下图所示。笔者使用的操作系统是中文版的Windows系统,所以会打印出cmd中的“help”执行结果。
Runtime类可以通过freeMemory()方法查看当前Java虚拟机可用内存的剩余量。如果程序能够实时监控内存余量,就可以尽量控制程序对内存的占用,从而避免出现“内存溢出”的情况。同样,也可以用来对测试程序性能,检验程序算法是否导致内存紧张。
例题:监控虚拟机内存使用情况
创建一个长度为10000的整形数组,利用循环为数组的每一个元素赋值,利用freeMemory()方法记录循环前后的内存剩余量,并计算出循环操作占用的内存总字节数。
注意:freeMemory()方法得到的剩余内存量是近似值。