public static void main(String[] args) {
int test = test(3,5);
System.out.println(test);
}
public static int test(int x, int y){
int result = x;
try{
if(x<0 || y<0){
return 0;
}
result = x + y;
return result;
}finally{
result = x - y;
}
}
/*
* (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
* (2)如果finally中有return语句,那么try...catch...finally结构
* 一定从finally中的return回去
* (3)如果finally中没有return语句,那么try...catch...finally结构
* 才会从try或catch中的return回去,但是finally值中代码不会影响最终的返回值
*/
public class Exercise2 {
public static void main(String[] args) {
try{
return;
}finally{
System.out.println("finally");
}
}
}
/*
* finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
*/
public class Exercise3 {
{
System.out.println("a");
}
static{
System.out.println("b");
}
Test03(){
System.out.println("c");
}
public static String getOut(){
try{
return "1";
}catch(Exception e){
return "2";
}finally{
return "3";
}
}
public static void main(String[] args) {
System.out.println(getOut());
}
}
/*
* (1)main()执行之前,需要先完成所在类的初始化
* (2)类初始化由两部分代码组成:①静态变量的显式赋值代码②静态代码块
* (3)没有创建对象,不会执行实例初始化相关的代码
* (4)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
* (5)如果finally中有return语句,那么try...catch...finally结构
* 一定从finally中的return回去
*/
public class Exercise4 {
static int i = 0;
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
try{
return ++i;
}finally{
return ++i;
}
}
}
/*
* (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
* (2)如果finally中有return语句,那么try...catch...finally结构
* 一定从finally中的return回去,但是try和catch中的return语句中返回值的表达式会执行。
* (3)如果finally中没有return语句,那么try...catch...finally结构
* 才会从try或catch中的return回去,但是finally值中代码不会影响最终的返回值
*/
public class Exercise5 {
public static void main(String[] args) {
int a = -1;
try{
if(a>0){
throw new RuntimeException("");
}else if(a<0){
throw new IOException("");
}else{
return ;
}
}catch(IOException ioe){
System.out.println("IOException");
}catch(Throwable e){
System.out.println("Throwable");
}finally{
System.out.println("finally");
}
}
}
/*
* (1)throw用于手动抛出异常
* (2)无论是JVM抛出的异常还是throw抛出的异常都需要catch处理
* (3)catch是多分支结构,从上到下按顺序匹配,只会进入第一个匹配上的catch分支
* (4)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
*/
public class Exercise6 {
public static int fun(){
int result = 5;
try{
result = result / 0;
return result;
}catch(Exception e){
System.out.println("Exception");
result = -1;
return result;
}finally{
result = 10;
System.out.println("I am in finally.");
}
}
public static void main(String[] args) {
int x = fun();
System.out.println(x);
}
}
/*
* (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
* (2)如果finally中有return语句,那么try...catch...finally结构
* 一定从finally中的return回去
* (3)如果finally中没有return语句,那么try...catch...finally结构
* 才会从try或catch中的return回去,但是finally值中代码不会影响最终的返回值
*/
public class Exercise7 {
public static int aMethod(int i)throws Exception{
try{
return i / 10;
}catch(Exception ex){
throw new Exception("exception in aMethod");
}finally{
System.out.println("finally");
}
}
public static void main(String[] args) {
try {
aMethod(0);
} catch (Exception e) {
System.out.println("exception in main");
}
}
}
/*
* (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
* 也不管try和catch中是否有return语句,都会执行的部分
* (2)throw用于手动抛出异常
* (3)throws用于将异常抛给调用者处理
*/
给出下面的不完整的方法:
1
2 { int success = connnect();
3 if(success == -1){
4 throw new TimedOutException();
5 }
6 }
TimedOutException 不是一个 RuntimeException,继承于Exception。下面的哪些声明可以被加入第1行完成此方法的声明?( B、C)
A. public void method()
B. public void method() throws Exception
C. public void method() throws TimedOutException
D. public void method() throw TimedOutException
E. public throw TimedOutException void method()
Java把所有的非正常情况分成两种:异常(Exception)和错误(Error),它们都继承Throwable父类。
Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。
通常应用程序无法处理这些错误,因此应用程序不应该试图使用catch块来捕获Error对象。
在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及其任何子类
Exception分为两大类:
运行时异常 [即程序运行时,发生的异常]。
编译时异常 [即编程时编译器检查出的异常,Checked异常]。
所有的RuntimeException类及其子类的实例被称为Runtime异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常。
RuntimeException即程序运行时发生的异常,编译时检测不到这种异常,程序运行后,抛出异常
Runtime异常则更加灵活,Runtime异常无须显式声明抛出,如果程序需要捕获Runtime异常,也可以使用try…catch块来实现
区别一:throw 是语句抛出一个异常;throws 是方法抛出一个异常;
区别二:throws可以单独使用,但throw不能;
区别三:throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但throws可以单独使用,然后再由处理异常的方法捕获
在java中,有一组关键字被用来进行异常的捕捉,它就是try-catch-finally。代码如下所示:
try{
// 尝试执行的可能会抛出异常的代码
}catch(异常类型1 异常的变量名1){
// 当异常抛出时,根据异常的类型和变量名执行对应的catch语句
//catch语句用来捕获异常。
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 不管最终如何,一定要执行的语句,一般做清理类型等收尾善后性质的工作
//finally不是必要出现的
}
此外,还有一组关键字被用来抛出异常,它就是throws/throw关键字:
如果一个方法没有捕获一个可查异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
下面方法的声明抛出一个 RemoteException 异常:
import java.io.*;
public class className{
public void deposit(double amount) throws RemoteException{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
例如,下面的方法声明抛出 RemoteException 和 InsufficientFundsException:
import java.io.*;
public class className{
public void withdraw(double amount) throws RemoteException,InsufficientFundsException{
// Method implementation
}
//Remainder of class definition
}
(1)java.lang.NullPointerException——空指针异常,
出现原因:调用了未经初始化或者不存在的对象。
(2)java.lang.ClassNoFoundException—— 指定类找不到,
出现原因:类的名称和路径加载错误,通常是试图通过字符串来加载某个类时可能引发异常。
(3)java.lang.NumberFormatException——字符串转换为数字异常,
出现原因:字符串数据中包含非数字型字符。
(4)java.lang.IndexOutOfBoundsException——数组下标越界异常,
出现原因:调用的下标超出了数组的范围。
(5)java.lang.IllegalArgumentException—— 方法传递参数错误,
出现原因:在很多j2me的类库中的方法,在一些情况下会引发这样的错误,比如本该是正数的被写成了负数。
(6)java.lang.ClassCastException——数据类型转换异常,
出现原因:强制类型转换类型不匹配时出现此异常。
(7)java.lang.illegalaccessexception——没有访问权限,
出现原因:当程序要调用一个类时,但是当前的方法没有对该类的访问权限。
(8)java.lang.SQLException——SQL异常,
出现原因:在执行sql语句时出现的各种异常。
(9)java.lang.InstantiationException——实例化异常,
出现原因:指不能实例化对象而出现的异常。
(10)java.lang.NoSuchMethodExceptioin—— 方法不存在异常,
出现原因:这个异常出现的原因有两个,第一,缺少某些jar文件;第二,某些jar文件有重复。
(11)java.lang.arithmeticexception——数学运算异常,
出现原因:出现不符合定义的运算,例如除以零。
(1)已知java.lang包下有一个Thread类,这个类有一个静态方法:
public static void sleep(long millis) throws InterruptedException
调用这个方法可以实现程序休眠millis毫秒(1000毫秒=1秒)。
(2)在测试类的main中,在for循环中调用上面的sleep方法,实现新年倒计时10,9,8,…,1,新年到!
public class Exercise16 {
public static void main(String[] args) {
for (int i = 10; i >=1 ; i--) {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("新年到!");
}
}
public class Exercise17 {
public static void main(String[] args) {
int[] arr = new int[Integer.MAX_VALUE];
}
}
/*
设置JVM参数
-verbose:gc
-Xms20M
-Xmx20M
-Xmn10M
-XX:+PrintGCDetails
-XX:SurvivorRatio=8
其中:
Xms:最小堆
Xmx:最大堆
Xmn:新生代的大小
PrintGCDetails:打印GC日志
SurvivorRatio:Eden区和Survivor比例
*/
public class Exercise17 {
public static void main(String[] args) {
ArrayList list=new ArrayList();
//通过不断的创建对象达到OOM
while (true){
list.add(new Object());
}
}
}
(1)声明一个Rectangle矩形类,
(2)在测试类中,创建一个Rectangle矩形对象,调用矩形对象的clone方法克隆出一个新对象,
public class Rectangle implements Cloneable{
private double length;
private double width;
public Rectangle() {
}
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
@Override
public String toString() {
return "Rectangle{" +
"length=" + length +
", width=" + width +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Exercise18 {
public static void main(String[] args) {
Rectangle r1 = new Rectangle(4,2);
System.out.println("r1 = " + r1);
Rectangle r2;
try {
r2= (Rectangle) r1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
r2 = new Rectangle();
r2.setLength(r1.getLength());
r2.setWidth(r1.getLength());
}
System.out.println("r2 = " + r2);
}
}
从键盘输入两个整数,求它们的商。尽量考虑和避免异常,无法避免的使用try…catch处理。
(1)如果用户输入的非整数,使用try…catch处理,并且让用户重新输入
(2)如果用户输入的除数为0,请用户重新输入。
public class Exercise19 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int a ;
while(true) {
try {
System.out.print("请输入被除数:");
a = input.nextInt();
break;
} catch (Exception e) {
input.nextLine();
System.out.println("输入错误,请重新输入!");
}
}
int b ;
while(true) {
try {
System.out.print("请输入除数:");
b = input.nextInt();
if(b==0){
System.out.println("除数不能为0,请重新输入");
}else {
break;
}
} catch (Exception e) {
input.nextLine();
System.out.println("输入错误,请重新输入!");
}
}
System.out.println(a + "/" + b + "=" + a/b);
input.close();
}
}
(1)声明数组工具类ArrayTools(自己写)
(2)运行如下测试类代码,对不同的arr分别测试(不用写,直接用)
public class Exercise20 {
public static void main(String[] args) {
// int[] arr = null;
// int[] arr = {}
// int[] arr = {3,2,1,4};
int[] arr = {1,5,16,28,39};
try {
System.out.println(ArrayTools.toString(arr));
System.out.println("最大值:" + ArrayTools.max(arr));
System.out.println("查找5:" + ArrayTools.binarySearch(arr,5));
} catch (Exception e) {
e.printStackTrace();
}
}
}
ArrayTools工具类代码:
public class ArrayTools {
private static void checkArr(int[] arr){
if(arr == null){
throw new NullPointerException("数组不能为null");
}
if(arr.length == 0){
throw new ArrayIndexOutOfBoundsException("数组不能没有元素");
}
}
public static int max(int[] arr){
checkArr(arr);
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i] > max){
max = arr[i];
}
}
return max;
}
public static boolean fromSmallToLarge(int[] arr){
checkArr(arr);
for (int i = 0; i < arr.length - 1; i++) {
if(arr[i] > arr[i+1]){
return false;
}
}
return true;
}
public static int binarySearch(int[] arr ,int value){
checkArr(arr);
if(!fromSmallToLarge(arr)){
throw new RuntimeException("数组元素不是从小到大");
}
for(int left = 0,right = arr.length-1; left<=right; ){
int mid = left + (right-left)/2;
if(arr[mid] == value){
return mid;
}else if(value > arr[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
return -1;
}
public static String toString(int[] arr){
if(arr == null){
return "";
}
String str = "[";
for (int i = 0; i < arr.length; i++) {
if(i==0){
str += arr[i];
}else{
str += "," + arr[i];
}
}
str += "]";
return str;
}
}
(1)自定义InvalidValueException异常,继承Exception
(2)声明图形工具类GraphicTools
声明public static void printRectangle(int line, int column, char sign)输出line行column列由sign接收的字符组成的矩形,如果line或column<=0则抛出new InvalidValueException(“矩形的长和宽必须是正整数”)异常对象,如果sign字符编码不在[33,126]范围,则抛出new InvalidValueException(“组成矩形的必字符必须是数字字母和基本标点符号”)异常对象。
(3)在测试类中测试调用
public class InvalidValueException extends Exception{
public InvalidValueException() {
}
public InvalidValueException(String message) {
super(message);
}
}
public class GraphicTools {
public static void printRectangle(int line, int column, char sign) throws InvalidValueException {
if(line <=0 || column<=0){
throw new InvalidValueException("矩形的长和宽必须是正整数");
}
if(sign<33 || sign>126){
throw new InvalidValueException("组成矩形的必字符必须是数字字母和基本标点符号");
}
for (int i = 1; i <= line; i++) {
for (int j = 1; j <= column; j++) {
System.out.print(sign);
}
System.out.println();
}
}
}
public class Exercise21 {
public static void main(String[] args) {
try {
GraphicTools.printRectangle(5,5,'*');
} catch (InvalidValueException e) {
e.printStackTrace();
}
}
}
案例:
在一款角色扮演游戏中,每一个人都会有名字和生命值,角色的生命值不能为负数。
要求:当一个人物的生命值为负数的时候需要抛出自定的异常
操作步骤描述:
(1)自定义异常类NoLifeValueException继承RuntimeException
? ① 提供空参和有参构造
? ② 在有参构造中,需要调用父类的有参构造,把异常信息传入
(2)定义Person类
? ① 属性:名称(name)和生命值(lifeValue)
? ② 提供空参构造
? ③ 提供有参构造:使用setXxx方法给name和lifeValue赋值
? ④ 提供setter和getter方法:
在setLifeValue(int lifeValue)方法中,首先判断,如果 lifeValue为负数,就抛出NoLifeValueException,异常信息为:生命值不能为负数:xx;然后在给成员lifeValue赋值。
(3)定义测试类Test08
? ① 使用满参构造方法创建Person对象,生命值传入一个负数。由于一旦遇到异常,后面的代码的将不在执行, 所以需要注释掉上面的代码
? ② 使用空参构造创建Person对象
? 调用setLifeValue(int lifeValue)方法,传入一个正数,运行程序
? 调用setLifeValue(int lifeValue)方法,传入一个负数,运行程序
? ③ 分别对①和②处理异常和不处理异常进行运行看效果
public class NoLifeValueException extends RuntimeException{
public NoLifeValueException() {
super();
}
public NoLifeValueException(String message) {
super(message);
}
}
public class Person {
private String name;
private int lifeValue;
public Person() {
super();
}
public Person(String name, int lifeValue) {
super();
setName(name);
setLifeValue(lifeValue);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLifeValue() {
return lifeValue;
}
public void setLifeValue(int lifeValue) {
if(lifeValue<0){
throw new NoLifeValueException("生命值不能为负数:" + lifeValue);
}
this.lifeValue = lifeValue;
}
}
public class Exercise22 {
public static void main(String[] args) {
try {
Person p = new Person("白蛇",-1);
} catch (Exception e) {
e.printStackTrace();
}
try {
Person p2 = new Person();
p2.setLifeValue(10);
p2.setLifeValue(-10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
1、声明银行账户类Account
(1)包含账号、余额属性,要求属性私有化,提供无参和有参构造,get/set方法(其中balance没有set方法)
(2)包含public void withdraw(double money)取款方法,当取款金额为负数时,抛出Exception,异常信息为“越取你余额越多,想得美”,当取款金额超过余额时,抛出Exception,异常信息为“取款金额不足,不支持当前取款操作”
(3)包含public void save(double money)存款方法,当取款金额为负数时,抛出Exception,异常信息为“越存余额越少,你愿意吗?”
2、编写测试类,创建账号对象,并调用取款和存款方法,并传入非法参数,测试发生对应的异常。
public class Account {
private String id;
private double balance;
public Account() {
}
public Account(String id, double balance) {
this.id = id;
this.balance = balance;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void withdraw(double money) throws Exception {
if(money<0){
throw new Exception("越取你余额越多,想得美");
}
if(money>balance){
throw new Exception("取款金额不足,不支持当前取款操作");
}
balance -= money;
}
public void save(double money) throws Exception {
if(money<0){
throw new Exception("越存余额越少,你愿意吗?");
}
balance += money;
}
}
public class Exercise23 {
public static void main(String[] args) {
Account a = new Account("111111",5000);
try {
a.withdraw(-5000);
} catch (Exception e) {
// e.printStackTrace();
System.err.println("取款失败," + e.getMessage());
}finally {
System.out.println("尝试取款-5000后," + a.getBalance() );
}
try{
a.withdraw(1000);
}catch (Exception e) {
// e.printStackTrace();
System.err.println("取款失败," + e.getMessage());
}finally {
System.out.println("尝试取款1000后," + a.getBalance() );
}
try{
a.withdraw(5000);
}catch (Exception e) {
// e.printStackTrace();
System.err.println("取款失败," + e.getMessage());
}finally {
System.out.println("尝试取款5000后," + a.getBalance() );
}
try{
a.save(-5000);
}catch (Exception e) {
// e.printStackTrace();
System.err.println("存款失败," + e.getMessage());
}finally {
System.out.println("尝试存款-5000后," + a.getBalance() );
}
try{
a.save(5000);
}catch (Exception e) {
// e.printStackTrace();
System.err.println("存款失败," + e.getMessage());
}finally {
System.out.println("尝试存款5000后," + a.getBalance() );
}
}
}
(1)自定义异常类UsernameAlreadyExistsException(用户名已存在异常)继承Exception。
(2)自定义异常类LoginFailException(登录失败异常)继承Exception。
(3)用户类User,包含用户名和密码属性,私有化,提供有参、无参构造器,提供get/set、toString
(4)用户管理类UserManager
? ① 包含如下成员变量:
private static User[] arr ; //存储已经注册的用户
private static int total; //存储实际注册的用户数量
? ② 包含无参构造器
? ③ 包含如下方法:
(5)测试类,实现如下运行效果
--------尚硅谷----------
1、注册
2、登录
3、退出
请选择:1
用户名:song
密码:123456
注册成功
--------尚硅谷----------
1、注册
2、登录
3、退出
请选择:1
用户名:song
用户名已存在
用户名:lin
密码:123456
注册成功
--------尚硅谷----------
1、注册
2、登录
3、退出
请选择:2
用户名:song
密码:123456
登录成功
--------尚硅谷----------
1、注册
2、登录
3、退出
请选择:2
用户名:lin
密码:654321
com.atguigu.homework10.LoginFailException: 登录失败
at com.atguigu.homework10.UserManager.login(UserManager.java:36)
at com.atguigu.homework10.Exercise24.login(TestUser.java:42)
at com.atguigu.homework10.Exercise24.main(TestUser.java:23)
--------尚硅谷----------
1、注册
2、登录
3、退出
请选择:3
public class UsernameAlreadyExistsException extends Exception {
public UsernameAlreadyExistsException() {
}
public UsernameAlreadyExistsException(String message) {
super(message);
}
}
public class LoginFailException extends Exception {
public LoginFailException() {
}
public LoginFailException(String message) {
super(message);
}
}
public class User {
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class UserManager {
private static User[] arr ;
private static int total;
public UserManager(){
arr = new User[5];
}
public void checkUsernameExists(String username) throws UsernameAlreadyExistsException {
for (int i = 0; i < total; i++) {
if(username.equals(arr[i].getUsername())){
throw new UsernameAlreadyExistsException("用户名已存在");
}
}
}
public void add(User user){
if(total>=arr.length){
User[] newArr = new User[arr.length + (arr.length>>2)];
for (int i = 0; i < total; i++) {
newArr[i] = arr[i];
}
arr = newArr;
}
arr[total++] = user;
}
public void login(User user) throws LoginFailException {
for (int i = 0; i < total; i++) {
if(user.getUsername().equals(arr[i].getUsername()) && user.getPassword().equals(arr[i].getPassword())){
return;
}
}
throw new LoginFailException("登录失败");
}
}
public class Exercise24{
private static Scanner input = new Scanner(System.in);
private static UserManager um = new UserManager();
public static void main(String[] args) {
boolean flag = true;
while(flag){
System.out.println("--------尚硅谷----------");
System.out.println("\t\t1、注册");
System.out.println("\t\t2、登录");
System.out.println("\t\t3、退出");
System.out.print("\t请选择:");
int select = input.nextInt();
switch (select){
case 1:
regist();
break;
case 2:
login();
break;
case 3:
flag = false;
}
}
input.close();
}
private static void login() {
System.out.print("用户名:");
String username = input.next();
System.out.print("密码:");
String password = input.next();
User user = new User(username,password);
try {
um.login(user);
System.out.println("登录成功");
} catch (LoginFailException e) {
e.printStackTrace();
}
}
private static void regist(){
String username;
while(true) {
System.out.print("用户名:");
username = input.next();
try {
um.checkUsernameExists(username);
break;
} catch (UsernameAlreadyExistsException e) {
System.err.println(e.getMessage());
input.nextLine();
}
}
System.out.print("密码:");
String password = input.next();
User user = new User(username,password);
um.add(user);
System.out.println("注册成功");
}
}