java注解、java异常处理机制

目录

注解(Annotation) 

@override

@Deprecated

@SuppressWarnings 

 元注解(了解)—— 修饰注解的注解 

静态属性、内部类、枚举类的练习

异常(Exception)

五大运行时异常

 1. NullPointerException

2. ArithmeticException

3. ArrayIndexOutOfBoundsException

4. ClassCastException

 5. NumberFormatException

异常处理方式 

1. try-catch-finally

2. throws

try-catch细节

try-catch小练习

throws异常处理

 throws细节:

自定义异常

throw和throws区别

 异常练习题


注解(Annotation) 

  1. 注解也称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息
  2. 和注释一样,注解不影响程序逻辑,但不同于注释,注解可以被编译或运行,相当于嵌入再代码中的补充信息
  3. 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据更重要的角色,例如用来配置应用程序的任何切面,代替javaEE旧版本中所遗留的繁冗代码和XML配置等
  • 使用Annotation时要在前面加上@符号,并把Annotation当成以一个修饰符使用 

三个基本的Annotation:

  1. @override:重写父类方法,只能注解方法
  2. @Deprecated:表示某个程序元素(类、方法等)已过时
  3. @SuppressWarnings:抑制编译器警告

@override

  • 方法前写了@override,编译器会进行语法校验,编译器会判断该方法是否是重写方法,如果没有构成重写,编译器就会报错
  • @Target是修饰注解的注解,称为元注解

 在idea中快速定位到override的源码:ctrl + alt + B


@Deprecated

  • @Deprecated修饰某个元素,表示这个元素已经过时了,不推荐使用,但还是能用 
  • @Deprecated源码如下:

  • @Deprecated可以做版本升级过渡时使用 

@SuppressWarnings 

  • 当我们不希望看到一些警告信息时,可以使用@Suppress Warnings{}注解来抑制警告信息,即不显示这些警告信息 
  • 在{}中可以写入希望抑制(不显示)的警告信息,{}中是一个字符串数组,如all是抑制所有警告
  • @Suppress Warnings作用范围和放置的位置有关,通常可以放在语句、方法、类上
package com.lili.Annotation_;

import java.util.ArrayList;
import java.util.List;

public class SuppressWarnings_ {
    //1.当我们不希望看到一些警告信息时,可以使用@SuppressWarnings注解来抑制警告信息
    //2.在{""}中可以写入希望抑制(不显示)的警告信息
    @SuppressWarnings({"unchecked", "rawtypes", "unused"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("hello");
        list.add("你好");
        list.add("hi");
        int n;
    }
}


 元注解(了解)—— 修饰注解的注解 

元注解的类型:

  1. @Retention 指定注解的作用时间范围,三种:SOURCE, CLASS, RUNTIME
  2. @Target 指定注解可以在哪些地方使用
  3. @Documented 指定注解是否会在javadoc体现
  4. @Inherited 子类会继承父类注解

 


静态属性、内部类、枚举类的练习

test1:看看会输出什么?

package com.homework.chapter10;

import java.awt.*;

public class Homework01 {
    public static void main(String[] args) {
        Car car = new Car();       //1
        Car car1 = new Car(11);    //2
        System.out.println(car);  
        System.out.println(car1);
    }
}

class Car{
    double price = 10;
    static String color = "white";

    @Override
    public String toString() {
        return "price = " + price +
                " color = " + color ;
    }

    public Car() {
        this.price = 9;
        this.color = "red";
    }

    public Car(double price) {
        this.price = price;
    }
}

语句1 new Car() 时,会先进行类加载,进行静态属性的初始化执行静态代码块(如果有的话) ,类变量color初始化为白色;再执行构造器,price = 9, 类变量color = red

语句2 ,car1指向一个新的Car对象,因为静态属性和静态代码块随类加载而执行一次且仅一次,所以直接执行构造器,price = 11,类变量color是共享的,color = red

所以输出 :

price = 9.0 color = red
price = 11.0 color = red


test2

/**
 * 1.在Frock类中声明私有的静态属性currentNum[int类型],初始值为100000,作为衣服出厂序列号起始值
 * 2.声明公有的静态方法getNextNum,作为生成上衣唯一序列号的方法,每调用一次,将currentNUM加100,并作为返回值
 * 3.在main方法中,分两次调用getNextNum方法,获取序列号并打印输出
 * 4.在Frock类中声明serialNumber(序列号)属性,并提供对应的get方法
 * 5.在Frock类的构造器中,通过调用getNextNum方法为Frock对象获取唯一序列号,赋给serialNumber属性
 * 6.在main方法中,分别创建3个Frock对象,并打印三个对象的序列号,验证是否为按100递增
 */

package com.homework.chapter10;

public class Homework02 {
    public static void main(String[] args) {
        System.out.println("第一次调用getNextNum():" + Frock.getNextNum());
        System.out.println("第二次调用getNextNum():" + Frock.getNextNum());
        Frock frock = new Frock();
        Frock frock1 = new Frock();
        Frock frock2 = new Frock();
        System.out.println(frock.getSerialNumber());
        System.out.println(frock1.getSerialNumber());
        System.out.println(frock2.getSerialNumber());
    }
}


class Frock {
    private int serialNumber;
    private static int currentNum = 100000;

    public Frock() {
        this.serialNumber = getNextNum();
    }

    public int getSerialNumber() {
        return serialNumber;
    }

    public static int getNextNum() {
        currentNum += 100;
        return currentNum;
    }

}

test3 

/**
 * 1.计算器接口具有work方法,功能是运算,有一个手机类Cellphone,
 * 定义方法testWork测试计算功能,调用计算接口的work方法
 * 2.要求调用Cellphone对象的testWork方法,使用匿名内部类
 */

package com.homework.chapter10;

import javafx.scene.control.Cell;

public class Homework04 {
    public static void main(String[] args) {
        //第一个实参编译类型是ICalculate,运行类型是匿名内部类
        Cellphone.testWork(new ICalculate() {
            @Override
            public double work(double a, double b) {   
                return a + b;
            }
        },2, 6);
    }
}

interface ICalculate {
    //接口中的方法,除了抽象方法,还可以有static方法、default方法、private方法
    double work(double a, double b);
}

class Cellphone {
    public static void testWork(ICalculate cal, double a, double b) {
        System.out.println("计算的结果是:" + cal.work(a, b));
    }
}

test4

/**
 * 1.编一个类A,在类中定义局部内部类B,B中有一个私有常量name,show()打印常量name
 * 2.进阶:A中也定义一个私有常量name,在show()打印常量name
 */

package com.homework.chapter10;

public class Homework05 {
    public static void main(String[] args) {
        //每new一个对象,就会执行一次普通代码块
        A a = new A();
    }
}

class A {
    private String name = "keddy";
    {
        System.out.println("A的普通代码块...");
        //局部内部类
        class B {
            private String name = "Jerry";
            void show() {
                System.out.println("name = " + name);
                //如果外部类的属性和局部内部类的属性重名,
                //则访问外部类属性用:外部类.this.属性
                System.out.println("A的name = " + A.this.name);
            }
        }
        B b = new B();
        b.show();
    }
}

test5

package com.homework.chapter10;

import com.lili.houserent.domain.House;
import com.lili.interface_.Phone;

public class Homework06 {
    public static void main(String[] args) {
        Person tang = new Person("唐僧", VehiclesFactory.getHorse());
        tang.passRiver();
        tang.commonSituation();
        tang.fireMountain();
    }
}

interface Vehicles {
    void work();
}

class Horse implements Vehicles {

    @Override
    public void work() {
        System.out.println("一般情况下,骑马赶路...");
    }
}

class Boat implements Vehicles {

    @Override
    public void work() {
        System.out.println("遇到大河,乘船过河...");
    }
}

class Plane implements Vehicles {

    @Override
    public void work() {
        System.out.println("遇到火焰山,乘飞机过路...");
    }
}

class VehiclesFactory {
    //单例设计模式,饿汉式
    private static Boat boat = new Boat();
    private static Horse horse = new Horse();
    private static Plane plane = new Plane();

    private VehiclesFactory() {
    }

    public static Vehicles getBoat() {
        return boat;
    }

    public static Vehicles getHorse() {
        return horse;
    }

    public static Vehicles getPlane() {
        return plane;
    }
}

class Person {
    private String name;
    private Vehicles vehicles;

    public Person(String name, Vehicles vehicles) {
        this.name = name;
        this.vehicles = vehicles;
    }

    public void passRiver() {
        if(!(vehicles instanceof Boat)) {
            vehicles = VehiclesFactory.getBoat();
        }
        vehicles.work();
    }

    public void commonSituation() {
        if (!(vehicles instanceof Horse)) {
            vehicles = VehiclesFactory.getHorse();
        }
        vehicles.work();
    }

    public void fireMountain() {
        if(!(vehicles instanceof Plane)) {
            vehicles = VehiclesFactory.getPlane();
        }
        vehicles.work();
    }
}

test6

package com.homework.chapter10;

public class Homework07 {
    public static void main(String[] args) {
        Car car = new Car(26);
        Car car1 = new Car(41);
        Car car2 = new Car(0);
        car.getAir().flow();
        car1.getAir().flow();
        car2.getAir().flow();
    }
}

class Car {
    private double temperature;

    public Car(double temperature) {
        this.temperature = temperature;
    }
    //成员内部类
    class Air {
        void flow() {
            if (temperature > 40) {
                System.out.println("现在温度" + temperature + "℃ 吹冷气...");
            } else if (temperature < 0) {
                System.out.println("现在温度" + temperature + "℃ 吹暖气...");
            } else {
                System.out.println("现在温度" + temperature + "℃ 空调关闭...");
            }
        }
    }

    public Air getAir() {
        return new Air();
    }
}

 test7

package com.homework.chapter10;

import java.util.Scanner;

public class Homework08 {
    public static void main(String[] args) {
        Color color = Color.GREEN;
        switch (color) {
            case RED:
                System.out.println("匹配到红色");
                break;
            case BLUE:
                System.out.println("匹配到蓝色");
                break;
            case GREEN:
                System.out.println("匹配到绿色");
                break;
            case BLACK:
                System.out.println("匹配到黑色");
                break;
            case YELLOW:
                System.out.println("匹配到黄色");
                break;
        }
        color.show();
    }
}

interface IA{
    void show();
}

enum Color implements IA{
    RED(255, 0, 0), GREEN(0, 255, 0),
    BLUE(0,0, 255), BLACK(0, 0, 0),
    YELLOW(255, 255, 0);
    private double redValue;
    private double greenValue;
    private double blueValue;

    Color(double redValue, double greenValue, double blueValue) {
        this.redValue = redValue;
        this.greenValue = greenValue;
        this.blueValue = blueValue;
    }

    @Override
    public void show() {
        System.out.println(this.name() + ": " + this.toString());
    }

    @Override
    public String toString() {
        return "redValue=" + redValue +
                ", greenValue=" + greenValue +
                ", blueValue=" + blueValue +
                '}';
    }
}

异常(Exception)

  • 程序执行中发生的不正常情况称为异常,开发过程中的语法错误和逻辑错误不是异常
  • 如果程序员认为一段代码可能出现异常,可以用try-catch异常处理机制来解决,保证程序的健壮性
  • 程序执行中发生的异常事件分为两种:Error(错误)和Exception

1.Error(错误):java虚拟机无法解决的严重问题。如:jvm系统内部错误、资源耗尽等严重情况。比如:StackOverflowError[栈溢出]和OOM(out of memory),Error是严重错误,程序会崩溃。

2.Exception :其它问题,可以使用针对性的代码处理。Exception分为两类:运行时异常和编译时异常。

选中可能出现异常的代码-->快捷键ctrl + alt + t -->选择try - catch (idea集成开发工具)

如果进行异常处理,程序即使出现异常,程序还是继续运行

package com.lili.exception_;

public class Exception01 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        try {
            int res = num1 / num2;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("程序继续...");
    }
}


  1. 异常分为两大类,编译时异常和运行时异常
  2. 运行时异常,编译器检查不出。一般指编程时的逻辑错误,是程序员应该避免其出现的异常
  3. 对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会影响程序的可读性和运行效率
  4. 编译时异常,是编译器要求必须处理的异常

五大运行时异常

 1. NullPointerException

空指针异常:当应用程序试图在需要对象的地方使用null时,抛出该异常

2. ArithmeticException

数学运算异常

3. ArrayIndexOutOfBoundsException

数组下标越界异常,索引为负或大于等于数组长度

4. ClassCastException

类型转换异常 ,试图将对象强制转换为不是实例的子类

 5. NumberFormatException

数字格式不正确异常


异常处理方式 

1. try-catch-finally

程序员在代码中捕获发生的异常,自行处理

try{

        可能有异常的代码

}catch(Exception e){

        捕获到异常,系统将异常封装成Exception对象传递给catch,得到异常对象后,程序员自己处理。注意:如果没有发生异常,catch代码块不会执行

}finally{

        不管代码块是否发生异常,都要执行finally,所以,通常将释放资源的代码放在finally

}

2. throws

将发生的异常抛出,交给调用者来处理,最顶级的处理者是JVM

如果没有显示的使用try-catch或throws处理异常,默认使用throws


try-catch细节

1. 如果发生了异常,try中异常发生后面的代码不会执行,直接进入到catch块 

2. 如果异常没有发生,则顺序执行try的代码块,不会进入到catch

3. 如果希望不管是否发生异常都执行,比如关闭连接、释放资源等,就写到finally中

4. 可以有多个catch语句捕获异常,要求子类异常写在前面,父类异常写在后面

package com.lili.exception_;

public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String name = null;
            System.out.println(name.length());
            String str = "12";
            int num = Integer.parseInt(str);
            System.out.println(num);
        } catch (NullPointerException e) {
            System.out.println("空指针异常=" + e.getMessage());
        } catch (NumberFormatException e) {
            System.out.println("算术异常=" + e.getMessage());
        } catch (Exception e) {
            System.out.println("异常信息=" + e.getMessage());
        }
    }
}

5.可以进行try-finally配合使用,相当于没有捕获异常,因此发生异常程序直接崩溃

应用场景:执行一段代码,不管是否发生异常,都必须执行某个业务逻辑


try-catch小练习

Exercise1:看看会输出什么?

package com.lili.exception_;

public class TryCatchExercise01 {
    public static void main(String[] args) {
        System.out.println(method());
    }
    public static int method(){
        try{
            String[] names = new String[3];
            if(names[1].equals("tom")){     //①NullPointerException异常
                System.out.println(names[1]);
            }else{
                names[3] = "lulu";
            }
            return 1;
        }catch(ArrayIndexOutOfBoundsException e){
            return 2;
        }catch (NullPointerException e){    //②捕获异常
            return 3;
        }finally {                          //③最后一定会执行finally
            return 4;
        }
    }
}

answer:  4


Exercise2

package com.lili.exception_;

public class TryCatchException02 {
    public static void main(String[] args) {
        System.out.println(method());    //4
    }

    public static int method(){
        int i = 1;
        try{
            i++;  //i=2
            String[] names = new String[3];
            if(names[1].equals("tom")){       //NullPointerException
                System.out.println(names[1]);
            }else{
                names[3] = "lulu";
            }
            return 1;
        }catch(ArrayIndexOutOfBoundsException e){
            return 2;
        }catch (NullPointerException e){
            return ++i;  //return 3,i=3
        }finally {
            return ++i;   //return 4,i=4
        }
    }
}

answer:  4 


Exercise3

package com.lili.exception_;

public class TryCatchExercise03 {
    public static void main(String[] args) {
        System.out.println(method());  //3
    }

    public static int method(){
        int i = 1;
        try{
            i++;  //i=2
            String[] names = new String[3];
            if(names[1].equals("tom")){       //NullPointerException
                System.out.println(names[1]);
            }else{
                names[3] = "lulu";
            }
            return 1;
        }catch(ArrayIndexOutOfBoundsException e){
            return 2;
        }catch (NullPointerException e){
            return ++i;  //i=3先不会执行return ->返回值保存到临时变量temp=3,先执行finally
        }finally {
            ++i;   //i=4
            System.out.println("i = " + i); //i = 4
        }
    }
}

answer:

i = 4

3


Exercise4

编程:如果用户输入的不是一个整数,就提示反复输入,直到输入一个整数为止

package com.lili.exception_;

import java.util.Scanner;

/**
 * s如果用户输入的不是一个整数,就提示反复输入,直到输入一个整数为止
 */
public class TryCatchExercise4 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String inputStr = "";
        int num = 0;
        while (true) {
            System.out.print("请输入一个整数:");
            inputStr = scanner.next();
            try {
                num = Integer.parseInt(inputStr);
                break;  //如果没抛出异常,就会执行break;
            } catch (NumberFormatException e) {
                System.out.println("输入不是一个整数");
            }
        }
        System.out.println("输入的整数:" + num);
    }
}

throws异常处理

1.如果一个方法可能出现异常,但是不能确定如何处理这种异常,则此方法应该显示地声明抛出异常,表明该方法将不对异常进行处理,而由该方法的调用者处理

2.throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类 

3.可以用try-catch-finally,也可以用throws抛出异常,让调用者去处理(二选一)

4.throws语句可以声明抛出异常的列表,逗号分隔


 throws细节:

1.对于编译异常,程序必须处理
2.对于运行异常,程序如果没有处理,默认用Throws处理
3.子类重写父类,子类抛出的异常要么和父类一致,要么是父类抛出异常类型的子类

public void f1() throws FileNotFoundException {
        //这里的异常是编译异常FileNotFoundException
        FileInputStream fis = new FileInputStream("D://a.txt");
    }
public static void f2() throws FileNotFoundException{
        /*
            因为f3()方法抛出的是一个编译异常,编译异常必须处理,
            f2()必须处理这个编译异常,在f2()中,要么try-catch-finally,
            要么继续throws这个编译异常
        */
        f3();
    }

    public static void f3() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream("D://a.txt");
    }
public static void f4() {
        /*
            因为f5()方法抛出的是一个运行异常,运行异常可以不必处理,
            java中有默认处理机制,
            所以不报错
        */
        f5();
    }

    public static void f5() throws ArithmeticException {
        
    }

自定义异常

当程序出现了一些“错误”,但该错误信息并没有在Throwable子类中描述处理,这时可以自定义异常类,用于描述错误信息

1.定义类:自定义异常类名,继承Exception或RuntimeException

2.如果继承Exception,属于编译异常

3.如果继承RuntimeException,属于运行异常

4.一般继承RuntimeException运行异常,好处是有默认的处理机制

package com.lili.customexception_;

/**
*要求age在18-120,否则抛出异常
*/
public class CustomException {
    public static void main(String[] args) {
        int age = 12;
        if(!(age >= 18 && age <= 120)) {
            //可以通过构造器设置信息
            throw new AgeException("年龄需在18~120之间");  //注意这里是throw +  异常对象
        }
        System.out.println("年龄正确");
    }
}

//自定义一个异常,age在18-120
class AgeException extends RuntimeException{
    public AgeException(String message){
        super(message);
    }
}

throw和throws区别

  1. throws是异常处理的一种方式,throw是手动生成异常对象的关键字
  2. throws位于方法声明处,throw位于方法体内
  3. throws后面跟异常类型,throw后面跟异常对象 

看看会输出什么? 

package com.lili.throws_;

public class ThrowException {
    public static void main(String[] args) {
        try {
            ReturnExceptionDemo.methodA();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        ReturnExceptionDemo.methodB();
    }
}

class ReturnExceptionDemo{
    static void methodA(){
        try {
            System.out.println("进入方法A");
            throw new RuntimeException("制造异常");
        } finally {
            System.out.println("用A方法的finally");
        }
    }

    static void methodB(){
        try {
            System.out.println("进入方法B");
            return;
        } finally {
            System.out.println("用B方法的finally");
        }
    }
}

answer: 

 


 异常练习题 

 1. 编写应用程序EcmDef.java,接收命令行的两个参数,计算两数整除
 2. 计算两数整除,用cal(int n1, int n2)
 3.  对数据格式不正确、缺少命令行参数、除0进行异常处理

package com.lili.homework;

import java.util.Scanner;

public class homework01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //缺少命令行参数
        try {
            if(args.length != 2) {
                throw new ArrayIndexOutOfBoundsException("命令行参数个数不对");
            }

            //接收命令行的两个参数
            int n1 = Integer.parseInt(args[0]);
            int n2 = Integer.parseInt(args[1]);

            //除0异常
            System.out.println(EcmDef.cal(n1, n2));
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());
        } catch (NumberFormatException e) {
            System.out.println("参数格式不正确");
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        }
    }
}

class EcmDef{
    public static double cal(int n1, int n2){
        return n1 / (double)n2;
    }
}

  • 36
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lili_1i1i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值