菜鸟学习笔记:Java其他常用类
基本数据类型包装类
通过之前的学习我们知道Java中有基本数据类型和引用数据类型,分别对其也进行了讲解,然而在实际使用中有时候需要将基本数据类型转化为对象,以便操作,举例说明:
我们对于一个方法,无论输入什么数据类型都可以打印出来,可以这样写:
public class test1 {
public static void Print(Object obj) {
System.out.println("输入的是:"+obj);
}
public static void main(String[] args) {
Print(123);
Print(true);
Print("abc");
Print(new Object());
}
}
程序会打印:
输入的是:123
输入的是:true
输入的是:abc
输入的是:java.lang.Object@2a139a55
这时我们会疑惑为什么Object对象可以接收基本数据类型?这就是包装类起了作用,用Object类型变量接收基本数据类型变量时,Java会通过自动装箱技术将基本数据类型转化为包装类进行存储,而在打印时用通过包装类本身的方法将其自动拆箱,变成基本数据类型进行输出。
对自动装箱和自动拆箱我们同样用一个小例子来说明:
public class test2 {
public static void main(String[] args) {
//自动装箱
Integer a = 1000;
//这段代码编译时编译器会自动帮我们改成
//Integer a = new Integer(1000);
//这就是自动装箱技术,再加上Java多态的特性,代码最终可改为
//Object a = new Integer(1000);
//自动拆箱
int c = new Integer(1000);
//这段代码编译时编译器会自动帮我们改成
//int c = new Integer(1000).intValue();
//通过该方法将数据自动变为int类型
}
}
对于8种基本数据类型,Java都有对应的包装类与之对应,对应类如下表。
基本数据类型 | 包装类 |
---|---|
int | Integer |
char | Character |
long | Long |
double | Double |
float | Float |
short | Short |
boolean | Boolean |
byte | Byte |
包装类除了对基本类型的封装,还提供了不同类型之间的转化方式、每个类型可以表示的范围以及一些常用方法。
对包装类还要注意的就是它重写了Object的equals()方法,在判断时不用为同一对象,只要值相同就为True,这一点在我的另一篇博客中有讲解,链接。
时间处理和文件处理相关类
Date时间类
它是标准Java类库中的一个类,实例化后表示一个特定的瞬间。例:
public static void main(String[] args) {
Date d = new Date();
//获取当前时间,生成一个date对象等价于
//Date d = new Date(System.currentTimeMillis());
//System.currentTimeMillis()函数会返回从1970年1月1日到现在的毫秒数,结果为long类型。
System.out.println(d);
//打印当前时间,格式为Tue Nov 03 22:30:23 CST 2020
System.out.println(d.getTime);
//将date转化为从1970年1月1日到现在的毫秒数
}
SimpleDateFormat
Date类得到的时间格式固定,对于中国人,尤其是像作者这种英文困难户很不友好,所以对于时间类另一个重要点就是对其进行不同格式的转化并输出。SimpleDateFormat就很好的解决了这个问题。
SimpleDateFormat的使用非常简单,大家看一个实例应该就会了:
public static void main(String[] args) throws ParseException {
//throws ParseException是我们接触的第一个异常,
//下一篇文章会详细讲述Java的异常机制
SimpleDateFormat dFormat = new SimpleDateFormat("YYYY年MM月dd日 hh:mm:ss");
//定义输出格式,Y代表年,M代表月,d代表日,h代表时,m代表分,
//s代表秒,有几个字符代表占多少位数字,不够时用0填补
Date d = new Date();
String timeString = dFormat.format(d);
//按照格式化字符串对Date类进行转化
System.out.println(timeString);
//打印2020年11月03日 10:52:09
String timeString2 = "2020-11-5";
//需要转为时间的字符串
DateFormat dFormat2 = new SimpleDateFormat("Y-MM-d");
//定义输入格式
Date d2 = dFormat2.parse(timeString2);
System.out.println(d2);//打印Sun Dec 29 00:00:00 CST 2019
}
SimpleDateFormat中定义了以下模式字母(所有其他字符 ‘A’ 到 ‘Z’ 和 ‘a’ 到 ‘z’ 都被保留):
字母 | 日期或时间元素 | 表示 | 示例 |
---|---|---|---|
G | Era | 标志符 | Text |
y | 年 | Year | 1996;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 |
k | 一天中的小时数(1-24) | Number | 24 |
K | am/pm 中的小时数(0-11) | Number | 0 |
h | am/pm 中的小时数(1-12) | Number | 12 |
m | 小时中的分钟数 | Number | 30 |
s | 分钟中的秒数 | Number | 55 |
S | 毫秒数 | Number | 978 |
z | 时区 | General time zone | Pacific Standard Time; PST; GMT-08:00 |
Z | 时区 | RFC 822 time zone | -0800 |
Calendar日历类
相对于Date来说运用较少,主要可以用来获取周,大家做了解即可,我直接举例说明:
public static void main(String[] args) {
Calendar oCalendar = new GregorianCalendar();
oCalendar.set(Calendar.YEAR, 2020);//设置年月日
oCalendar.set(Calendar.MONTH, 4);
oCalendar.set(Calendar.DAY_OF_MONTH, 20);
Date date = oCalendar.getTime();//转为date类型
SimpleDateFormat dFormat = new SimpleDateFormat("YYYY年MM月dd日");
String timeString = dFormat.format(date);
System.out.println("今天是" + timeString + "星期" + oCalendar.DAY_OF_WEEK + "你在干嘛那?");
//今天是2020年05月20日星期7你在干嘛那?
}
个人感觉应该不难理解,我就不做过多解释了。对于日历类其他功能详见API文档,个人找了一篇:链接。
文件类
文件的读写是编成中的常用操作,Java对文件的读取需要借助IO流来进行,对于IO流的概念我们在中级篇中详细介绍,这里主要介绍下File(java.io.File)类,它是文件和路径名的抽象表示形式,可以通过File对象访问文件的属性。举例说明:
先看文件结构
执行如下代码
public static void main(String[] args) {
File file1 = new File("d:/testFile/haha.txt"); //创建对象指向已存在的文件
System.out.println(file1.exists()); //判断文件是否存在true
System.out.println(file1.isFile());//判断是否为文件true
System.out.println("-------------------------------");
File file2 = new File("d:/testFile/haha1.txt");
System.out.println(file2.exists()); //判断文件是否存在false
System.out.println("---------------文件夹----------------");
File directory1 = new File("d:/testFile"); //创建对象指向已存在的文件夹
File directory2 = new File("d:/testFile/aaa/bbb/ccc");
System.out.println(directory2.exists()); //判断文件夹是否存在false
directory2.mkdirs();//创建文件夹
//(注意mkdir也会创建文件夹,但不同点是如果路径不存在mkdirs()
//会创建所有路径,而mkdir()会报错)
System.out.println(directory2.exists()); //true
System.out.println(file2.isDirectory()); //true
File file3 = new File(directory1, "haha.txt");创建对象指向已存在的文件夹下的文件
System.out.println(file3.exists()); //true
}
程序结果:
true
true
-------------------------------
false
---------------文件夹----------------
false
true
true
true
执行完程序后的文件结构:
File类对于文件操作的方法还有很多,这里就不一一列举,对于时间和文件类的相关内容没有什么需要理解的地方,主要就是一些类和方法的调用,建议大家不用死记硬背,先搞明白它是怎么个原理,然后在需要的时候去查阅API就行。附上文件操作api文档:链接。
异常机制
异常的概念
对异常机制直接上概念大家估计有可能像当年的我一样陷入懵逼,状态,我们先通过一段伪代码来带入。
对于文件读写操作大家都不陌生,但需要考虑的意外情况也很多,拿文件复制来看,比方说:
- 文件是否存在
- 磁盘空间是否足够
- 复制过程中如果意外中断怎么办
如果写成伪代码就会这样:
public boolean Copy(File file){
//复制文件逻辑
}
public boolean SpaceIsEnough(){
//判断磁盘空间是否充足的逻辑
}
public static void main(String[] args) {
File file = new File("c://aaa");
if(file.exists()){
if(SpaceIsEnough()){
boolean isSuccess = Copy(file);
if(isSuccess){
System.out.println("文件复制成功!");
} else {
System.out.println("发生中断,请重新复制!");
}
}else{
System.out.println("磁盘空间不足!");
}
} else {
System.out.println("文件不存在!");
}
}
可以看到其实实际复制的操作并没多少,但判断意外的逻辑非常多,这大大加大了编成的难度,所以异常机制帮我们解决了这个问题。
程序的意外一般分为两类(概念性的东西借鉴了以下其他博客,链接):
错误(Error) 一般是指合理的应用程序中不应该出现的严重问题,如内存溢出、虚拟机错误、栈溢出等问题。这类错误一般与硬件有关,与程序本身无关,通常由系统进行处理,程序本身无法捕获和处理。
异常(Expection) 是指程序本身可以捕获并且可以处理的问题,比如数组越界、除数为零等。它又可以细分为运行时异常和检查型异常。
- 运行时异常(不受检异常RuntimeException) 表示JVM在运行期间可能出现的错误。编译器不会检查此类异常,并且不要求处理异常,比如用空值对象的引用、数组下标越界。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。
- 非运行时异常(受检异常,除RuntimeException外其他异常) 编译器会检查此类异常,如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,要么使用try-catch捕获,要么使用throws语句抛出,否则编译不通过。
下图是Java中异常类的继承关系:
在编程过程中遇到异常是家常便饭,对于一些常见异常产生原因的了解非常重要,本人找了一篇博客对常见异常做了总结,大家在编成过程中遇到相应异常可以拿来查阅,当然也可以直接搜索异常,网上绝大多数都有解决方法,链接。这里限于篇幅就不做太多赘述了,但不做赘述不代表它不重要。
Java异常处理
在程序中程序员如果觉得一段程序在运行过程中可能会出现错误,可以通过Java为我们提供的API对异常进行捕获,并在发生异常后进行相应的处理,也可以对外抛出异常,由调用该段程序的地方再选择捕获或者抛出,抛出异常需要在方法定义处throws Exception ,其中 Exception可以是具体的异常类型名称,也可以是可以代表所有异常的Exception关键字。捕获异常需要采用try-catch语句,其中被catch的e同样可以是具体的异常,也可以是可以代表所有异常的Exception类异常。
try-catch语句还有一种扩展方式叫try-catch-finally语句,它和try-catch语句的不同之处在于finally模块的代码无论异常是否发生都会执行,通常用于处理善后清理工作(比如关闭数据库链接等的操作)。
下面举例来说明:
public static void Expcetion() throws InterruptedException{
Thread.sleep(-1000);
//非运行时异常(受检异常),需要我们自行处理,否则编译不通过,在函数中我们
//采用对外抛出的处理方法throws Exception
}
public static void main(String[] args) {
int i = 1/0;
//运行时异常(不受检异常),我们不需要对其进行任何处理,编译时编译器会自动检测并抛出
try {
Expcetion();
FileReader fileReader = new FileReader("c:/aaa");//非运行时异常(受检异常),需要我们自行处理
//由于该函数抛出了异常,所以在调用时需要对该异常进行处理,
//这里采用捕获的方法处理
} catch (InterruptedException e) {//Expcetion()中的异常
//catch语句中是异常发生时的处理方法,e代表异常对象。
e.printStackTrace();//跟踪异常发生时堆栈的内容
System.out.println("异常发生了!");//new FileReader("c:/aaa")中的异常
} catch (FileNotFoundException e1) {//对不同异常采用不同处理方法
e1.printStackTrace();
} finally {
fileReader.close();//是否发生异常都要关闭fileReader
}
}
注意:
- 即使在try或catch语句中使用return,finally中的代码块也会执行。
执行顺序: 1.try-catch 2.inally 3.return - 在方法重写过程中,子类声明的异常范围不能超过父类。以下情况就不合规:
public class A {
private void name() throws IOException{}
}
public class B extends A {
private void name() throws Exception{}
}
自定义异常
throw关键字
Java异常类对象除了在程序执行过程中出现异常时由系统自动生成并抛出,也可以根据需要手动创建并抛出。也就是说我们可以手动写一个异常,从外部可以对其捕获,这个功能可通过throw关键字实现。例:
public boolean Copy(File file){
//复制文件逻辑
}
public static void main(String[] args) {
File file = new File("c://aaa");
if(file.exists()){
Copy(file)
} else {
try {
throw new FileNotFoundException("文件没找到");
//手动生成异常,生成后就需要外程序进行处理
} catch (Exception e) {
e.printStackTrace()
}
}
}
自定义异常类
在程序中,可能会遇到任何标准异常类都没有描述清楚的问题,这种情况下可以创建自己的异常类。来解决,例:
public class MyException extends Exception {
//定义异常需要继承Exception类
public MyException() {}
public MyException(String message) {
super(message);
}
}
class Test{
void TestMethod() throws MyException{}//定义后方法就可以抛出自定义异常
public static void main(String[] args) {
try {
new Test().TestMethod();
} catch (MyException e) {
e.printStackTrace();
}
}
}
后语
至此整个Java基础篇就讲完了,回收看这些博客还挺有成就感的 ≧◠◡◠≦。本人也是第一次写博客,能感觉到有的地方确实不好总结,难免有些地方说的不清楚。希望大家看的时候要是有问题可以指出来,大家相互纠错嘛。
零基础的同学学到这里应该对Java已经有了初步了解,个人觉得这个时候大家不用急着继续往下走,找一些基础类的项目来做做,体会下前面讲的知识点是怎么运用的,然后回过来在看肯定有不一样的感觉,还是那句话,代码是练出来的,光看不练肯定是学不会的。
对于项目个人Swing桌面小程序非常适合这个阶段来联系。我在B站找了一个不错的小项目,学生成绩管理。大家不喜欢视频也可以直接在csdn上搜索,也有相关的教程。
过段时间我会继续给大家带来Java提高篇的博客,希望大家能继续关注哦!