本章内容:

1.包装类
2.enum枚举类型
3.常用工具类
4.异常处理机制
5.Java集合
6.日期与时间

1. 包装类

映射关系

基本类型===> 对应的引用类型
boolean ===> java.lang.Boolean
byte ===> java.lang.Byte
short ===> java.lang.Short
int ===> java.lang.Integer
long ===> java.lang.Long
float ===> java.lang.Float
double ===> java.lang.Double
char ===> java.lang.Character

包装类的实际运用(以int和integer为例)

  1. int和integer类之间的转换:在实际转换时,使用Integer类的构造方法和Integer类内部的intValue方法实现这些类型之间的相互转换
1
2
3
4
5
6
7
int n=5;
Integer n1=new Integer(n);
System.out.println("int类型转换为integer类:"+n1);

Integer i=new Integer(50);
int i1 = i.intValue();
System.out.println("integer类转换为int类型:"+i1);
  1. Integer类内部的常用方法(Integer类的主要方法有:parseInt方法和toString方法)
1
2
3
4
5
6
7
8
9
10
11
12
//parseInt方法: 数字字符串类型转成int类型
String ss="123";
int ii = Integer.parseInt(ss);
System.out.println("字符类型转成整型:"+ii);

// parseInt(String s ,int radix)的目的是求"radix"进制数"s"的十进制数是多少
System.out.println(Integer.parseInt("444",16);); // 表示16进制的0x444的十进制是多少

//toString方法:int类型转成数字字符串类型
int ii2=123;
String ss2 = Integer.toString(ii2);
System.out.println("int类型转成数字字符串类型:"+ss);

拓:

  • equals() 比较的是两个对象的值(内容)是否相同。
  • == 比较的是两个对象的引用(内存地址)是否相同,也用来比较两个基本数据类型的变量值是否相等

3.enum枚举类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Main {
public static void main(String[] args) {
Weekday day = Weekday.SUN;
if (day == Weekday.SAT || day == Weekday.SUN) {
System.out.println("Work at home!");
} else {
System.out.println("Work at office!");
}
}
}

enum Weekday {
SUN, MON, TUE, WED, THU, FRI, SAT;
}

4.常用工具类

Math:数学计算

Math.abs()求绝对值
Math.max/min()
Math.pow(a,b)计算a的次方
Math.sqrt()计算开方
Math.exp()计算e的次方
Math.PI数学常量PI
Math.E数学常量e
Math.random()生成随机[0,1)的数

Random:随机数

1
2
3
4
5
6
7
8
9
10
11
12
// 创建Random实例对象
Random r = new Random(seed); // 种子数只是随机算法的起源数字,和生成的随机数的区间没有任何关系
r.nextInt(); // 2071575453,每次都不一样
r.nextInt(100); // 54,生成一个随机[0,100)的随机整数
r.nextInt(10); // 5,生成一个[0,10)之间的int
r.nextLong(); // 8811649292570369305,每次都不一样
r.nextFloat(); // 0.54335...生成一个[0,1)之间的float
r.nextDouble(); // 0.3716...生成一个[0,1)之间的double

Random rand =new Random(25); // 预设种子数
int i=rand.nextInt(100);
System.out.println(i);

初始化时25并没有起直接作用(注意:不是没有起作用),rand.nextInt(100);中的100是随机数的上限,产生的随机数为0-100的整数,不包括100

对于种子相同的Random对象,生成的随机数序列是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Random ran1 = new Random(10);
System.out.println("使用种子为10的Random对象生成[0,10)内随机整数序列: ");
for (int i = 0; i < 10; i++) {
System.out.print(ran1.nextInt(10) + " ");
}
System.out.println();
Random ran2 = new Random(10);
System.out.println("使用另一个种子为10的Random对象生成[0,10)内随机整数序列: ");
for (int i = 0; i < 10; i++) {
System.out.print(ran2.nextInt(10) + " ");
}

/**
* 输出结果为:
*
* 使用种子为10的Random对象生成[0,10)内随机整数序列:
* 3 0 3 0 6 6 7 8 1 4
* 使用另一个种子为10的Random对象生成[0,10)内随机整数序列:
* 3 0 3 0 6 6 7 8 1 4
*
*/

BigDecimal大数类

float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal(大数类的运算效率肯定不如原生类型效率高,代价比较昂贵,需要结合具体的场景来使用)
大数类的传入的值必须为字符串类型

1
2
3
4
5
6
7
8
9
10
11
12
BigDecimal a=new BigDecimal ("4.5");
BigDecimal b=new BigDecimal ("1.5");
a.add(b) // 6.0
add(BigDecimal value):加法,求两个BigDecimal类型数据的和。
subtract(BigDecimal value):减法,求两个BigDecimal类型数据的差。
multiply(BigDecimal  value):乘法,求两个BigDecimal类型数据的积。
divide(BigDecimal divisor):除法,求两个BigDecimal类型数据的商。
remainder(BigDecimal divisor):求余数,求BigDecimal类型数据除以divisor的余数。
max(BigDecimal value):最大数,求两个BigDecimal类型数据的最大值。
min(BigDecimal value):最小数,求两个BigDecimal类型数据的最小值。
abs():绝对值,求BigDecimal类型数据的绝对值。
negate():相反数,求BigDecimal类型数据的相反数。

5.异常处理机制

在Java中,凡是可能抛出异常的语句,都可以用try ... catch捕获。把可能发生异常的语句放在try { … }中,然后使用catch捕获对应的Exception及其子类。

在使用try…catch捕获处理异常时需要注意:

  • 不要过度使用异常,不能使用异常处理机制来代替正常的流程控制语句
  • 异常捕获时,一定要先捕获小异常,再捕获大异常。否则小异常将无法被捕获
  • 避免出现庞大的try块
  • 避免使用catch(Exception e){}
  • 不要忽略异常

Exception类的常用的几种情况:系统IO异常/运行异常

  1. IOException有:
    EOFException文件已结束异常
    FileNotFoundException文件未找到异常

  2. RuntimeException有:
    IndexOutOfBoundsException索引越界异常;
    ArrayIndexOutOfBoundsException数组索引越界异常;
    ArithmeticException算数条件异常,譬如:整数除零等;
    NullPointerException空指针异常;
    NegativeArraySizeException数组长度为负异常;
    ArrayStoreException数组存储异常,当向数组中存放非数组声明类型对象时抛出;
    SecurityException违背安全原则异常;
    IllegalArgumentException非法参数异常;
    ClassCastException类型强制转换异常。
    ReflectiveOperationException有:
    ClassNotFoundException找不到类异常;
    NoSuchMethodException方法未找到异常;
    NoSuchFieldException找不到属性异常。

  3. 错误类Error:
    一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败
    等,这种错误无法恢复或不可能捕获,将导致应用程序中断。所以不应该试图使用catch块来捕捉Error和不能在throws子句中声明该方法可能抛出Error及其任何子类

多catch语句

多catch语句:简单来说,多个catch语句只有一个能被执行 可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch代码块,然后不再继续匹配。

finally语句

无论是否有异常发生,程序语句最终都要执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloWorld{
public static void main(String[] args) {
try {
process1();
process2();
} catch (UnsupportedEncodingException e) {
System.out.println("Bad encoding");
} catch (IOException e) {
System.out.println("IO error");
} finally {
System.out.println("END");
}
}
}

6.集合

collection接口

Java的集合与数组都是为了处理一类数据,但Java数组也存在很大的缺陷:

  • 数组初始化后大小不可变;
  • 数组只能按索引顺序存取。

Java集合类型分为Collection和Map,它们是Java集合的根接口,这两个接口又包含了一些子接口或实现类。Java的java.util包的collection主要提供了以下三种类型的集合:

  • List接口:一种有序列表的集合,允许存储重复的元素,具体实现的类有ArrayList集合,LinkedList集合,Vector集合;
  • Set接口:一种保证没有重复元素的集合,且没有索引(不能使用普通的for循环遍历集合),具体实现的类有TreeSet集合,HashSet集合,LinkedHashSet集合;
  • Map:一种通过键值(key-value)查找的映射表集合。

List接口

创建List:

1
2
3
4
5
List<String> list = new ArrayList<>(); // 只能放入String类型
List<Integer> list1 = new ArrayList<>(); // 只能放入Integer类型
List<Character> list2 = new ArrayList<>(); // 只能放入Character类型
拓展:根据给定的元素快速创建List
List<Integer> list3 = List.of(1, 2, 5);

collection接口的List接口的共性方法

1
2
3
4
5
在末尾或指定索引添加一个元素:add([index], E)
删除指定索引处的元素值或指定的元素:remove(index) 或 remove(Object)
获取指定索引的元素(不支持负索引):get(index)
更改指定索引对元素(不支持负索引):set(index, element)
获取List大小(包含元素的个数):size()

List接口特点:

  1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
  2. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
  3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

ArrayList集合

对于ArrayList来说,有一个尖括号代表泛型(泛型:也就是装在集合中的所有元素,全部都是统一的什么类型。注意,泛型只能是引用数据类型,不能是基本类型

java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

  1. 创建ArrayList:
1
2
3
ArrayList<String> sites = new ArrayList<>();
ArrayList<Integer> bite = new ArrayList<>();
ArrayList<Float> byd = new ArrayList<>();
  1. ArrayList的常用方法

除了之前提到的共性方法之外,ArrayList还具有如下方法

方法 描述
addAll() 添加集合中的所有元素到arraylist中
clear() 删除集合所有元素
contains() 判断目标元素是否存在
indexOf() 返回目标元素的索引值,不存在返回-1
isEmpty() 判断有序数组是否为空
subList(start, end) 有序数组截取,满足左闭右开,不支持负索引
set(index, element) 对指定位置对元素进行更新
sort(type) 对动态数组进行排序(Comparator.naturalOrder()升序;Comparator.reverseOrder()降序)
toArray() 将arraylist转换为静态数组
toString() 将arraylist转换为字符串
forEach((x)->{…}) 动态数组遍历,跟for-each循环不同

LinkedList集合

java.util.LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。

LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解下

  1. 创建LinkedList
1
2
3
4
// 引入 LinkedList 类
import java.util.LinkedList;
// 创建LinkedList类
LinkedList<E> list = new LinkedList<E>();
  1. 常用方法
方法 描述
addFirst() 指定元素插入此列表的开头
addLast() 指定元素插入此列表的结尾
getFirst() 返回列表第一个元素
getLast() 返回列表最后一个元素
removeFirst() 移除列表第一个元素
removeLast() 移除列表最后一个元素
pop()/push() 移除或添加列表第一个元素
indexOf() 判断目标元素是否存在
isEmpty() 判断是否为空列表

Set接口

Set接口中元素无序,允许有null值,并且会以某种规则保证存入的元素不出现重复。HashSet不是线程安全对,若多个线程同时修改HashSet,其结果并不能保证安全的。

HashSet

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

  1. 创建HashSet
1
2
3
4
5
6
7
8
9
10
11
public class HashSetDemo {
public static void main(String[] args) {
//创建 Set集合
HashSet<String> set = new HashSet<String>();
set.add("cba");
//遍历
for (String name : set) {
System.out.println(name);
}
}
}
  1. 常用方法

HashSet的常用方法此处不会仔细描述,常用到的方法:add,remove,clear,contains,size

LinkedHashSet

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?

在HashSet下面有一个子类java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

演示代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
结果:
bbb
aaa
abc
bbc

Map接口

collection接口的Map接口的共性方法

1
2
3
4
5
map.put(key,value):在末尾添加一组键值对
map.get(key):通过指定的key值获取相应的value值
map.containerKey(key):查询某个Key是否存在
map.containerValue(value):查询某个value是否存在
map.size():获取Map中键值对的元素个数

HashMap

前面已经讲解了List接口下的ArrayList类,接下来我们开始了解Map接口的HashMap类(Map<K, V>是一种键-值映射表,Map中不存在重复的key,因为放入相同的key,只会把原有的key-value对应的value给替换掉。

  1. 创建HashMap类
1
2
3
4
5
6
7
8
9
10
11
12
// Map<键Key的引用数据类型, 值Value的引用数据类型> map = new HashMap<>();
Map<String, Integer> map = new HashMap<>();

// 遍历输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}
// 遍历返回所有 value 值
for(String value: Sites.values()) {
// 输出每一个value
System.out.print(value + ", ");
}
  1. 常用方法
方法 描述
put(k, v) 添加键值对
get(k) 获取key对应的value
remove(key) 删除key对应的键值对
clear() 清空map
size() 获取map大小

关于HashMap的小结:

  • 对Map来说,要遍历key可以使用for-each循环遍历Map实例的keySet()方法返回的Set集合,它包含不重复的key的集合
  • 同时遍历key和value可以使用for-each循环遍历Map对象的entrySet()集合,它包含每一个key-value映射

Iterator迭代器接口

collection接口下有各种各样的集合,不同的集合存储方式不同,相应的集合取值方式也不同,这时就需要Iterator迭代器接口了。
我们要始终坚持使用迭代器Iterator来访问List。Iterator本身也是一个对象,但它是由List的实例调用iterator()方法的时候创建的。Iterator对象知道如何遍历一个List,并且不同的List类型,返回的Iterator对象实现也是不同的,但总是具有最高的访问效率。

Iterator对象有两个方法:boolean hasNext()判断是否有下一个元素,E next()返回下一个元素。因此,使用Iterator遍历List代码如下:

1
2
3
4
5
6
7
8
9
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}
}
}

童鞋可能觉得使用Iterator访问List的代码比使用索引更复杂。但是,要记住,通过Iterator遍历List永远是最高效的方式。并且,由于Iterator遍历是如此常用,所以,Java的for each循环本身就可以帮我们使用Iterator遍历

1
2
3
4
5
6
7
8
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (String s : list) {
System.out.println(s);
}
}
}

6.日期与时间类

我们再来看一下Java标准库提供的API。Java标准库有两套处理日期和时间的API:

  • 定义在java.util这个包里面,主要包括Date、Calendar和TimeZone这几个类(这里面有很多方法已经过时,废弃了,会报出warning);
  • 新的API是在Java 8引入的,定义在java.time这个包里面,主要包括LocalDateTime、ZonedDateTime、ZoneId等(推荐使用这个API)

Date类

Date类目前已经过时废弃了很多方法,仅推荐getTime()方法:把日期对象转换成对应的时间毫秒值

1
2
3
Date date = new Date();
// 1586141801899(十三位数,毫秒级,与js的时间戳相同)
System.out.println(date.getTime());

Calendar

Calendar可以用于获取并设置年、月、日、时、分、秒,它和Date比,主要多了一个可以做简单的日期和时间运算的功能

概念

日历我们都见过,java.util.Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。日历类就是方便获取各个时间属性的。

获取方式

Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:

  1. Calendar静态方法

    public static Calendar getInstance():使用默认时区和语言环境获得一个日历

例如:

1
2
3
4
5
6
7
import java.util.Calendar;

public class Demo06CalendarInit {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
}
}
  1. 常用方法

根据Calendar类的API文档,常用方法有:

  • public int get(int field):返回给定日历字段的值。
  • public void set(int field, int value):将给定的日历字段设置为给定值。
  • public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
  • public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。

Calendar类中提供很多成员常量,代表给定的日历字段:

字段值 含义
YEAR
MONTH 月(从0开始,可以+1使用)
DAY_OF_MONTH 月中的天(几号)
HOUR 时(12小时制)
HOUR_OF_DAY 时(24小时制)
MINUTE
SECOND
DAY_OF_WEEK 周中的天(周几,周日为1,可以-1使用)

  • get/set方法

get方法用来获取指定字段的值,代码使用演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.Calendar;

public class CalendarUtil {
public static void main(String[] args) {
// 创建Calendar对象
Calendar cal = Calendar.getInstance();
// 设置年
int year = cal.get(Calendar.YEAR);
// 设置月
int month = cal.get(Calendar.MONTH) + 1;
// 设置日
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
System.out.print(year + "年" + month + "月" + dayOfMonth + "日");
// 2020年4月6日
}
}

set方法用来设置指定字段的值,代码使用演示:

1
2
3
4
5
6
7
8
9
import java.util.Calendar;

public class Demo07CalendarMethod {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2020);
System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 2020年1月17日
}
}
  • add方法

add方法可以对指定日历字段的值进行加减操作,如果第二个参数为正数则加上偏移量,如果为负数则减去偏移量。代码如:

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.Calendar;

public class Demo08CalendarMethod {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 2018年1月17日
// 使用add方法
cal.add(Calendar.DAY_OF_MONTH, 2); // 加2天
cal.add(Calendar.YEAR, -3); // 减3年
System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 2015年1月18日;
}
}
  • getTime方法

Calendar中的getTime方法并不是获取毫秒时刻,而是拿到对应的Date对象。

1
2
3
4
5
6
7
8
9
10
import java.util.Calendar;
import java.util.Date;

public class Demo09CalendarMethod {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
System.out.println(date); // Tue Jan 16 16:03:09 CST 2018
}
}

小贴士:西方星期的开始为周日,中国为周一。在Calendar类中,月份的表示是以0-11代表1-12月。日期是有大小关系的,时间靠后,时间越大。

从Java 8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:

  1. 本地日期和时间:LocalDateTime,LocalDate,LocalTime;
  2. 带时区的日期和时间:ZonedDateTime;
  3. 时刻:Instant;
  4. 时区:ZoneId,ZoneOffset;
  5. 时间间隔:Duration。
  6. 以及一套新的用于取代SimpleDateFormat的格式化类型DateTimeFormatter。

和旧的API相比,新API严格区分了时刻、本地日期、本地时间和带时区的日期时间,并且,对日期和时间进行运算更加方便。

此外,新API修正了旧API不合理的常量设计:

Month的范围用1~12表示1月到12月;
Week的范围用1~7表示周一到周日。
最后,新API的类型几乎全部是不变类型(和String类似),可以放心使用不必担心被修改。

DateFormat类

java.text.DateFormat 是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。

  • 格式化:按照指定的格式,从Date对象转换为String对象。
  • 解析:按照指定的格式,从String对象转换为Date对象。

常用的格式规则为:

标识字母(区分大小写) 含义
y
M
d
H/h
m
s

format方法

format方法是将Date对象格式化为字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.text.SimpleDateFormat;
import java.util.Date;
/*
把Date对象转换成String
*/
public class Demo03DateFormatMethod {
public static void main(String[] args) {
// 获取当前的日期对象
Date date = new Date();
// 创建日期格式化对象,在获取格式化对象时可以指定风格
DateFormat df = new SimpleDateFormat(""yyyy-MM-dd HH:mm:ss"");
String str = df.format(date);
System.out.println(str); // 2020-04-06 10:23:54
}
}

parse方法

使用parse方法的代码为:把目标String转换成相应的Date对象

1
2
3
4
5
6
7
8
9
10
11
12
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo04DateFormatMethod {
public static void main(String[] args) throws ParseException {
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String input = "2015-11-11 22:18:18" ;
System.out.println(date); // Tue Dec 11 00:00:00 CST 2018
}
}

参考文章


 评论

联系我 | Contact with me

Copyright © 2019-2020 谁知你知我,我知你知深。此恨经年深,比情度日久

博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议