Java API介绍
Java API(Java Application Programming Interface)即Java应用程序编程接口,它是运行库得集合,预先定义一些接口和类,程序可以直接使用这些已经打包好的接口和类开发具体得应用来节约大量的时间和精力。API除了有“应用程序编程接口”的意思。
Java语言的强大之处在于它提供了多种多样的类库,从而大大提高了程序的编程效率和质量。
Java API提供的常用包
- java.lang:编写Java程序时使用最广泛的包,自动导入所有的程序中,包含了Java程序的基础类和接口。包装类、String类等常用的类都被包含在此包中。java.lang包还提供了用于管理类的动态加载、外部进程创建、主机环境查询和安全策略实施等系统操作的类。
- java.util:包含了系统辅助类,特别是
Collection
、List
和Map
等集合类。 - java.time:包含了对日期时间进行处理的类,如创建日期对象,格式化日期等。
- java.io:包含了与输入/输出有关的类,如文件操作等类。
- java.net:包含了与网络有关的类,如
Socket
、ServerSocket
等类。 - java.sql:包含了与数据库相关的类,如
Connection
、Statement
等类。
枚举
在学习了Java有两种方式定义新类型:类和接口。对于开发大多数情况来说这方式已经足够了,但是在一些特殊情况下,这些方式就不适合了。例如,定义果树的生长状态,包括:生长期、采摘期、已死亡,需要定义一个Contants类,在其中定义三个静态常量分别记录三种状态,如下所示。
public class Constants{
public static final String GROW = "生长期";
public static final String MATURE = "采摘期";
public static final String DEAD = "已死亡";
}
但如果遇到以下需求,还需继续完善,继续繁琐的处理。
需要为每个常量分配一个整数值,以便向数据库录入数据。
在实际开发中,状态值以整型数据形式存储到数据库中效率更高,在程序中执行状态判断时使用整型值效率更高。例如:生长期=0、采摘期=1、已死亡=2。代码如下。
public class Constants{
public static final int GROW = 0;
public static final int MATURE = 1;
public static final int DEAD = 2;
}
上面的代码很容易出错,例如,整型的常量值出现重复,编译器也不会给出任何提示。
如果需要更强大的数据展示和处理功能,则需要自行编写。
例如,遍历所有果树生长状态信息,或者需要自动获取果数状态的个数等。
自从Java1.5引入枚举类型,这些问题就得以解决。
枚举的概述
事先考虑到某一变量可能的取值,尽可能用自然语言中表意清楚的单词来表示它的每一个值,用这种思路定义的类型被称为枚举类型。
枚举使用一组戈丁的常量组成的类型。在Java中每个枚举都继承Java.lang.Enum
类,使用关键字enum
定义。
语法:
访问修饰符enum枚举名{
常量1[,常量2…[:]]
//其他成员
}
- 在枚举中可以定义多个常量,表示不同的枚举值,即枚举元素,之间用逗号隔开。
- 在枚举中可以定义其他成员,包括构造方法等,置于枚举常量之后。
- 可以使用“枚举名.常量名“的形式去除枚举中的指定内容。
定义表示性别的枚举,两个枚举常量分别代表"男"和"女",如下所示。
public enum Genders{
Male,Female;
}
在以上代码中,Genders
中定义的枚举类型里包含Male、Female两个数据。
在Java中,通常使用枚举表示一组有限的值,实现对输入的值进行约束。下面通过示列1学习在程序中如何定义和使用枚举。
定义一个枚举,包括七个枚举常量,代表一周中的七天,编程实现查看一周中每天的日程安排。代码如示列1所示。
示列1
枚举代码如下
package UtilityClass.enumeratePractice;
public enum Week {
MON,TUE,WED,THU,FRI,SAT,SUN;
}
测试类如下
package UtilityClass.enumeratePractice;
public class WeekTest {
/**
* 查看日程安排
*
* @param day 星期几
*/
public void doWhat(Week day) {
switch (day) {
case MON:
case TUE:
case WED:
case THU:
case FRI:
System.out.println("工作日,努力写代码!");
break;
case SAT:
System.out.println("星期六,休息!看电影!");
break;
case SUN:
System.out.println("星期日,休息!打篮球!");
break;
default:
System.out.println("地球上一个星期接口7天");
}
}
public static void main(String[] args){
WeekTest test = new WeekTest();
test.doWhat(Week.THU);
Week sat = Week.SAT;
test.doWhat(sat);
}
}
在示列1中,枚举类型Week可存储表示一周七天的枚举常量,使用"Week.THU
"可输出表示星期四的枚举值。switch
结果传入变量day是Week类型,即枚举练习:case
关键字后的常量要与之匹配,必须是Week中定义的枚举常量。
除此之外,使用枚举类型的Values()
方法可以实现对枚举值的遍历操作,修改示列1,关键代码如下。
public static void main(String[] args){
WeekTest test = new WeekTest();
for (Week w:Week.values()){
test.doWhat(w);
}
}
示列1枚举的遍历结果
工作日,努力写代码!
工作日,努力写代码!
工作日,努力写代码!
工作日,努力写代码!
工作日,努力写代码!
星期六,休息!看电影!
星期日,休息!打篮球!
Process finished with exit code 0
上面的代码中,Week.values()
方法表示取得枚举中的全部内容,返回一个对象数组,这是枚举本身支持的一个方法,除此之外,关于Enum类的其他用法,此处不深入讲解,以后用到时可自行查看API帮助文档。
枚举的方法
每一个枚举类型的成员都可被看作Enum对象。所有枚举实例都可以调用Enum类的方法,实现枚举的遍历、比较等操作。
每一个枚举类型的成员都可被看作Enum对象。所有枚举实例都可以调用Enum类的方法,实现枚举的遍历、比较等操作。
方法 | 描述 |
---|---|
T[] values() | 以数组形式返回枚举类型的所有成员 |
T valueOf() | 将普通字符串转换为枚举实例 |
int compareTo() | 比较两个枚举成员在定义时的顺序,结果为负数、零或正整数,表示当前对象小于、等于胡哦大于指定对象 |
int ordinal() | 获取枚举成员的索引位置 |
示列2综合运用枚举的常用方法,实现枚举的遍历和比较等操作,关键代码如下。
示列2
枚举代码如下
package UtilityClass.enumeratePractice.theenumerationmethod;
public enum Week {
MON,TUE,WED,THU,FRI,SAT,SUN;
}
测试类
package UtilityClass.enumeratePractice.theenumerationmethod;
import UtilityClass.enumeratePractice.Week;
public class EnumTest {
public static void main(String[] args){
//遍历枚举
System.out.println("********foreach遍历枚举元素********");
for (Week w :Week.values()){
System.out.println(w);
}
System.out.println("********获取枚举的个数********");
System.out.println("一周有"+Week.values().length+"天");
System.out.println("********使用索引遍历枚举元素********");
for (int i =0; i < Week.values().length; i++){
System.out.println("索引"+Week.values()[i].ordinal()+",值:"+Week.values()[i]+"。");
}
System.out.println("********枚举元素比较********");
//字符串转换为枚举再进行比较
System.out.println((Week.valueOf("MON")).equals(Week.MON));
System.out.println(Week.FRI.compareTo(Week.TUE));
}
}
运行结果
********foreach遍历枚举元素********
MON
TUE
WED
THU
FRI
SAT
SUN
********获取枚举的个数********
一周有7天
********使用索引遍历枚举元素********
索引0,值:MON。
索引1,值:TUE。
索引2,值:WED。
索引3,值:THU。
索引4,值:FRI。
索引5,值:SAT。
索引6,值:SUN。
********枚举元素比较********
true
3
Process finished with exit code 0
在示列2中可以看出,枚举具有类似数组的特征,每个枚举元素都默认有一个对应的索引值,表示枚举元素的位置,初始化值从0开始,能够通过索引访问枚举元素。同时,通过调用枚举类中的方法可以实现更多样化的数据操作,大大提高了遍码效率,避免了错误的发生,简化代码。
小结
在程序中使用枚举,好处如下。
- 枚举可以使代码更易于维护,有助于确保为变量指定合法的,期望的值。
- 使用枚举赋值,只需输入枚举名和 ",", 就可以显示所有枚举值。
- 枚举使代码更加清晰,允许用描述性的名称表示数据,使用时更加直观方便。
包装类
包装类概述
Java是面向对象的编程语言,但它的基本数据类型是不支持面向对象机制的,比具备对象的特征,他们为程序开发带来的一定的方便性,如可以进行有效、常规的数据处理,但有些时候也会受到一些制约,例如,所有的引用类型的变量都继承了Object
类,可以当作Object
类型变量使用,但基本数据类型不可以,如果方法的参数是Object
类型,但实际上需要的数据是类似2、3这样的数值,就比较难处理。思考下面的问题。
问题
在以下定义的ArrayList
集合中,集合元素为Object
类型,但向其中添加数据类型时,程序为什么不报错呢?
ArrayList fruitList.add = new ArrayList();
fruitList.add("香水梨");
fruitList.add("苹果梨");
fruitList.add(5);//添加基本数据类型
fruitList.add(2.8);//添加基本数据类型
fruitList.add("甜")//添加基本数据类型
答案是代码中使用了包装类。包装类是指将数据类型封装到一个类中,也就是基本类型包装成一个类类型。Java
程序设计语言为每一种基本类型都提供了一个包装类,而这些包装类存在于Java.lang包中,共有八卦包装类。如图所示。
其中:
- 所有字母类型包装类都继承Number类,Number类是一个抽象类。
- Number类包装了Byte、Short、Interger、Long、Float、Double等数据类型,并且实现其所定义的方法,这些方法以不同的数字格式返回对象的值。
包装类和基本数据类型的对应关系表如下:
基本数据类型 | 包装类型 |
---|---|
byte | java.lang.Byte(父类Number) |
short | java.lang.Short(父类Number) |
int | java.lang.Integer(父类Number) |
long | java.lang.Long(父类Number) |
float | java.lang.Float(父类Number) |
double | java.lang.Double(父类Number) |
boolean | java.lang.Boolean(父类Object) |
char | java.lang.Character(父类Object) |
包装类的用途主要有以下两个
- 包装类作为和基本数据类型对应的类型存在,方便对象的操作。
- 包装类包含每种基本数据类型的相关属性,如最大值、最小值等。以及相关的操作方法
包装类和基本数据类型的转换
在不同的应用场景中,基本数据类型和包装类要进行互相转换以完成特定操作,下面详细介绍它们之间互相转换的方法。
基本数据类型转换为包装类
在Java中,基于基本类型数据创建包装类对象通常不可以采用如下两种方式。
public Type(type value)
public Type(String value)
其中,Type表示包装类,参数type为基本数据类型。
针对每一个包装类,都可以使用关键字new将一个基本数据类型值包装为一个对象。
Integer intValue=new Integer(21);
或
Integer intValue=new Integer(“21”);
基本数据类型向包装类转换的用法,如示列3所示。
示列3
package UtilityClass.enumeratePractice.packagingtransition;
/**
* 基本数据类型向包装类转换
*/
public class Test {
public static void main(String[] args){
boolean bl = true;
//1、通过构造方法实现基本数据类型向包装类转换
//若 new xxx 报错 原因是JDK版本太高了 1.8左右不会报错 可以运行~
Boolean blObj = new Boolean(bl);
Integer itObj = new Integer(35);
Character chObj = new Character('男');
System.out.println(blObj+","+itObj+","+chObj);
//2、将字符串转换为Boolean对象
Boolean bObj = new Boolean("true");
//不区分大小写
Boolean bObj2 = new Boolean("TRue");
//非true即false
Boolean bObj3 = new Boolean("hello");
System.out.println(bObj+","+bObj2+","+bObj3);
//运行时将出现java.lang.NumberFormatException异常
Long lObj = new Long("hello");
//Char型数据类型不能使用字符串构造包装对象
//报错 java: 不兼容的类型: java.lang.String无法转换为char
//Character chobj = new Character("男");
}
}
运行结果
true,35,男
true,true,false
Exception in thread "main" java.lang.NumberFormatException: For input string: "hello"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Long.parseLong(Long.java:711)
at java.base/java.lang.Long.<init>(Long.java:1348)
at UtilityClass.enumeratePractice.packagingtransition.Test.main(Test.java:23)
Process finished with exit code 1
包装类转换基本数据类型
包装类型转换为基本数据类型通常采用如下方法:
public type typeValue();
其中,type指的是基本数据类型,如byteValue()
、charValue()
等,相应的返回值为byte
、 char
。将包装类对象转换为基本类型数据。代码如示列4所示。
示列4
package UtilityClass.enumeratePractice.packagingtransitiontow;
/**
* 包装类转换为基本数据类型
*/
public class Test {
public static void main(String[] args){
boolean bl = true;
//通过构造器实现基本数据类型向包装类转换
//若 new xxx 报错 原因是JDK版本太高了 1.8左右不会报错 可以运行~
Boolean blObj = new Boolean(bl);
Integer itObj = new Integer(35);
Character chObj = new Character('男');
//包装类转换为基本数据类型
boolean b1 = blObj.booleanValue();
int i = itObj.intValue();
char ch = chObj.charValue();
System.out.println(b1+","+","+ch);
}
}
如下结果如下
true,,男
Process finished with exit code 0
装箱拆箱
Java基本数据类型变量和包装类对象之间的转换较烦琐,从JDK1.5之后提供了自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)功能。
- 自动装箱:把基本书记类型变量直接转换为对应的包装类对象,或者转换为Object对象。
- 自动拆箱:与装箱相反,将包装类对象转换成对应的基本数据类型变量。
自动装箱和自动拆箱操作的用法如示列5所示
示列5
package opp.UtilityClass.splitopenacaseusingthe;
public class BoxTest {
public static void main(String[] args) {
//基本数据类型变量转换为包装类(装箱)
Integer inObj = 5;
Object boolObj = true;
System.out.println(inObj+","+boolObj);
//包装类转换为基本数据类型(拆箱)
int it = inObj;
System.out.println(it);
if (boolObj instanceof Boolean){
//先把object对象强制转换为Boolean类型,再赋值给boolean变量
boolean b = (Boolean)boolObj;
System.out.println(b);
}
}
}
运行结果
5,true
5
true
Process finished with exit code 0
从示列 5可以看出,当JDK提供了自动装箱/拆箱功能后,大大简化了基本数据类型和包装类互相转换的过程,但是进行自动装箱/除箱时必须注意利类型匹配。例如,Integer
对象只能自动拆箱成int变量,不能试图自动拆箱成boolean类型变量;而int变量也只能自动装箱成Integer
对象,不能自动装箱成Boolean
对象。即使其可以赋值给Object
对象,也利用了Java中向上转型的特性。
日期类
在程序开发中经常会遇到日期类的操作,在JDK1.8之前的版本中,所有关于时间和日期的API在使用上都存在缺陷。
- 易用性差,时间的计算方式繁琐
- 不是线程安全的。
基于以上问题,JDK1.8引入了一套新的时间API,借助新的API可以用更简洁的方法处理时间和日期。
创建日期对象
在JDK1.8中,日期和时间的类都位于java.time包中,他是新的Java日期/时间API的基础包,这些类都是不可变的、线程安全的,在绝大多数情况下,这些类能够有效地处理一些公共需求。常用如下表
类 | 描述 |
---|---|
LocalDate | 表示日期(年/月/日),不包含时间,如2022-10-28 |
LocalTime | 表示时间(时/分/秒/毫秒),不包含日期,如15:52:13 |
LocalDateTime | 表示日期和时间(年/月/日/时/分/秒/毫秒),如2022-10-28 15:52:13 |
LocalDate
类、LocalTime
类、LocalDateTime
类的实列是不可变的对象,它提供了简单的日期或时间,并不包含时间信息,也不包含与时区相关的信息。日期类通用方法如下表
方法 | 描述 |
---|---|
日期类 now() | 静态方法,根据当前时间创建对象,返回日期对象 |
日期类 of(int year,Month month,int dayOfMonth) | 静态方法,根据指定日期/时间创建日期类对象,如LocalDate.of(2022,Month APRLL,8) |
Month get Month() | 获取月份,返回Month,是一个表示月份的枚举 |
int getDayOfMonth() | 返回当前日期类对象的月份天数 |
int get Year() | 返回当前日期类对象的年份 |
日期类plusDays () 日期类plusWeeks() 日期类plusMonths() 日期类plusYears() | 在指定日期的基础上增加天数,周数,月份,年数,返回日期对象 |
日期类指 LocalDate
类、LocalTime
类、LocalDateTime
等类型。运用这些类可以实现获取日期时间类对象。例如,获取当前日期或者时间代码如下。
LocalDate localDate = LocalDate.new();//获取当前日期
LocalDate localTime = LocalTime.new();//获取当前时间
日期格式化
有时需要按照定义的格式输出系统时间,这就需要使用DateTimeFormatter
类的相关方法进行日期格式化处理,该类位于java.time.format包中。日期类中的format
方法用于将日期格式化为字符串,该方法接收了一个DateTimeFormatter
对象,除此之外,DateTimeFormatter
类的format()
方法也可以实现日期格式化。示列代码如下。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
//两种格式化方式
String str1 = localDate.forme(formatter);
String str2 = localDate.forme(localDate);
在以上代码中,ofPattern()方法用于指定日期格式。参数为格式字符串,该方法的作用是指定日期输出格式。
根据当前日期,计算农场下次播种时间,和收割时间,要求如下。
- 使用不同格式输出当前日期,如 "yyyy"年MM月dd日HH:mm:ss" "yyyy-MM-dd"。
- 分别提取当前日期对应的年、月、日信息并输出。
- 输入当前日期距离下次播种还有几个月,计算并输出下次播种时间。
- 输入收割时间,并输出到控制台。
示列6
package opp.UtilityClass.datefarm;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
/**
* 时间类测试
*/
public class TimeTest {
public static void main(String[] args) {
//1、获取现在时间
LocalDateTime today = LocalDateTime.now();
//2、创建格式化器
DateTimeFormatter fr1 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
DateTimeFormatter fr2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//3、将日期格式化为字符串
String str1 = today.format(fr1);
String str2 = today.format(fr2);
System.out.println("当前日期(日期+时间):"+str1+"。");
System.out.println("当前日期:"+str2+"。");
//4、提取日期中的年、月、日信息
System.out.println("年:"+today.getYear()+"月:"+today.getMonth()+"日:"+today.getDayOfMonth());
//5、根据间隔时间输出日期
System.out.print("距离下次播种大约还有几个月?(1~12间整数:)");
Scanner input = new Scanner(System.in);
LocalDateTime future = today.plusMonths(input.nextLong());
String str3 = future.format(fr2);
System.out.println("下次播种时间约为:"+str3+"。");
//6、根据输入时间输出
System.out.print("请输入计划开始收割日期(格式:yyyy-MM-dd):");
//将字符串转换为日期
LocalDate id = LocalDate.parse(input.next());
String str4 = id.format(fr2);
System.out.println("收割开始日期为"+str4+",过个好年");
}
}
运行结果为
当前日期(日期+时间):2022年10月28日 21:46:03。
当前日期:2022-10-28。
年:2022月:OCTOBER日:28
距离下次播种大约还有几个月?(1~12间整数:)5
下次播种时间约为:2023-03-28。
请输入计划开始收割日期(格式:yyyy-MM-dd):2024-05-23
收割开始日期为2024-05-23,过个好年
Process finished with exit code 0
Random类
在项目开发中,经常需要使用随机数值,例如,网站登陆中的验证码,或者需要以一定概率实现的某种效果(如游戏程序中的物品掉落等),就需要Java提供的Random
类,该类用于生成随机数。它位于Java.util包中,每当需要以任意或非系统方式生成数字时,就是用此类。Maath
类的Random
()方法也可以产生随机数。其实,Math
类Random()
方法的底层就是使用Random
类实现的。该类的构造方法有两种重载方式。如下表所示。
构造方法 | 描述 |
---|---|
Random() | 创建一个随机生成器 |
Random(long seed) | 使用单个long种子创建一个随机生成器 |
Random
类定义了很多用于获取随机数的方法,最常用的时nextInt()
方法,它返回下一个interesting
类型的伪随机数,有如下两个重载方法。
int nextInt();
int NextInt(int n);
其中,前者返回下一个伪随机数,他是此随机数生成器序列中均匀分布的int值:后者返回下一个伪随机数,他是取自此随即苏生成器序列的、在0(包括)和指定值n(不包括)之间均匀分布的int值。
随机生成十个10以内大于或等于0的整数并将其显示出来,代码示列7所示
示列7
package opp.UtilityClass.randomnumber;
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
//创建一个Random对象,即随机生成器
Random rand = new Random();
//随机生成10个随机整数并显示
for (int i = 0; i < 10; i++) {
int num = rand.nextInt(10);
System.out.println("第" + (i + 1) + "个随机数是:" + num);
}
}
}
运行结果
第1个随机数是:0
第2个随机数是:1
第3个随机数是:9
第4个随机数是:2
第5个随机数是:2
第6个随机数是:5
第7个随机数是:0
第8个随机数是:0
第9个随机数是:8
第10个随机数是:9
Process finished with exit code 0
Random
类还定义了得到long
型、boolean
型、float
型等伪随机数方法。具体用法可查看API帮助文档。
提示
- 计算机不能产生绝对的随机数,只能产生伪随机数."伪"的意思并非真正的随机,而是有规律的,伪随机数实际上就是计算机通过系统的随机数算法计算得出的有规律的"随机数",可以把这个算法看成一个黑盒子,种子可被认为是放入黑盒子中参加计算的一个参数。
- 如果用同样的一个种子值来初始化两个
Random
对象,要每个对象调用相同的方法,得到的随机数也是相同的。未设置种子值时,默认使用当前时间作为种子。