java学习笔记201-219 装箱与拆箱,时间与日历,异常

前言
b站java课程学习笔记整理。
b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程
201. 基本类型包装类
将基本数据类型封装成对象的好处是可以在对象中定义更多的功能方法操纵该数据。
常用的操作之一:用基本的数据类型和字符串之间的转换。
怎么理解呢? 比如 int a =10
; 这里a只是一个变量。 但是如果 Integer i1 = Integer.valueOf(100)
,这样就创建了一个i1
的对象。
这样就可以使用里面的方法了。
举例:我如果想要判断int a
的范围,如果a
单纯的是一个变量,那挺难判断的。
这个时候可以把int a
装箱成Integer a
,调用Integer
中的MIN_VALUE
和MAX_VALUE
就可以找到答案。这就是装箱的优势。
基本数据类型 | 包装类 |
---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
202. Integer
Integer
是int
类的包装类型。
创建Integer
的代码:
package Integer创建对象;
public class GetInteger {
public static void main(String[] args) {
Integer i1 = Integer.valueOf(10);
// toString方法已经重写过了
System.out.println(i1);
Integer i2 = Integer.valueOf("10");
// toString方法已经重写过了
System.out.println(i2);
}
}
203. Int和String的相互转换
注意:之前学过的那个强转的没有Int
和String
的转换!这俩在之前的知识中想要转换,要这么做:
public class IntStringThans {
public static void main(String[] args) {
int a = 10;
String s = "" + a;
System.out.println(s);
}
}
利用字符串拼接的特性。这么搞虽然简单但是有点不专业。第二种方法是使用String
类中的valueOf
构造方法。
代码:
package Int和String的转换;
public class IntStringThans {
public static void main(String[] args) {
int a = 10;
// 第一种方法
String s = "" + a;
System.out.println(s);
// 第二种方法
String s1 = String.valueOf(a);
System.out.println(s1);
}
}
同理,String
转int
也是两种方法。完整代码:
package Int和String的转换;
public class IntStringThans {
public static void main(String[] args) {
int a = 10;
// 第一种方法
String s = "" + a;
System.out.println(s);
// 第二种方法
String s1 = String.valueOf(a);
System.out.println(s1);
System.out.println("---------------");
String s2 = "100";
// 方法一: String- Integer-Int
Integer i = Integer.valueOf(s2);
int x = i.intValue();
System.out.println(x);
//方法二: String-Int
int y = Integer.parseInt(s2); //parse是解析的意思
System.out.println(y);
}
}
总结:
int
转String
用String.valueOf();
String
转int
用Integer.parseInt();
204. 字符串中数据排序
需求:有一串字符串”91 27 46 38 50”, 写程序让他输出成”27 38 46 50 91”
思路:
- 定义一个字符串。
- 把字符串中的数字存储到一个int数组中,然后排序。
- 对
int
数组排序 - 使用
StringBuilder
拼接成字符串 - 输出结果
package 字符串中的数据排序;
import java.util.Arrays;
public class SortString {
public static void main(String[] args) {
String s = "91 27 46 38 50";
String[] strArr = s.split(" ");
int[] arr = new int[strArr.length];
for(int i = 0; i < arr.length; i++){
arr[i] = Integer.parseInt(strArr[i]);
}
Arrays.sort(arr);
// 如何将数组输出为字符串呢?可以自己写一个方法(类似于自己之前写的那个"["+遍历+"]")
StringBuilder sb = new StringBuilder();
sb.append("\"");
for (int j = 0; j < arr.length;j++ ){
sb.append(arr[j]);
if (j!=arr.length-1){
sb.append(" ");
}
}
sb.append("\"");
String result = sb.toString();
System.out.println(result);
}
}
思路分析:字符串不能排序,转换成数组应用Arrays.sort
排序再用StringBuilder
换回来就行了。
注意:最后构建出来的sb
是StringBuilder
类型!要用toString
转换为String
类型。
205. 自动装箱和拆箱
装箱: 把基本的数据类型转换为对应的包装类类型。 拆箱: 把对应的包装类类型转换为基本的数据类型。
自动操作只不过就是简化了手动操作而已。
package 自动装箱与拆箱;
public class Pack {
public static void main(String[] args) {
// 手动装箱
Integer i = Integer.valueOf(100);
// 自动装箱
Integer i1 = 100;
System.out.println("____________________________________________________________-");
//i1.intValue()是拆箱,再加上int赋值给ii叫自动装箱
i1 = i1.intValue()+200;
//自动拆箱+自动装箱,返回的是boxingi1
i1 += 200;
// 报错,因为i2为null,null不可以拆箱,空指针错误。
// Cannot invoke "java.lang.Integer.intValue()" because "i2" is null
// 使用前最好做一个是否为null的判断。
Integer i2 = null;
i2 += 200;
}
}
206. Date
构造方法:
方法名 | 说明 |
---|---|
public Date() |
分配一个无参对象,并初始化,以便他代表它被分配的时间,精确到毫秒 |
public Date(long date) |
分配一个带参对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |
构造方法:
package Date类构造;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
Date a = new Date();
//按理来说应该输出地址值,但是并没有。说明重写了Object.toString方法。
System.out.println(a);
long date = 1000*60*60;
Date b = new Date(date);
System.out.println(b);
}
}
207.Date常用方法
方法名 | 说明 |
---|---|
public long getTime() |
获取从1970年1月1日00:00:00到现在的毫秒值 |
public void setTime(long time) |
设置时间,给的是毫秒值 |
package Date类方法;
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
Date d = new Date();
System.out.println(d.getTime());
System.out.println("距今过去了"+d.getTime()*1.0/1000/60/60/24/365+"年");
Date s = new Date();
System.out.println(s);
long time = 1000*60*60;
s.setTime(time);
System.out.println(s);
long timi = System.currentTimeMillis();
Date x = new Date();
x.setTime(timi);
System.out.println(x);
}
}
208. SimpleDateFormat类
SimpleDateFormat
是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。说人话就是用来规范输出日期的格式的。
- 常用的模式字母:
字母 | 代表 |
---|---|
y |
年 |
M |
月 |
d |
日 |
H |
时 |
m |
分 |
s |
秒 |
- 构造方法:
方法名 | 说明 |
---|---|
public SimpleDateFormat() |
构造一个SimpleDateFormat ,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) |
构造一个SimpleDateFormat ,使用给定的模式和默认的日期格式 |
- 格式化(从
Date
到String
)
public final String format(Date date)
: 将日期格式化成日期/时间字符串。
- 解析(从
String
到Date
)
public Date **parse(String source)
**: 从给定字符串开始解析文本,以生成日期。
利用该类对日期进行格式化和解析:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormat演示 {
public static void main(String[] args) throws ParseException {
// 格式化: 从Date到String
// 无参构造
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat();
String s = sdf.format(d);
System.out.println(s);
//输出:2021/11/3 下午8:33
//带参构造
Date f = new Date();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s1 = sdf1.format(f);
System.out.println(s1);
//解析: 从String到Date
String s2 = "2042-10-20 11:11:11";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date x = sdf2.parse(s2);
System.out.println(x);
}
}
209. 日期工具类
需求:定义一个日期工具类。包含两个方法:八日起转换为指定格式的字符串,把字符串解析为指定格式的日期。然后用测试类测试。
思路:
- 定义日期工具类(
DateUtils
) - 定义一个方法
dateToString
,用于把日期转换为指定格式的字符串。- 返回值类型:
String
- 参数:
Date date
,String format
- 返回值类型:
- 定义一个方法
stringToDate
, 用于字符串解析为指定格式的日期。- 返回值类型:
Date
- 参数:
String s
,String format
- 返回值类型:
- 定义测试类
DateDemo
,调用方法。 - 补充:可以把它当成是一个工具类,构造方法应该私有,成员方法应该静态。
package 日期工具类;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
private DateUtils(){}
//将Date类对象转换成指定格式的字符串
public static String dataToString(Date date,String format){
SimpleDateFormat sdf = new SimpleDateFormat(format);
String s = sdf.format(date);
return s;
}
//将字符串对象解析为Date类对象
public static Date stringToDate(String s, String format) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date d = sdf.parse(s);
return d;
}
}
package 日期工具类;
import java.text.ParseException;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws ParseException {
String format = "yyyy年MM月dd日 HH:mm:ss";
Date d = new Date();
System.out.println(d);
String result = DateUtils.dataToString(d, format);
System.out.println(result);
Date new_date = DateUtils.stringToDate(result,format);
System.out.println(new_date);
}
}
210. Calendar类
Calendar
为某一时刻和一组日历字段之间的转换提供了一些方法,并未操作日历字段提供了一些方法。
Calendar
提供了一个类方法getInstance
用于获取Calendar
的对象,其日历字段已使用当前日期和时间初始化。
示例:
Calendar rightNow = Calendar.gerInstance();
package Canlendar类;
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args) {
Calendar c = Calendar.getInstance(); // 多态的形式得到对象
System.out.println(c); // 注意Month是从0开始的
//Calendar.YEAR表示Calendar的成员变量。
// 这个成员变量用static修饰,可以直接调用。因为是多态,重写了所以值变化了。
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int date = c.get(Calendar.DATE);
System.out.println(year + "," + month + "," + date);
}
}
需要注意的是Calendar.MONTH
是从0开始计数的。
211. Calendar的常用方法
方法名 | 说明 |
---|---|
public int get(int field) |
返回给定日历字段的值 |
public abstract void add(int field, int amount) |
根据日历的规则,将指定的时间量添加或减去给定的日历字段(修改日历的) |
public final void set(int year,int month, int date) |
设置当前日历的年月日(设置日历的) |
package Canlendar类;
import java.util.Calendar;
public class CalendarMethod {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
// 十年后的五天前
// add方法
c.add(Calendar.YEAR,10);
c.add(Calendar.DATE,-5);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int date = c.get(Calendar.DATE);
System.out.println(year + "," + month + "," + date);
// set方法
// 注意这里老师讲错了,set方法月份设置多少就是多少,不需要+1。
c.set(2048,11,7);
int year1 = c.get(Calendar.YEAR);
int month1 = c.get(Calendar.MONTH);
int date1= c.get(Calendar.DATE);
System.out.println(year1 + "," + month1 + "," + date1);
}
}
注意:使用set方法设置的月份设置多少就是多少。老师讲错了。
212. 二月天
需求:获取任意一年的二月有多少天。
思路:
- 键盘录入任意年份。
- 设置日历对象的年月日。
- 年:来自键盘的录入。
- 月:设置为3月,月份是从0开始的,所以设置的值为2.
- 日:设置为1日。
- 3月1日往前推一天就是2月的最后一天
- 输出这一天的数值。
package 二月天;
import java.util.Calendar;
import java.util.Scanner;
public class FebDays {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int yearNum = sc.nextInt();
Calendar c = Calendar.getInstance();
//注意这里month不能设置为3!因为month是从0开始计数!
c.set(yearNum, 2, 1);
c.add(Calendar.DATE, -1);
int day = c.get(Calendar.DATE);
System.out.println(yearNum + "年的二月,一共有" + day + "天");
}
}
213. 异常
就是程序出现了不正常的情况。
异常的体系:
Error
是严重问题,不需要处理。Exception
表示程序本身可以处理的异常。
RuntimeException
:在编译期是不检查的,出现问题后,需要我们回来修改代码。(比如索引越界)
非RuntimeException
:编译期就必须处理的,否则程序不能通过编译,就更不能正常运行了。
214. JVM的默认处理方案
如果程序出现问题,我们没有做任何处理,最终JVM会做默认的处理
- 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台。
- 程序停止执行。
215. 异常处理之try…catch
格式:
try{
可能出现异常的代码;
}catch (异常类名 变量名){
异常的处理代码;
}
程序从try
里面的代码开始执行,出现异常,会自动生成一个异常类对象,该异常对象将会被提交给Java运行时系统。
当Java运行时系统接收到异常对象时,会到catch
中去找匹配的异常类,找到后进行异常的处理。
执行完毕后,程序还可以继续往下执行。
package 异常;
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try{
int[] arr = {1,2,3};
System.out.println(arr[3]);
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
}
}
216. throwable的成员方法
方法名 | 说明 |
---|---|
public String getMessage() |
返回此throwable 的详细消息字符串 |
public String toString() |
返回此可抛出的简短描述 |
public void printStackTrace() |
把异常的错误信息输出在控制台 |
package 异常;
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try{
int[] arr = {1,2,3};
System.out.println(arr[3]); // new ArrayIndexOutOfBoundsException("Index 3 out of bounds for length 3")
}catch(ArrayIndexOutOfBoundsException e){
System.out.println(e.getMessage()); //返回异常的原因
System.out.println(e.toString()); //包含getMessage里面的信息
e.printStackTrace();
}
}
}
217. 编译时异常和运行时异常的区别
编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译。例子:之前那个sdf.parse(s)
。format
和pattern
可能不匹配。所以会有“可能异常”的警告。
运行时异常: 无需显示处理,也可以和编译时异常一样处理。(比如用try...catch
)例子:之前那个索引越界。
所有的RuntimeException
类及其子类都是运行时异常。
218. 异常处理之throws
有的时候用try...catch
处理异常时没有权限,这个时候使用throws
。
throws
并没有真正的处理这个异常,只不过是一种向调用者“甩锅”的行为。最后还得调用者使用try...catch
处理(当然了也可以接着抛,抛给java虚拟机)。
throws
一般处理编译时异常。
219. 自定义异常
只要继承Exception
这个类就可以自定义异常。写的时候要写无参和带参构造。
package 自定义异常;
public class ScoreException extends Exception{
public ScoreException(){}
public ScoreException(String message){
super(message);
}
}
package 自定义异常;
public class checkScore {
public void checkScore(int score) throws ScoreException{
if(score<0||score>100){
throw new ScoreException("你给的分数有误");
}else{
System.out.println("分数正常");
}
}
}
package 自定义异常;
import 老师与学生.继承版.Teacher;
import java.util.Scanner;
public class teecherTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分数:");
int score = sc.nextInt();
checkScore t = new checkScore();
try {
t.checkScore(score);
} catch (ScoreException e) {
e.printStackTrace();
}
}
}
总结:
- 先自定义一个异常,该异常可以有无参构造和带参构造。
- 在需要产生异常的时候,使用
throw
手动的抛出异常(注意方法也要相应的throws
甩锅给调用者) main
函数在使用的时候用try...catch
解决异常(或者接着抛)。throws
和throw
的区别:
throws |
throw |
---|---|
跟在方法声明后面,跟的是异常类名 | 跟在方法体内,跟的是异常对象名 |
表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,由方法体内的语句来处理 |
表示出现异常的一种可能性,不一定发生 | 一定发生了异常 |