异常是程序在运行过程中出现的特殊情况。
Throwable ,可抛出的,一切错误或异常的父类,位于java.lang包中。分为 Error,JVM、硬件、执行逻辑错误,不能手动处理;Exception,程序在运行和配置中产生的问题,可处理。其中 Exception 可分为 RuntimeException ,运行时异常,可处理,可不处理;CheckedException,检查异常,必须处理。
异常按照方法的调用链反向传递。throw, 抛出异常;throws,声明异常,可声明多个。
public class Test3 {
public static void main(String[] args) {
/**
* method1 start
* method2 start
* method3 start
* java.lang.Exception: 有妖气
* method2 end
* method1 end
*/
method1();
}
public static void method1() {
System.out.println("method1 start");
method2();
System.out.println("method1 end");
}
public static void method2() {
System.out.println("method2 start");
try {
method3();
// 不会执行
System.out.println("method2 try");
} catch (Exception e) {
System.out.println(e.fillInStackTrace());
}
System.out.println("method2 end");
}
// 声明异常
public static void method3() throws Exception {
System.out.println("method3 start");
// 抛出异常
throw new Exception("有妖气");
// System.out.println("method3 end");
}
}
常见运行异常。
// 1 java.lang.ArithmeticException 算术异常
int i = 10 / 0;
// 2 NullPointerException 空指针异常
String a = null;
System.out.println(a.length());
// 3 NumberFormatException 数字转换异常
System.out.println(Integer.valueOf("a"));
// ClassCastException 类型转换异常
Object b = "a";
Integer i2 = (Integer)b;
// ArrayIndexOutOfBoundsException 数组越界
int[] c = new int[2];
System.out.println(c[5]);
try{ } catch{ } catch{ } finally{ } 异常处理结构,遵循从子( 小 )到父( 大 )的顺序,父类异常在最后。try,可能出现异常的代码;catch(Exception e),异常处理的相关代码;finally,无论是否出现异常,都需执行的代码结构,常用于释放资源。
// 1
try {
int i = 10 / 0;
} catch (ArithmeticException e) {
//为了更精确的报错信息,我们应该使用更精确的异常类型
System.out.println(e);
}
// 2
try {
int i = 10 / 0;
} catch (ArithmeticException e) {
e.printStackTrace();
} catch (NullPointerException e) {
System.out.println("不是对应的异常不会执行");
e.printStackTrace();
} catch (Exception e) {
System.out.println("子类执行了,父类不会执行");
e.printStackTrace();
} finally {
System.out.println("总是会执行");
}
// 3
try {
int i = 10 / 0;
} finally {
System.out.println("后面的代码不会执行");
}
System.out.println("结束");
自定义异常。
自定义异常需继承 Exception 或 Exception 的子类,代表特定问题。
public class AgeException extends RuntimeException {
public AgeException(String message) {
super(message);
}
}
public class SexException extends Exception {
public SexException() {
super("没有性别");
}
public SexException(String message) {
super(message);
}
}
public class Person {
private String id;
private String name;
private String sex;
private int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String id, String name, String sex, int age) {
super();
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
// 声明异常
public void setSex(String sex) throws SexException {
if (sex.equals("男")
|| sex.equals("女")) {
this.sex = sex;
} else {
throw new SexException("性别问题");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0
&& age < 120) {
this.age = age;
} else {
// 只要是继承与运行时异常的,都不需要申明
// 不申明的异常不会有红线提示
throw new AgeException("年龄范围");
}
}
}
public class Test {
public static void main(String[] args) {
Person s = new Person();
try {
s.setSex("k");
} catch (SexException e) {
e.printStackTrace();
}
System.out.println("运行1");
// 没有抛出异常 ,出错后程序直接结束
s.setAge(130);
System.out.println("运行结束");
}
}
带有异常声明的方法重写,方法名、参数列表、返回值类型必须和父类相同,子类的访问修饰符合父类相同或是比父类更宽,子类中的方法,不能抛出比父类更宽泛的异常。
简单的注册,登陆抛出异常系统。
// 用户类
public class User {
private String account;
private String name;
private int age;
private String password;
public User() {
// TODO Auto-generated constructor stub
}
public User(String account, String name, int age, String password) {
super();
this.account = account;
this.name = name;
this.age = age;
this.password = password;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
// 自定义登陆异常
public class LoginException extends Exception {
public LoginException() {
super();
}
public LoginException(String message) {
super(message);
}
}
// 自定义注册异常
public class RegisterException extends Exception {
public RegisterException() {
super();
}
public RegisterException(String message) {
super(message);
}
}
// 登陆 、注册 接口类 , 带异常声明的方法
public interface UserServices {
void login(String account, String password) throws LoginException;
void register(String account, String password, String rePassword) throws RegisterException;
}
// 实现 登陆、 注册接口类 ,做一些存储和判断等
public class UserServiceImpl implements UserServices {
private Map<String, User> userMaps = new HashMap<String, User>();
public UserServiceImpl() {
User u1 = new User("123", "张三", 1, "123");
User u2 = new User("124", "李四", 2, "124");
User u3 = new User("124", "王五", 3, "124");
userMaps.put("123", u1);
userMaps.put("124", u2);
userMaps.put("125", u3);
}
@Override
public void login(String account, String password) throws LoginException {
// TODO Auto-generated method stub
Set<String> keys = userMaps.keySet();
for (String string : keys) {
if (account.equals(string)) {
User u = userMaps.get(string);
if (u.getPassword().equals(password)) {
System.out.println("欢迎你 " + u.getName());
return;
} else {
throw new LoginException("密码错误, 请重新输入");
}
}
}
throw new LoginException("没有这个账户, 请注册");
}
@Override
public void register(String account, String password, String rePassword) throws RegisterException {
Set<String> keys = userMaps.keySet();
for (String string : keys) {
if (string.equals(account)) {
throw new RegisterException("该账户已存在, 请重新输入");
}
}
if (!password.equals(rePassword)) {
throw new RegisterException("输入密码不一致,请重新输入");
}
System.out.println("注册成功!");
User u = new User(account, "新注册", 0, password);
userMaps.put(account, u);
}
}
// 测试程序
public class Test1 {
public Test1() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
UserServices us = new UserServiceImpl();
Scanner input = new Scanner(System.in);
while (true) {
try {
System.out.println("请输入 1,注册 2,登陆 0 退出");
int chose = input.nextInt();
if (chose == 1) {
System.out.println("用户名");
String account = input.next();
System.out.println("密码");
String password = input.next();
System.out.println("再次输入密码");
String rePassword = input.next();
us.register(account, password, rePassword);
} else if (chose == 2) {
System.out.println("用户名");
String account = input.next();
System.out.println("密码");
String password = input.next();
us.login(account, password);
} else if (chose == 0) {
break;
} else {
System.out.println("无法识别 请重新输入");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}