java3-流程控制&异常

1,分支结构

1.1,if

  • 单分支

    • {}可以省略不写;但如果省略,if的执行代码只包含之后的一句代码,其余缩进中的代码相当于顺序结构进行执行
    if(条件表达式1){
        执行代码1;
    }
    if(条件表达式2){
        执行代码2;
    }
    
    public class TestIf01{
    	public static void main(String[] args){
    		int num1 = 1;
    		int num2 = 1;
    		int num3 = 5;
    		
    		int sum = 0;
    		sum+=num1;
    		sum+=num2;
    		sum+=num3;
    		System.out.println(sum);
    		
    		if(sum>=14)
    			System.out.println("一等奖");
    			System.out.println("真幸运");
    		if((sum>=10)&&(sum<14))
    			System.out.println("二等奖");
    		}
    	}
    
  • 多分支

    if(条件表达式1){
        执行代码1;
    }else if(条件表达式2){
        执行代码2;
    }else{
        执行代码3;
    }
    
  • 双分支

    if(条件表达式){
        执行代码1;
    }else{
        执行代码2;
    }
    
    //等价于
    条件表达式?执行代码1:执行代码2
    
    /*
    if(sum>10){
    	System.out.println("一等奖");
    }else{
    	System.out.println("二等奖");
    }
    */
    System.out.println(sum>10?"一等奖":"二等奖");
    
  • 嵌套

    if(条件表达式){
        if(条件表达式){
            执行代码1;
        }
    }else{
        执行代码2;
    }
    

1.2,switch

switch(){
    case * : 执行代码1;
    case * : 执行代码2;
    default : 执行代码3;
}
/*
1,switch后面()中表达式返回的结果的类型可以是:byte,short,int,char,String,枚举类型
2,()中所获得的值会依次跟case后面的值比较,如果匹配成功,就执行相应:后面所有的代码
3,为了防止代码穿透,在每个分支后加上break关键词
4,default类似if中的else,所有分支都不走会执行default的代码
5,default可以写在switch{}中的任意位置,执行到default处就会执行相应的代码,其后也可以加上break,建		议将default放在最后
6,如果相邻的分支的执行代码逻辑相同,可以只保留一个分支的执行代码,其他都不写
7,swich分支与if分支的区别:
	表达式等值判断:if,switch都合适;
	表达式区间判断:if合适
8,switch的应用场合:等值判断,且情况比较少
*/
switch(){
    case * : 执行代码1;break;
    case * : 执行代码2;break;
    default : 执行代码3;
}
public class TestSwitch01{
	public static void main(String[] args){
		//1,定义成绩
		int score = 97;
		
		//2,根据成绩判断学生的等级
		switch(score/10){
			//default : System.out.println("成绩错误或者太垃圾了!");break;
			case 9 : 
				System.out.println("A级");
				//break;
			case 8 : System.out.println("B级");//break;
			case 7 : System.out.println("C级");//break;
			case 6 :
			case 5 :
			case 4 :
			case 3 :
			case 2 :
			case 1 :
			case 0 : System.out.println("垃圾!");//break;
			default : System.out.println("成绩错误或者太垃圾了!");
		}
	}
}

2,循环结构

2.1,while

条件初始化;
while(条件判断){
    循环体;
    条件更新;
}
/*
1,在判断条件满足的情况下,执行循环体以及条件更新中的代码
2,循环只是提高了编写代码的效率,但是底层执行依然是重复执行的
3,循环四要素:条件初始化,条件判断,循环体,条件更新
4,条件初始化,条件判断,条件更新的变量是一致的
*/
public class TestWhile01{
	public static void main(String[] args){
		int num = 1;	//条件初始化
		int sum = 0;
		while(num<=5){	//条件判断
			sum += num;	//循环体
			num++;		//条件更新
		}
		System.out.println(sum);
	}
}

2.2,do while

条件初始化;
do{
    循环体;
    条件更新
}while(条件判断);	//;不要忘了

/*
1,do while先执行再判断;while先判断再执行
2,使用do while的场合:有些场景必须先获取一个结果,根据结果判断是否要循环,此时要用do while
*/

2.3,for

for(条件初始化;条件判断;条件更新){
    循环体;
}
/*
1,条件变量的作用域:离变量最近的{}
2,for的格式很灵活:
	for(;;){},这样是死循环,while(ture)效果相同
	
	int i = 1;
	for(;i<=100;){
	i++;
	},这样和while类似
3,循环可以分为两大类:
	当型:while(){}	for(){}
	直到型:do()while{}
4,while,do-while,for的效率是一样的
*/
public class TestFor{
	public static void main(String[] args){
		int sum = 0;
		for(int i=1; i<=100; i++){
			sum+=i;
		}
		System.out.println(sum);
		//System.out.println(i);	//超出i的作用域,编译报错
	}
}
public class TestFor{
	public static void main(String[] args){
		int sum = 0;
		int i;
		for(i=1; i<=100; i++){
			sum+=i;
		}
		System.out.println(sum);
		System.out.println(i);
	}
}

3,关键字

3.1,break

默认停止最近的循环。

public class TestBreak{
	public static void main(String[] args){
		int sum = 0;
		for(int i=1; i<=100; i++){
			sum += i;
			if(sum>=100){
				System.out.println(sum);
				System.out.println(i);
				break;
			}
		}
	}
}

break加标签,结束预设的循环

  • 标签必须放在希望跳出的最外层循环之前,并且必须紧跟一个冒号。
public class TestBreak02{
	public static void main(String[] args){
		outer1:		//定义标签结束的位置
			for(int i=1; i<=100; i++){
				System.out.println(i);
				while(i==30){
					//break;
					break outer1;	//根据标签结束循环
				}
		}
	}
}
  • 事实上,可以将标签应用到任何语句中,甚至可以应用到if语句或者块语句中。因此,如果希望使用一条goto语句,并将一个标签放在想要跳到的语句块之前,就可以使用break语句!当然,并不提倡使用这种方式。另外需要注意,只能跳出语句块,而不能跳入语句块。
    • 此时,break后面跟的标签必须在if语句或者块语句之前。

3.2,continue

停止本次循环,继续下一次循环。

public class TestContinue{
	public static void main(String[] args){
		for(int i=1; i<=100; i++){
			if (i%6!=0){
				continue;
			}
			System.out.println(i);
		}
	}
}

也可以加标签

public class TestContinue02{
	public static void main(String[] args){
		outer1:
			for(int i=1; i<=100; i++){
				while(i==30){
					continue outer1;	//30被跳过,没有输出
				}
				System.out.println(i);
			}
	}
}

3.3,return

结束当前正在执行的方法

public class TestReturn{
	public static void main(String[] args){
		for(int i=1; i<=100; i++){
			while(i==30){
				return;
			}
			System.out.println(i);
		}
	}
}

4,异常

4-1,基本用法和基本概念:

  • 基本用法-try-catch
try{
} catch (Exception e){
  //e的有效范围在其后的{}中
  e.printStackTrace();
}
  • 基本概念:
    • 异常也是java的类
    • 所有异常的父类是Throwable
    • Throwable的继承关系,IDEA中可以查看:
    • java有两类异常:
      • Error:不可修复的(Catch无法补救),应用程序无解决方案的异常,如栈溢出,内存不足、磁盘不足等资源不够用(应该由java虚拟机平台处理,但是平台处理不了导致的异常)
      • Exception:可修复的(Catch可补救),和应用程序相关的异常,如除零、索引超出等
    • 按照处理的方式不同,Exception异常又可以分为:
      • checked exception:语法必须要用try-catch(自己解决)或者throws(抛给调用者解决)语句处理的异常(该类异常必须用语法处理,否则编译都无法通过)。
      • unchecked exception:语法不要求一定要用try-catch或者throws语句处理的异常(该类异常可以不处理,编译可以通过,但是出问题了程序依旧会中断报错)。
        • ErrorRuntimeExceptionunchecked exception的父类,一般使用RuntimeException
    • 异常是用来处理程序错误的,不要用异常做正常逻辑的程序跳转,因为异常的创建和处理都很耗费资源。

4-2,异常的处理方法1:再抛出-thorws

  • 抛出别的代码抛过来的异常
    • 可以使用throws关键字,抛出一个异常
    • 抛出的异常类型,可以是实际异常的父类或者本身
    • 可以抛出多种类型的异常,用逗号分开就可以
例子
public class testThrows {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException{
        Class clazz = Class.forName("test");
        clazz.getField("");
    }
}
  • 自己创建一个异常,并抛出去
    • 可以自己在方法中创建一个checked exception,然后用throws关键字抛出去(构建的方法也必须throws,并且抛出的异常是自建异常的同类或父类)
    • 可以自己在方法中创建一个unchecked exception,然后用throws关键字抛出去(构建的方法不是必须throws)
例子
public class selfBuildedException {
    public static void main(String[] args) throws Exception{
        //causeException1();
        //System.out.println(1);
        //causeException2();
        //System.out.println(2);
        causeException3();
        System.out.println(3);
    }

    public static void causeException1() throws Exception{
        throw new Exception("");  //方法内用throw
    }

    public static void causeException2() throws RuntimeException{
        throw new RuntimeException("");
    }

    public static void causeException3(){
        throw new RuntimeException("");
    }
}
  • 接口/抽象方法中声明抛出的异常
    • 这里的异常是抽象方法签名的一部分
      • 实现抽象方法时抛出的异常不能超出抽象方法定义时所用异常的类型范围。
      • 接口中声明了异常,实现类可以抛,也可以不抛
    • 接口中没有声明异常,实现类中可以抛出RuntimeException,也可以不抛
      • 此时如果抛checked exception,就会报错
      • 可以使用try-catch抓住checked exception,然后将它封在RuntimeException
例子
//接口
public interface interfaceWithException {
    void danger() throws Exception;

    void safe();
}

//实现类
public class implementInterfaceWithException implements interfaceWithException{
    //*******************接口throws异常,实现类可以不throws
    public void danger(){}
    //*******************接口throws异常,实现类也可以throws
    /*public void danger() throws Exception{
        //接口中声明了异常,实现中可以抛出,也可以不抛
        throw new Exception("");
    }*/

    //*******************接口未throws异常,实现类可以不throws
    //public void safe(){}
    //*******************接口未throws异常,实现类可以throw RuntimeException
    /*public void safe(){
        throw new RuntimeException();
    }*/
    //*******************接口未throws异常,实现类可以throw checked exception,但是需要封装在RuntimeException
    public void safe(){
        try{
            throw new Exception("");
        }catch (Exception e){
            throw new RuntimeException("", e);
        }
    }
}

4-3,异常的处理方法2:try-finally、try-catch-finally、try-catch-catch-...-finally

  • try-finally
    • try中有异常就向上抛,但是如果finally中有return语句会截断异常的传递(异常被遮蔽了)
  • try-catch-finally
    • finally总会执行(try或者catch有return也会执行finally)
    • finally中给前面try/catch中的return变量赋值是无效的(try/catch中的return是在finally之前执行的,只是return后立即执行finally,在执行之后的代码)
    • finally中最好没有return语句,否则会覆盖之前try/catch的return值
try{
}catch(Exception e){
}finally{
}
  • try-catch-catch-...-finally
    • 可以捕获多类异常,分别进行处理
    • 位于前面异常类型不能和后面的有交叉(比如前面catch一个Exception,然后又catch一个ClassNotFoundException),交叉会报错
//语法1
try{
}catch (Exception1 e){
}catch (Exception2 e){
}finally{
}
//语法2
try{
}catch (Exception1 | Exception2 e){
}finally{
}

4-4,异常的传递

  • java方法一个调用一个的层层调用,组成了方法调用栈
  • java的异常
    • 或者沿着方法调用栈顺序一路抛出,最终造成当前线程出错退出
    • 或者被catch住,然后得到解决
      • catch语句是根据异常类型匹配来捕捉相应类型的异常的;如果类型不匹配,catch语句不会执行,异常会继续抛出
      • 如果catch一个其实没有被抛出的checked exception,java程序会报错
      • 如果catch一个unchecked exception,java程序会报错
      • 如果throws一个没有被抛出的checked exception或者unchecked exception,java程序不会报错

4-5,自定义异常

  • 异常最重要的信息:异常的类型、错误信息、出错时的调用栈,其中可以自定义异常的类型、错误信息。
  • 语法
//自定义异常:IDEA可以右键->Generater->Constructor自动生成
public class myException extends Exception{
    public myException() {}

    public myException(String message){
        super(message);
    }

    public myException(String message, Throwable cause){
        super(message, cause);
    }

    public myException(Throwable cause){
        super(cause);
    }
}

//使用自定义的异常:可以将catch到的Exception包装成自己定义的exception
public class testMyException {
    public static void main(String[] args) throws myException{
        Object n = null;
        try{
            n.toString();
        }catch (Exception e){
            throw new myException("执行出错", e);
        }
    }
}

4-6,自动回收资源的try语句

  • 和资源相关的操作比较容易发生异常(比如网络、文件操作),需要在这些操作出现异常时正确得回收资源。
try(创建可关闭回收的资源对象,获得了资源对象A){
  //对A的操作
}catch(Exception e){
  e.printStackTrace();
}

//可关闭回收的资源实现AutoCloseable接口,在遇到异常时会自动调用重写的close()方法

//资源类的写法
public class resource implements AutoCloseable{
  //各种属性、方法、构造函数

  public void close() throws Exception{
  //关闭时的处理方法
  }
}

4-7,java中的常见异常

  • NullPointerException //unchecked exception,最烦的是不知道在哪里,又为什么会得到一个null对象🐕
  • IndexOutOfBoundsException //unchecked exception,
  • ClassCastException //unchecked exception,对象强转声明类的时候会出现
  • ClassNotFoundException //checked exception
  • IOException //checked exception
posted @ 2021-08-20 14:29  tensor_zhang  阅读(58)  评论(0编辑  收藏  举报