异常:
异常是程序中出现的导致程序崩溃、无法运行的错误。
Java中处理异常的关键字:
try,catch,finally,throw,throws.
使用 try-catch 处理异常的情况:
public void method(){
try{ //try的作用是用来监视可能会出现异常的代码段
//异常处理(三种情况)
} //catch用于对产生的异常进行捕获
catch(异常类型){ //catch应针对于try语句出现的异常类型进行捕获
//异常处理
}
}
应用示例:
import java.io.IOException;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字:");
String num = sc.next();
//对输入的数字递增10
int n = 0;
//try的作用是用来监视(包围)可能会出现异常的代码段
try{
n = Integer.parseInt(num);
}
//catch用于对产生的异常进行捕获,一旦捕获到异常后可以在语句块中处理异常
//catch应针对try语句出现的异常类型进行捕获
//Exception是所有异常的父类,catch时写入Exception可以捕获到所有类型的异常
catch(NullPointerException e){
System.out.println("出现了异常");
//打印异常信息
e.printStackTrace();
//获取异常信息
System.out.println(e.getMessage());
}
//finally表示无论是否发生,始终会执行的代码段
finally{
System.out.println("finally语句");
}
n+=10;
System.out.println("自增10后的值是:"+n);
}
}
Java异常机制:
当try语句块中出现异常,会相应产生一个Exception对象与catch语句中的异常对象进行匹配,如果类型相符,则在catch语句块中处理异常。
Java中异常的体系结构:
说明 :
- Exception是开发人员能够处理的异常
- Error是无法通过try-catch处理的程序中的致命错误
- RuntimeException(运行时异常):表示在程序运行过程中才会出现的异常类型
- 非RuntimeException(非运行时异常):表示程序在编译前就能显示呈现的异常
多重异常捕获(示例):
public class Demo {
/**多重异常捕获 */
public static void main(String[] args) {
String[] array = new String[10];
array[0] = "10";
array[1] = "20";
array[2] = "hello";
try {
for(int i = 0; i < array.length; i++){
System.out.println(array[i].length());
int n = Integer.parseInt(array[i]);
n+=10;
System.out.println(n);
}
}
catch (NumberFormatException e) {
System.out.println("数字格式化异常");
}
catch(NullPointerException e){
System.out.println("空引用异常");
}
catch(Exception e){
System.out.println("其他异常");
}
}
}
异常处理:(关于程序的健壮性)
Exception是所有异常的父类,catch时将其写入可以捕获到所有类型的异常:
catch(Exception e){
}
- finally:无论是否会发生异常,始终都会执行。
- throw:用于抛出并引发异常。
- throws:用于声明异常,提醒方法的调用者,该方法在执行时将会出现问题。
- throws:在抛出非运行时异常时使用。
- Java中所有能捕获的Exception都是通过底层方法借助与throw产生。
注意事项 :
在继承中,重写的方法不能比原方法抛出更多的异常。
日志文件:
使用 log4j 日志文件的步骤:
Step1:添加日志文件所需要的JAR包;
Step2:添加日志的配置文件;
Step3:创建日志对象,使用日志对象的方法记录日志。
日志配置文件(log4j.properties):
### 设置日志文件在控制台中的输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
### 设置日志文件在文件中的输出 ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=Chiang.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
###设置日志的记录级别###
log4j.rootLogger=debug, stdout,file
###log4j.logger.s2jsp.sg.ch04.ArrayIndexExceptionLog4j=info,file
使用方法
Step1:创建日志对象(单例模式),参数表示当前类的字节码文件(运行时类)
Logger logger = Logger.getLogger(类名.class);
Step2:使用日志对象记录类容 info/debug/warn/error
logger.info( );
日志的安全级别:
debug < info < warn < error
附: 生成万年历并记录其查询历史
import java.math.BigDecimal;
import java.util.Random;
import java.util.Scanner;
import javax.xml.crypto.Data;
import org.apache.log4j.Logger;
public class Calendar {
public void typeCalendar(){
//创建日志对象 参数表示当前类的字节码文件(运行时类)
Logger logger = Logger.getLogger(Calendar.class);
System.out.println("-----------------万年历------------------");
Scanner sc = new Scanner(System.in);
System.out.println("请输入年份:");
int year = sc.nextInt();
//使用日志对象记录内容
//可以通过info,debug,warn,error方法记录日志
//普通信息
logger.info("输入的年份是"+year);
System.out.println("请输入月份:");
int month = 1;
try {
month = sc.nextInt();
} catch (Exception e) {
//错误信息
logger.error("月份必须输入数字!");
}
logger.info("输入的月份是"+month);
if(month < 1 || month > 12){
//警告信息
logger.warn("输入了非法的月份:"+month);
return;
}
//总天数
int total = 0;
//计算1900至所输年份间的总天数
for(int i = 1900; i < year; i++){
//判断每一年是否是闰年
if(i%4 == 0 && i%100 != 0 || i%400 == 0){
total+=366;
}
else{
total+=365;
}
}
logger.debug("计算完1900年至"+year+"年间的总天数:"+total+"天");
//月份的总天数
int thisYearDays = 0;
//每月的天数,默认是大月的天数
int days = 31;
//计算所输年份的1月至所输月份间的总天数
for(int i = 1; i <= month; i++){
//判断每个月份的情况
switch(i){
//2月
case 2:
//判断当前年份是否是闰年
if(year%4 == 0 && year%100 != 0 || year%400 == 0){
days = 29;
}
else{
days = 28;
}
break;
//小月
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
//大月
default:
days = 31;
}
//累计每月的天数
if(i < month){
thisYearDays+=days;
}
}
//调试信息
logger.debug(year+"年1月1日至"+(month-1)+"底的天数:"+thisYearDays+"天");
//(累加年份和月份的天数+1)%7计算所输月份第一天的星期数
total+=thisYearDays;
int week = (total+1)%7;
//int week = (total+thisYearDays+1)%7;
//System.out.println(week);
System.out.println("日\t一\t二\t三\t四\t五\t六");
//循环打印\t,控制1号的位置
for(int i = 1; i <= week; i++){
System.out.print("\t");
}
for(int i = 1; i <= days; i++){
System.out.print(i+"\t");
//判断每一天是否是星期六
if((total+i)%7 == 6){
//换行
System.out.println();
}
}
}
/**万年历 */
public static void main(String[] args) {
Calendar cal = new Calendar();
cal.typeCalendar();
}
}
断言:
对一个程序逻辑的某种假设进行测试的方法。
默认情况下,JVM禁用断言,修改JVM参数:-enableassertions
断言的语法:
assert 表达式 : 执行的代码
注:表达式结果必须为boolean类型,如果为false时执行后面的测试代码。