包装类
在前一章的字符串章节中,可以把字符串当作对象来进行处理,衍生出了许多灵活的操作,更让我们能使用非常多的方法对字符串的操作,让变得异常灵活。
但是在Java中,基础类型并不是类,并不能定义基础类型的变量,使得对基础类型的操作也能很方便。这个时候包装类就出现了,它主要的作用就是将基本类型封装在包装类中,这样就是方便的把这些基本数据类型转换成对象进行处理了。
包装类与基本类型关系图
需要注意的是,在JDK5之后引入包装类自动装箱与拆箱的新特性,在JDK5之前,包装类与基本类型之前需要进行手动装箱与拆箱。下面以Integer包装类为例
手动装箱与拆箱
Integer iNum=Integer.valueOf(10); // 装箱
int num=i.intValue(); // 拆箱
自动装箱与拆箱
Integer number=10; // 装箱
int curNum=number; // 拆箱
1、Integer类
在Java中整数类型被分为byte、short、int、long,它们也有对应的包装类,所有包装类,除int类型与char类型之外,其它的包装类都是以首字母大写来做区别,而int类型的包装类则是Integer,char类型的包装类是Character。
Integer源码:Integer类中包装了一个int类型的变量
但是这个时候,我们可以看到,这个int类型的变量是被final静态关键字所修饰了的,但是根据我们之前所学,被静态关键字所修饰的变量不应该在定义时就给定初值吗?那么像Integer类中的这样不符合语法规定吧?那么接下来我就来介绍final关键字的另一个特性。
final修饰成员变量
final关键字在修饰局部变量时,必须给定该变量一个值,这就是常见的final的用法,定义常量。
但是final关键字再修饰成员变量时,却变得也可以“通融”一下,在Java中,final关键字所修饰的成员变量,在该类的所有构造方法中必须给该被final修饰的成员变量赋值
,请注意,是所有的构造方法,如果没有构造方法,必须编写一个构造方法,在该构造方法中给该变量赋值。
例如:
此时定义了一个f类,在该类中定义了一个被final修饰的int类型的变量val,此时没有给定初值,此时也没有构造方法,所以编译器直接报了一个错误。
接下来我们编写一个构造方法,并给该变量赋值,看看会有什么变化。
这个时候错误就消失了,那么如果我们将下面注释掉的构造方法再取消注释呢?
报错,又出现了,因为在Java中,被final修饰的成员变量,如果没有在定义是给定初始值,那么必须在构造方法中赋值。
因为这个成员变量是随着类的创建而出现,如果该类没有被实例化,那么赋不赋值也无关紧要,但是在创建类时,虚拟机会自动调用构造方法,如果没有在构造方法中给该成员变量赋值,那么就相对于类已经创建好了,但是这个成员变量还没有赋值,因为该变量是被final修饰的,所以在类已经创建后,也无法修改该变量的值,所以这个时候就不符合final的语法规定了,就会报错。
但是如果在虚拟机调用构造方法时,给该变量赋值,那么在类创建后,该变量也是有值的,所以达到了在创建给定值的效果。那为什么这个构造方法需要是所有的构造方法呢,因为如果有不同的构造方法,在实例化对象时,可能会调用不同的构造方法来实例化类,那么如果调用的这个构造方法没有给该变量赋值,那么就出现该类创建后,常量没有值的情况,所以Java不允许这种情况出现,所有得是所有的构造方法都得为该变量赋值。
这就是为什么在Integer包装类中value可以定义为final的变量,但可以不给定初值。
Integer中的静态常量,可直接使用 类名. 的方式调用。
Integer中常用的方法
示例代码:
public class demo {
public static void main(String[] args) {
int num=Integer.parseInt("456"); // 将字符串转换为int类型
Integer iNum=Integer.valueOf("456"); // 创建一个Integer对象
System.out.println("int数据与Integer对象的比较:"+iNum.equals(num));
String str2=Integer.toBinaryString(num); // 获取数字的二进制表示
String str3=Integer.toHexString(num); // 获取数字的十六进制表示
String str4=Integer.toOctalString(num); // 获取数字的八进制表示
String str5=Integer.toString(num,15); // 获取数字的十五进制表示
System.out.println("456的二进制表示为:"+str2);
System.out.println("456的十六进制表示为:"+str3);
System.out.println("456的八进制表示为:"+str4);
System.out.println("456的十五进制表示为:"+str5);
}
}
运行结果
2、Double类
Double类与Float类是对double、float基本类型的封装,它们都是Number类的子类,都是以浮点数进行操作,所以常见方法都基本相同。
而其源码的组成也与Integer大致相同。
Double类中静态常量
NAN表示"Not a Number",在JavaDouble类中,它是一种特殊的浮点数值,表示一个无法表示或定义的结果,例如0.0/0.0,根据IEEE标准,这个结果应该是NaN。在数学和科学计算中,NaN通常表示错误或非法输入,它可以用来表示无效的计算结果或错误的类型转换。----------百度百科
NAN值无法使用比较运算符进行比较,需要使用isNAN方法进行比较。
Double类中常见方法
示例代码
public class demo {
public static void main(String[] args) {
// 定义一个Double对象
Double dNum=Double.valueOf("3.14");
// 判断是否为非数字值
System.out.println("3.14是否为非数字值:"+Double.isNaN(dNum.doubleValue()));
// 转换为int类型
System.out.println("3.14转换为int值为:"+dNum.intValue());
// 判断大小
System.out.println("值为3.14的Double对象与3.14的比较结果:"+dNum.equals(3.14));
// 转换为十六进制
System.out.println("3.14的十六进制表示为:"+Double.toHexString(dNum));
}
}
运行结果
3、Boolean类型
Boolean类将基本类型为boolean的值包装在一个对象中。一个Boolean类型的对象只包含一个类型为boolean的字段。
Boolean类常用方法
Boolean类构造方法
示例
public class demo {
public static void main(String[] args) {
Boolean b1=new Boolean("true");
Boolean b2=new Boolean("ok");
System.out.println("b1:"+b1.booleanValue());
System.out.println("b2:"+b2.booleanValue());
}
}
运行结果
4、Character类
上面介绍过了几种基本类型的包装类,也说过了除了int类型与char类型的包装类不同外,其它基本类型的包装类都是首字母大写即可。
Character类在对象中包装了一个基本类型为char的值,该类也提供了很多方法,使得对char类型的操作变得灵活许多。
Character类常用方法
示例
public class demo {
public static void main(String[] args) {
Character mychar1=Character.valueOf('A');
Character mychar2=Character.valueOf('a');
// 判断是否为大写字母
if(Character.isUpperCase(mychar1)){
System.out.println(mychar1+"是大写字母");
// 转换为小写字母
System.out.println("转换为小写字母的结果:"+Character.toLowerCase(mychar1));
}
// 判断是否为大写字母
if(Character.isLowerCase(mychar2)){
System.out.println(mychar2+"是小写字母");
// 转换为大写并输出
System.out.println("转换为大写字母的结果:"+Character.toUpperCase(mychar2));
}
}
}
运行结果
5、Number类
前面介绍了Java中的包装类,对于数值型的包装类,它们有一个共同的父类 ~~~~ Number类,该类是一个抽象类,它是Byte、Integer、Short、Long、Float和Double类的共同父类,其子类必须提供将表示的数值转换为基本类型的方法。
Number类源码
数值型包装类的共有方法
数字处理
在程序中对于数字的处理也是非常重要的,在某些方法甚至是必要的,如在科学计算中,如果某一项对数字的处理出了错误,那么整个结果也是错误的,再如在支付方面,如果某一款软件对于用户金钱的支出、收入与余额的计算出了错误,那么将是致命性的打击,将会流失一大批用户,毕竟谁也不想使用一个金额计算正确的软件。
所以在Java中对于数字的处理也提供了非常多用于数字处理的类。
1、数字格式化
数字格式化在解决实际问题的应用非常普遍,数字格式化操作主要针对的是浮点类型的处理。Java中提供了 java.text.DecimelFormat 类格式化数字。由于该类不是在java.lang包下的类,所以使用时需要导包。
在Java中,如果没有格式化的数据遵从一下原则:
- 如果数据的绝对值大于0.001并且小于 10^7 ,使得以常规小数形式表示。
- 如果数据的绝对值小于0.001或者大于 10^7,使用科学记数法表示。
DecimelFormat类中的特殊字符及其说明
常见方法
示例
import java.text.DecimalFormat; // 导包
public class demo {
// 使用实例化对象时设置格式化模式
public static void SimgleFormat(String pattern,double value){
// 实例化DecimalFormat对象
DecimalFormat myFormat=new DecimalFormat(pattern);
// 将数字进行格式化
String output=myFormat.format(value);
System.out.println(value+" "+pattern+" "+output);
}
//使用applyPattern方法对数字进行格式化
public static void UseApplyPatternMethodFormat(String pattern,double value){
DecimalFormat myFormat=new DecimalFormat();
myFormat.applyPattern(pattern); // 调用applyPattern方法设置格式化模板
System.out.println(value+" "+pattern+" "+myFormat.format(value));
}
public static void main(String[] args) {
SimgleFormat("###,###.###",123456.789);
// 调用SimgleFormat方法,在数字后加上单位
SimgleFormat("00000000.###kg",123456.789);
// 按照模板格式化数字,不存在的位以0显示
SimgleFormat("000000.000",123.78);
// 将数字转换位百分数形式
UseApplyPatternMethodFormat("#.###%",0.789);
// 将小数点后格式化位两位
UseApplyPatternMethodFormat("###.##",123456.789);
// 将数字转换位千分数形式
UseApplyPatternMethodFormat("0.00\u2030",0.789);
}
}
运行结果
2、Math类
Mtah类,就是一个与基本数学计算有关的工具类,该类中常量或方法都是静态的,可以直接使用 类名.的方式调用。
Math类的空参构造被private修饰了,并且没有有参构造,所以无法创建Math的实例化对象。
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 angdeg) :将角度转换为弧度
- public static double toDegrees(double angrad) :将弧度转换为角度
大概数学免不了与小数打交道,所以以上方法的形参与返回值都定义为double类型的。以上方法参数都以弧度代替角度来实现,其中 1° 等于 π /180° ,所以可以使用180°可以使用π弧度来代替。需要注意的是,角度与弧度的转换通常是不准确的。
示例
public class demo_2 {
public static void main(String[] args) {
// 取90度的正弦
System.out.println("90度的正弦值是:"+Math.sin(Math.PI/2));
// 取0度的余弦
System.out.println("0度的余弦值:"+Math.cos(0));
// 取60度的正切
System.out.println("60度的正切值:"+Math.tan(Math.PI/3));
// 取2的平方根与2商的反正弦
System.out.println("2的平方根与2商的反正弦值:"+Math.asin(Math.sqrt(2)/2));
// 取1的反正切
System.out.println("1的反正切值:"+Math.atan(1));
// 取120度的弧度值
System.out.println("120度的弧度值:"+Math.toRadians(120.0D));
// 取π/2的角度
System.out.println("π/2的角度值:"+Math.toDegrees(Math.PI/2));
}
}
运行结果
②、指数函数方法
Math类中与指数相关的函数方法如下。
以下方法的形式皆是:public static double 方法名(形参);
1. exp(double x):用于获取e的x此方法,即取 e×
2. log(double a):用于取自然对数,即取lna的值。
3. log10(double a):用于取底数为10的a的对数。
4. sqrt(double a):用于取a的平方根,其中a的值不能为负数
5. cbrt(double a):用于取a的立方根。
6. pow(double a,double b):用于取a的b次方。
示例
public class demo_2 {
public static void main(String[] args) {
System.out.println("e的平方值:"+Math.exp(2));
System.out.println("以e为底 2的对数值:"+Math.log(2));
System.out.println("以10为底 2的对数值:"+Math.log10(2));
System.out.println("4的平方根:"+Math.sqrt(4));
System.out.println("8的立方根:"+Math.cbrt(8));
System.out.println("2的2次方:"+Math.pow(2,2));
}
}
运行结果
③、取整函数方法
在具体的问题中,取整操作也是使用的很普遍,所以Java在Mtah类中也添加了数字取整方法。
以下方法的形式皆是:public static double 方法名(形参);
1. ceil(double a):返回大于等于a的最小整数,向上取整。
2. floor(double a):返回小于等于a的最大整数,向下取整。
3. rint(double x):返回与a在数轴上距离最接近的整数,如果存在两个在数轴上的距离相同的整数,那么返回为偶数的那个。
例如,数1.0与数2.0的距离数1.5都是0.5的单位长度,因此Math.rint(1.5)返回偶数2.0。
publi static int round(float a):将参数加上0.5后返回与参数最近的整数。四舍五入函数
publi static long round(double a):是上述方法的重载方法,会将结果强转为长整型。
示例
public class demo_2 {
public static void main(String[] args) {
// 取整函数
System.out.println("使用ceil()方法取整:"+Math.ceil(5.2));
System.out.println("使用floor()方法取整:"+Math.floor(2.5));
System.out.println("使用rint()方法取整:"+Math.rint(2.7));
System.out.println("使用ring()方法取整:"+Math.rint(2.5));
// 四舍五入函数
System.out.println("使用round()方法取整:"+Math.round(3.4f));
// 将结果强转为long类型
System.out.println("使用round()方法取整:"+Math.round(2.5));
}
}
运行结果
④、取最大、最小与绝对值方法
这个方面的方法在Mtah类中提供了很多类型的重载形式。所以这里就不一一介绍了,详细见JavaAPI文档
取最大值:Math.max(参数 a,参数b);
取最小值:Math.min(参数 a,参数b);
取绝对值:Math.abs(参数a);
需要注意的是,在abs取绝对值方法中,有一个漏洞,可能会让你的程序产生误差,那就是如果在使用abs方法时,将int类型的最小整数值 -2147483648 作为参数传入,那么返回的结果将不是 2147483648,而还是-2147483648。
原因是:因为int类型的取值范围是-2147483648 ~ 2147483647,当对最小值取绝对值时,其值超出了int类型的范围,导致溢出。在Java中,整数溢出是一种运行时异常,没有明确定义其行为,因此结果是不确定的。
max、min、abs方法还有一个共同的特征,那么就是它们的方法体主要逻辑都是使用三目运算符实现的。
以返回值为int类型源码
示例
public class demo_2 {
public static void main(String[] args) {
System.out.println("4 和 8 较大值:"+Math.max(4,8));
System.out.println("4.4 和 4 较小值:"+Math.min(4.4,4));
System.out.println("-7 的绝对值:"+Math.abs(-7));
}
}
运行结果
3、Random类
Random类是JDK中的随机数生成器类,可以通过实例化一个Random对象创建一个随机数生成器。
语法如下:Random r=new Random();
Random()方法返回的值实际上是伪随机数,它是通过复杂的运算而得到一系列的数。
这种方式实例化对象时,Java编译器会以系统当前时间作为随机数生成器的种子。但是这种方式会有一个弊端,那就是如果程序运行速度太快,那么产生的随机数可能会相同。
用户也可以在实例化Random对象时,设置随机数生成器的种子。
语法如下:Random r=new Random(seedValue);
Random类常用方法
示例
import java.util.Random;
public class demo_2 {
public static void main(String[] args) {
Random r=new Random();
System.out.println("随机产生一个整数:"+r.nextInt());
System.out.println("随机产生一个大于等于 0 小于等于 10 的整数:"+r.nextInt(10));
System.out.println("随机产生一个布尔类型的值:"+r.nextBoolean());
System.out.println("随机产生一个双精度浮点类型的值:"+r.nextDouble());
System.out.println("随机产生一个单精度浮点类型的值:"+r.nextFloat());
System.out.println("随机产生一个概率密度为高斯分布的双精度浮点类型的值:"+r.nextGaussian());
}
}
运行结果
4、BigInteger类
BigInteger类的数字范围较Integer类的数字范围要大得多。int类型所能表示的最大返回为2^31次方-1,如果要计算更大范围的数字,那么使用int类型也就无法实现了,所以Java中提供了BigInteger类处理更大的数字。BigInteger类支持任意精度的整数,也就是说在计算中BigInteger类可以表示任意精度的整数值而不会丢失信息。
需要注意是,BigInteger虽然能处理任意精度的整数,但是仅限于整数,不支持浮点数类型数据。
例如将整数转换为BigInteger类型。
BigInteger br = new BigInteger("2"); // 十进制参数是以字符串形式存在的。
一但创建了对象实例,就可以调用BigInteger类中的一些方法进行运算操作。
以下介绍几种常见的运算操作,其余详细见JavaAPI文档。
1. public BigInteger add(BigInteger val):做加法运算。
2. public BigInteger subtract(BigInteger val):做减法运算。
3. public BigInteger multiply(BigInteger val):做乘法运算。
4. public BigInteger divide(BigInteger val):做除法运算。
示例
import java.math.BigInteger;
public class demo_2 {
public static void main(String[] args) {
BigInteger b1=new BigInteger("987654321987654321");//第1个大数字
BigInteger b2=new BigInteger("123456789123456789");//第2个大数字
System.out.println("加法操作:"+b1.add(b2));//加法运算
System.out.println("减法操作:"+b1.subtract(b2));//减法运算
System.out.println("乘法操作:"+b1.multiply(b2));//乘法运算
System.out.println("除法操作:"+b1.divide(b2));//除法运算
System.out.println("取商:"+b1.divideAndRemainder(b2)[0]);//取商
System.out.println("取余数:"+b1.divideAndRemainder(b2)[1]);//取余数
System.out.println("做2次方操作:"+b1.pow(2));//取2次方运算
System.out.println("取相反数操作:"+b1.negate());//相反数运算
}
}
运行结果
在本示例中需要的是,divideAndRemainder()方法做除法操作,以数组的形式返回,第一个值为做除法的商,第二个值为做除法的余数。
5、BigDecimal类
相比于BigInteger类,BigDecimal类加入了小数的概念。BigDecimal类支持任何精度的定点数。 可以看做是float与double类型的超强进化版。
常用构造方法
BigDecimal类型的数字可以用来做超大的浮点数的运算,例如+、-、*、\ 等,但是在所有的运算中除法是最复杂的,因为在除不尽的情况下商小数点后的末位的处理是需要考虑的。
常用计算方法
add(BigDecimal augend) :加法
subtract(BigDecimal augend) :减法
multiply(BigDecimal augend) :乘法
divide(BigDecimal divisor,int,scale,RoundingModeroundingMode):除法,方法中3 个参数分别代表除数、商的小数点后的位数、近似处理模式
divide()方法的多种处理模式
示例
import java.math.BigDecimal;
import java.math.RoundingMode;
public class demo_2 {
public static void main(String[] args) {
BigDecimal b1=new BigDecimal("0.00987654321987654321");//第1个大数字
BigDecimal b2=new BigDecimal("0.00123456789123456789");//第2个大数字
System.out.println("两个数字相加结果:"+b1.add(b2));//加法运算
System.out.println("两个数字相减结果:"+b1.subtract(b2));//减法运算
System.out.println("两个数字相乘结果:"+b1.multiply(b2));//乘法运算
//除法运算,商保留小数点后9位,并将结果进行四舍五入操作
System.out.println("两个数字相除,保留小数点后9位:"+b1.divide(b2,9, RoundingMode.HALF_UP));
}
}
运行结果
System类
System类的JDK中提供的系统类,该类是用final修饰的,所以不允许继承。System类提供了很多系统层面的操作方法。
这个类其实我们并不陌生,像输出语句,就是调用System类中静态方法来实现的。而很多工具类内部其实也是使用System类中的方法实现的。
如同Arrays类中的copyOf数组复制方法,底层也是通过调用System类中的方法来实现的
System类常见方法
示例
通过使用System类中的currentTimeMillis()方法来获取某段程序的运行时间。
public class demo_2 {
public static void main(String[] args) {
long start=System.currentTimeMillis();//获取程序开始的时间
String str=null;
for(int i=0;i<10000;i++) {//循环次数
str+=i;
}
long end=System.currentTimeMillis();//获取程序结束时间
System.out.println("循环用时:"+(end-start)+"毫秒");//输出
}
}
运行结果
Scanner类
与C语言不同,Java从控制台中读出用户输入的值,用到的不是一行可以直接使用的代码,而是由一个叫Scanner的类来实现的,它的用途可以将数字化信息流转为人类可识别的文字,控制台输出内容用到了System.out就表示向控制台输出,System.in就表示从控制台输入,让Scanner扫描System.in就可以获取用户输入的值了。
由于Scanner类不是在Java.lang包下的,所以使用时需要导包。
import java.util.Scanner;
Scanner类提供了很多获取不同数值类型的方法。但是却没提供读取单个字符的方法,那么如果想要读取单个字符,除了使用Java的其它类之外,还有一个小技巧也能达到读取的那个字符的效果。
Scanner in=new Scanner(System.in);
System.out.println(in.nextLine().charAt(0));
Scanner常见读取方法
需要注意的是,nextLine()方法扫描的内容是从第一个字符开始到换行符为止,而next()、nextInt()等方法扫描的内容是从第一个字符开始到这段完整内容结束。
也就是说nextLine()方法获取输入内容,会一直读取,直到遇到换行符为止,而next()等其余的方法,读取输入,如果遇到空格、换行符就会停止读取。
示例
public class demo_2 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("第一句:"+in.next());
System.out.println("第二句:"+in.nextLine());
}
}
运行结果
可以看到第二个输入会将空格一起获取,而第一个输入遇到空格就停止读取。所以以后使用时需要根据不同的应用场景来选取不同的读取方法。
日期时间类
在程序开发中,日期与时间的获取也是非常的普遍的,例如根据业务需求,需要制作一个零点秒杀活动,此时准确的获取时间是一定的。所以Java中也提供了专门的日期时间类来处理相应的问题。
1、Date类
Date 类用于表示日期时间,使用该类表示时间需要使用其构造方法创建对象。
构造方法
需要注意的是创建Date对象时,使用的的是long类型整数,而不是double类型,这主要是因为double类型可能会丢失精度。
常见方法
详细见JavaAPI
示例
import java.util.Date;
public class demo_2 {
public static void main(String[] args) {
Date date=new Date();//创建现在的日期
long value=date.getTime();//获取毫秒数
System.out.println("日期:"+date);
System.out.println("到现在所经历的毫秒数为:"+value);
}
}
运行结果
需要注意的是,本节的Date类是在java.util包下的,但是java.sql包下也有个Date类,所以使用不要将两者弄混。
2、DateFormat类
如果在程序中直接输出Date类,显示的结果是:“日期:Sun May 21 09:19:52 CST 2023”这种格式的日期时间,那么如何让其显示为 “2023/5/21"或"9:26" 这样的时间格式呢?Java提供了DateFormat类来实现类似的功能。
DateFormat 类是日期时间格式化子类的抽象类,可以按照指定的格式对日期或时间进行格式化。
DateFormat 类提供了很多类方法,以获得基于默认或给定语言环境和多种格式化风格的默认日期时间Formatter,格式化风格主要包括 SHORT、MEDIUM、LONG 和FULL4种:
SHORT:完全为数字,如 12.13.2或3:30pm。
MEDIUM:较长,如 Jan 12,1952。
LONG:更长,如January 12,1952 或3:30:32pm。
FULL:完全指定,如 Tuesday、April 12、1952AD 或3:30:42pm PST。
要格式化一个当前语言环境下的日期,首先需要创建 DateFormat 类的一个对象,由于它是抽象类,因此可以使用其静态方法 getDateInstance() 进行创建。
语法:DateFormat df = DateFormat.getDatelnstance();
DateFormat 类常用方法
详细见JavaAPI文档
示例
import java.util.Date;
import java.text.DateFormat;
public class demo_2 {
public static void main(String[] args) {
System.out.println("将当前日期按照DateFormat类默认格式输出:");
DateFormat df = DateFormat.getInstance();
System.out.println(df.format(new Date()));
System.out.println("输出长类型格式的当前时间:");
DateFormat df2 = DateFormat.getTimeInstance(DateFormat.LONG);
System.out.println(df2.format(new Date()));
System.out.println("输出长类型格式的当前日期:");
DateFormat df3 = DateFormat.getDateInstance(DateFormat.LONG);
System.out.println(df3.format(new Date()));
System.out.println("输出长类型格式的当前日期和时间:");
DateFormat df4 = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
System.out.println(df4.format(new Date()));
}
}
运行结果
由于DateFormat类是一个抽象类,不能直接使用new创建实例化对象,因此除了使用getXXXInstance()方法的方式创建其对象外,还可以使用多态的方式,用它的子类创建对象,如SimpleDateFormat类,该类是一个以与语言环境相关的方式来格式化和分析日期的具体类,它允许进行格式化(日期 ~ 文本),分析(文本 ~ 日期)和规范化。
SimpleDateFormat提供了19个格式化字符,可以让开发者随意的编写日期格式。
格式化字符表
需要注意的是,H与k,虽然都是表示一天中的小时数,但是这两个格式化字符的区别在于对处理24点时刻,在k代表的小时制中,24点就是表示24点。在H代表的小时制中,24点就是表示0点。
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) throws ParseException {
String time="2023年5月21号 24:00:00";
SimpleDateFormat sdf1=new SimpleDateFormat("yyyy年MM月dd号 kk:mm:ss");
SimpleDateFormat sdf2=new SimpleDateFormat("yyyy年MM月dd号 HH:mm:ss");
Date date1=sdf1.parse(time); // 将字符串时间解析为Date对象
Date date2=sdf2.parse(time);
// 格式化
System.out.println("k代表的小时制:"+sdf1.format(date1));
System.out.println("H代表的小时制:"+sdf2.format(date2));
}
}
运行结果
3、Calendar类
Calendar是一个日历类,可以对日期时间进行加减运算等复杂的操作。Calendar类是抽象类,它为特定瞬间与一组日历字段之间的转换提供一些的方法,并为操作日历字段提供了一些方法。这些字段与方法被定义为protected。
Calendar提供了一个类方法 getInstance(),以获取一个通用的对象。
使用方法:Calendar rightNow=Calendar.getInstance();
由于Calendar是一个抽象类,所以不能使用new创建对象,因此除了使用上述方法创建其对象外,必须使用其子类,如GregorianCalendar类创建对象。
Calendar 常见字段
详细见API文档
Calendar 常见方法表
示例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class demo_2 {
public static void main(String[] args) {
System.out.println("——————————————中华人民共和国成立100周年倒计时——————————");
Date date=new Date();//当前时间
//创建SimpleDateFormat指定目标格式
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyy年MM月dd日");
//调用format方法,格式化时间,转换为指定格式
String today=simpleDateFormat.format(date);
//输出当前时间
System.out.println("今天是"+today);
//将当前时间转换为毫秒数
long time1=date.getTime();
//使用默认时区和语言环境获得一个日历
Calendar calendar=Calendar.getInstance();
//设置日历calendar中的年月日,因为月份是从0开始计算的,所以这里
calendar.set(2049,10-1,1);
//计算1970年1月1日至2049年10月1日所经过的毫秒数
long time2=calendar.getTimeInMillis();
//计算差值
long day=(time2-time1)/(1000*60*60*24);
//输出
System.out.println("距离2049年10月1日还有"+day+"天!");
}
}
运行结果
最后对 Calendar 类的使用做出几点总结:
c.set(CalendarDAY_OF_MONTH,0)获取的是上个月的最后一天,所以调用前需要将月份往后加一个月。
Calendar.MONTH的第一个月是使用0记录的,所以在获得月份数字后要加1。年和日是从1开始记录的,不需要加 1。
Calendar.DAY OF WEEK 的第一天是周日,周一是第二天,周六是最后一天。
Runtime类
Runtime 类是 JDK 供的运行时类,该类为 Java程序提供了与当前运行环境相连接的一个通道。
Runtime 类将唯一的一个无参构造给私有化了,所以外界不能使用 new 关键字创建实例,只能通过 Runtime. getRuntime()方法获取实例。
Runtime常见方法
执行本地命令
本地命令指的是操作系统的命令。例如,在 Linux 系统下就表示 shell 命令,在 Windows 系统下表示 cmd 命令。
Runtime 类提供 exec()方法让 Java 代码可以执行系统的命令,exec()方法有很多重载的形式。
例如:
Process exec(String command); // command:要执行的系统命令,字符串类型
Process exec(Stringl cmdarray); // cmdarray:要执行的命令和相应的命令参数,字符串数组类型。
Process类
exec()方法会返回一个Process对象。Process类是Java中的进程类,该类是抽象类,不能使用new创建其对象。
Process类常见方法表
示例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class demo_2 {
public static void main(String[] args) {
Runtime r=Runtime.getRuntime();//获取本地Runtime对象
try {
Process p=r.exec("help");//执行help命令,获取进程对象
InputStream is=p.getInputStream();//获取进程的字节输入流
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String str=null;//创建空字符
while((str=br.readLine())!=null) {//如果字符流中可以获取非空内容
System.out.println(str);//打印
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
2、查看内存
Runtime类可以通过 freeMemory()方法查看当前Java虚拟机可用内存的剩余量。如果程序能够实时监控内存剩余量,就可以尽量控制程序对内存的占用,从而避免出现“内存溢出”的情况。同样,也可以用来对测试程序性能,检验程序算法是否导致内存紧张。
示例
public class demo_2 {
public static void main(String[] args) {
Runtime r=Runtime.getRuntime();//获取本地Runtime对象
Integer ints[]=new Integer[10000];//创建长度为10000的整型数组
long before=r.freeMemory();//获取当前空闲内存数
System.out.println("赋值前空闲内存字节数:"+before);
for(int i=0,length=ints.length;i<length;i++) {//循环为整型数组赋值
ints[i]=i;//赋值
}
long after=r.freeMemory();//获取当前空闲内存数
System.out.println("赋值后空闲内存字节数:"+after);
System.out.println("数组用掉的内存字节数:"+(before-after));//输出数组用掉的内存量
}
}
运行结果
总结
在本章中,学习了大量的AIP(Application Programming Interface)的使用,在程序中合理的运行这些API的话,能使得程序的编写变得事半功倍,但是大量的API的学习,不一定学完就记住了,毕竟本章的篇幅可谓是很长的,一般都是在使用的过程中,才会逐渐加深印象,但是如果有时想运用某个API的时候记不到了怎么办,这个时候就需要查阅Java的API文档了,在文档中有着详细的介绍,通过AIP文档,我们就能知道某个API内部的字段、方法、子类、父类等信息。
b站的up主黑马程序员,在发布的Java教学视频下,免费分享了一个版本的API文档,能够满足大部分初学者的需求。
https://www.bilibili.com/read/cv11763184
该API文档在本路径下,可自行下载。