• 内部类,异常


    1内部类

    在java中,一个文件可以定义多个类,文件名必须和public类型的类的类名保持一致。这两个类 是平行关系。

    1.1 内部类概念:

    在java中,一个类可以定义在一个类的内部 ,定义在内部的类称为内部类(inner class),定义在类的外部的类叫做外部类(outer class)。

    1 public class Outer {
    2     
    3     [修饰符] class Inner{
    4         
    5     }
    6 }

    编译后的结果

    内部类根据具体的修饰符和具体位置分为很多情况。

    2.1 成员内部类

    一个内部类作为外部类的成员而存在,此时该内部类称为外部类的成员内部类。一般而言,内部类都用默认修饰符。

    public class Outer {
        class Inner{
        }
    }

    2.1.1 内部类创建对象

     1 public class Test01 {
     2     public static void main(String[] args) {
     3         
     4         // 【1】创建外部类对象
     5         Outer outer = new Outer();
     6         // 【2】创建内部类对象
     7         Inner inner = outer.new Inner();
     8         inner.showInfo();
     9     }
    10 }

    2.1.2 内部类可以访问外部类的私有变量

     1 public class Outer {
     2     
     3     private String name = "Outer";
     4     
     5     class Inner{
     6         
     7         public void showInfo() {
     8             System.out.println(name);
     9         }
    10     }
    11 }

    特殊情况:外部类和内部类的变量同名

     1 public class Outer {
     2     
     3     private String name = "Outer";
     4     
     5     class Inner{
     6         
     7         private String name = "Inner";
     8         
     9         public void showInfo() {
    10             // String name = "show info";
    11             
    12             // 访问外部类的私有成员
    13             System.out.println(this.name);
    14             
    15             // 访问外部类的私有成员
    16             System.out.println(Outer.this.name);
    17             
    18         }
    19     }
    20 }

    3 静态内部类

    如果一个内部类被static修饰,我们认为这个内部类是静态内部类。形式如下。

    1 package cn.sxt01.inner02;
    2 
    3 public class Outer {
    4     
    5     static class Inner{    
    6     }
    7 }

    3.1 静态内部类创建对象

    1 public class Test01 {
    2     public static void main(String[] args) {
    3         
    4         Inner inner = new Outer.Inner();
    5         inner.showInfo();
    6     }
    7 }

    3.2静态内部类可以访问外部类中的(私有)静态成员。

     1 public class Outer {
     2     
     3     private static String name = "Outer";
     4     
     5     static class Inner{
     6         
     7         public void showInfo() {
     8             System.out.println("showInfo");
     9             
    10             System.out.println(name);
    11         }
    12     }
    13 }

    特殊情况:静态内部类和外部类有同名变量(避免发生)

    public class Outer {
        
        private static String name = "Outer";
        
        static class Inner{
            
            private static String name = "Outer";
            
            public void showInfo() {
                System.out.println("showInfo");
                
                System.out.println(name);
                
                System.out.println(Outer.name);
            }
        }
    }

    4 方法内部类

    4.1 如果一个内部类定义在一个方法中,称之为方法内部类。形式如下:

     1 public class Outer {
     2     
     3     
     4     public void print() {
     5         
     6         class Inner{
     7             
     8             public void showInfo() {
     9                 System.out.println("show info");
    10             }
    11         }
    12         
    13         Inner inner = new Inner();
    14         inner.showInfo();
    15     }
    16 }

    4.2 方法的局部变量进入方法内部类时,会被final修饰,出了方法的内部类则不会被final修饰。

     1 public class Outer {
     2     
     3     public void print(int b) {
     4         
     5         int a = 10;
     6         
     7         class Inner{
     8             
     9             public void showInfo() {
    10                 System.out.println("show info");
    11                 
    12                 System.out.println("print()->a:"+10);
    13                 
    14                 // 在方法内部类中不能修改方法的局部变量(final)
    15                 // a = 20;
    16                 // b = 20;
    17             }
    18         }
    19         
    20         a = 20;
    21         
    22         Inner inner = new Inner();
    23         inner.showInfo();
    24     }
    25 }

    5 匿名内部类

    未来一个类如果只使用一次,我们可以把类声明为匿名类。匿名类一般和内部类一起使用。形成匿名内部类。

    匿名内部类可用在:实现接口

     1 package cn.sxt01.inner04;
     2 
     3 public class Outer {
     4     
     5     public void print() {
     6         
     7         // 方法内部类
     8         /*class Inner implements MyInterface{
     9 
    10             @Override
    11             public void showInfo() {
    12                 System.out.println("Inner:showInfo");
    13             }
    14             
    15         }*/
    16         
    17         /*Inner inner = new Inner();
    18         inner.showInfo();*/
    19         
    20         // new Inner().showInfo();
    21         
    22         // 匿名内部类
    23         new MyInterface(){
    24             @Override
    25             public void showInfo() {
    26                 System.out.println("Inner:showInfo");
    27             }
    28         }.showInfo();
    29         
    30     }
    31 }

    2 异常处理

    2.1传统异常处理的方式

     1 public class Test01 {
     2     public static void main(String[] args) {
     3         Scanner sc = new Scanner(System.in);
     4         System.out.println("请输入第一个数:");
     5         
     6         int num1 = 0;
     7         if(sc.hasNextInt()) {            
     8             num1 = sc.nextInt();
     9             
    10             System.out.println("请输入第二个数:");
    11             int num2 = 0;
    12             if(sc.hasNextInt()) {
    13                 num2 = sc.nextInt();
    14                 
    15                 if(0 == num2) {
    16                     System.out.println("除数不能为0!");
    17                 }else {                    
    18                     int r = num1 / num2;
    19                     System.out.println("num1/num2 = "+r);
    20                 }
    21 
    22             }else {
    23                 System.out.println("第二个数输入不是数字");
    24             }
    25             
    26         }else {
    27             System.out.println("第一个数输入不是数字!");
    28         }
    29     }
    30 }

    缺点:

    [1] 通过判断影响执行效率

    [2] 判断逻辑和业务逻辑交织在一起可维护性很差。

    2.2 异常

    异常是指在程序运行过程中发生的不正常的情况,它会中断正在运行的程序。

    异常处理机制

    java中通过异常处理机制为程序提供异常处理的能力,保证java在运行过程中,能够保持运行而不因为异常中断程序。

    2.3异常处理

     涉及异常处理的关键字有try ...catch/try ...catch ...finally

    2.3.1 try/catch

     把可能产生异常的代码放在try代码块中,catch代码块去买个捕获并处理异常。

    【1】正常执行,没有异常

    【2】出现异常,异常处理,正常结束

     Exception是所有异常类的直接的或间接的父类。

    getMessage:返回异常的描述信息

     1 package cn.sxt02.exception02;
     2 import java.util.Scanner;
     3 public class Test01 {
     4     public static void main(String[] args) {
     5         Scanner sc = new Scanner(System.in);
     6         System.out.println("请输入第一个数:");
     7 
     8         int num1 = 0;
     9         int num2 = 0;
    10         
    11         try {
    12             num1 = sc.nextInt();
    13 
    14             System.out.println("请输入第二个数:");
    15             num2 = sc.nextInt();
    16 
    17             int r = num1 / num2;
    18             System.out.println("num1/num2 = " + r);
    19         }catch (Exception e) {
    20             System.out.println("程序出现异常");
    21             // 打印异常的信息
    22             // System.out.println(e.toString());
    23             
    24             
    25             // 打印异常堆栈信息
    26              e.printStackTrace();
    27             
    28             // 返回异常的描述信息,如果没有信息,返回null(InputMismatchException 没有描述信息)
    29             System.out.println(e.getMessage());
    30         }
    31         
    32         System.out.println("程序正常结束");
    33     }
    34 }

    【3】异常类型不匹配

    【4】多重catch

     1 public class Test03 {
     2     public static void main(String[] args) {
     3         Scanner sc = new Scanner(System.in);
     4         System.out.println("请输入第一个数:");
     5 
     6         int num1 = 0;
     7         int num2 = 0;
     8         
     9         try {
    10             num1 = sc.nextInt();
    11 
    12             System.out.println("请输入第二个数:");
    13             num2 = sc.nextInt();
    14 
    15             int r = num1 / num2;
    16             System.out.println("num1/num2 = " + r);
    17         }catch (ArithmeticException e) {
    18             System.out.println("数学计算异常:"+e.getMessage());
    19         }catch(InputMismatchException e) {
    20             System.out.println("输入不匹配异常:"+e.getMessage());
    21         }catch (Exception e) {
    22             System.out.println("发送异常:"+e.getMessage());
    23         }
    24         
    25         System.out.println("程序正常结束");
    26     }
    27 }

    2.3.2 try/catch/finally

    把有可能产生异常的代码放到try代码块中,catch能够捕获并处理异常,finally用于进行收尾工作(关闭数据库、关闭文件、释放内存等资源).

    不管是否发生异常,finally都执行。

     1 public static void main(String[] args) {
     2         Scanner sc = new Scanner(System.in);
     3         System.out.println("请输入第一个数:");
     4 
     5         int num1 = 0;
     6         int num2 = 0;
     7 
     8         try {
     9             num1 = sc.nextInt();
    10 
    11             System.out.println("请输入第二个数:");
    12             num2 = sc.nextInt();
    13 
    14             int r = num1 / num2;
    15             System.out.println("num1/num2 = " + r);
    16         } catch (Exception e) {
    17             System.out.println("程序出现异常");
    18         } finally {
    19             System.out.println("不管是否出现异常,finally都执行");
    20         }
    21 
    22         System.out.println("程序正常结束");
    23     }

     finally总是执行,常用进行收尾工作。

     特殊情况

     [1] finally执行的情况。

     System.exit(0);正常退出jvm,finally不会执行。

     [2]catch可以省略,变成try...finally块。

    2.3.3 return

    存在return的try/catch/finally执行顺序。

    【1】如果不出现异常,顺序为:try->finally->return

    【2】如果出现异常,顺序为:try->catch->finally->return

     1 package cn.sxt02.exception03;
     2 
     3 /**
     4  * 存在return的情况
     5  */
     6 public class Test02 {
     7 
     8     public static int div(int a, int b) {
     9 
    10         try {
    11             int r = a / b;
    12             return r;
    13 
    14         } catch (Exception e) {
    15             System.out.println("出现异常");
    16 
    17             return 0;
    18 
    19         } finally {
    20             System.out.println("我是finally");
    21         }
    22 
    23     }
    24 
    25     public static void main(String[] args) {
    26 
    27         int r = Test02.div(10, 0);
    28         System.out.println("r=" + r);
    29         System.out.println("程序正常结束");
    30     }
    31 }

    2.4异常的分类

    Throwable类是java中所有错误(error)或异常(exception)的父类。

    Exception类表示异常类,分为两种:

    RuntimeException:运行时异常。不要求程序必须做出处理。是所有运行时异常的父类。

    CheckedException:检查时异常。要求程序必须做出处理,不处理无法编译。

     1 public class Test01 {
     2     public static void main(String[] args) {
     3         // 运行时异常
     4         Scanner sc = new Scanner(System.in);
     5         // runtime exception
     6         int r = sc.nextInt();
     7         System.out.println("r = "+ r);
     8         
     9         // 检查时异常
    10         SimpleDateFormat df = new SimpleDateFormat();
    11         try {
    12             Date date = df.parse("2019");
    13         } catch (ParseException e) {
    14             e.printStackTrace();
    15         }
    16     }
    17 }

    常见的运行时异常

    ArithmeticException:数学计算异常。比如除数为0

    InputMismatchException:输入不匹配异常

    ArrayIndexOutofBoundsException:数组下标越界异常。

    NullPointException:空指针异常,对象没有初始化就使用时,jvm抛出该异常

    IllegalArgumentException:非法参数异常。

    ClassCastException:强制类型转换异常。

    NumberFormatException:数字格式化异常。比如把“abc”格式化成数字。

    常见检查时异常:

    ClassNotFoundException:类没有被发现异常。

    SQLException:数据库相关异常

    IOException:IO操作异常

    ParseException:解析错误异常

    FileNotFoundException:文件未发现异常。

    运行时异常和检查时异常的区别

      运行时异常:包括RuntimeException及其所有子类。不要求程序必须对它们作出处理,比如InputMismatchException、ArithmeticException、NullPointerException等。即使没有使用try-catch或throws进行处理,仍旧可以进行编译和运行。如果运行时发生异常,会输出异常的堆栈信息并中止程序执行。

      Checked异常(非运行时异常):除了运行时异常外的其他异常类都是Checked异常。程序必须捕获或者声明抛出这种异常,否则出现编译错误,无法通过编译。处理方式包括两种:通过try-catch捕获异常,通过throws声明抛出异常从而交给上一级调用方法处理.

    2.5.1

    throws关键字

    当一个方法可能存在异常,而此时自身又无法更好的处理时,可以用将异常交给外界处理。此时用throws关键字声明异常并抛出。

     1 public class Test01 {
     2 
     3     public static int div(int a, int b) throws ArithmeticException{
     4         int r = 0;
     5         r = a / b;
     6         return r;
     7     }
     8 
     9     public static void main(String[] args) {
    10         try {
    11             Test01.div(10, 0);
    12         } catch (ArithmeticException e) {
    13             System.out.println("除数不能为0");
    14         }
    15     }
    16 }

    开发者可以根据需要声明检查时异常(Exception或者非运行时异常)和运行时异常(RuntimeException其子类)

    如果调用处也不知道如何处理异常,可选择继续声明异常,我们把这个过程称为异常上抛

     1 public class Test01 {
     2 
     3     public static int div(int a, int b) throws Exception{
     4         int r = 0;
     5         r = a / b;
     6         return r;
     7     }
     8 
     9     public static void main(String[] args) throws Exception{
    10         
    11         //【1】 调用处知道如何处理!
    12         /*
    13         try {
    14             Test01.div(10, 0);
    15         } catch (Exception e) {
    16             e.printStackTrace();
    17         }
    18         */
    19         
    20         // 【2】调用处也不知道如何处理
    21         Test01.div(10, 0);
    22         
    23     }
    24 }

    2.5.2 声明异常和重载的关系

     发明异常和重载没有关系。

    方法重载

    【1】方法名相同

    【2】参数列表不同(个数,类型,不同类型的顺序不同)

    【3】和返回值,修饰符,声明异常无关

    2.5.3 声明异常和重写的关系

    声明异常和方法重写有关系。

    【1】父类方法声明了异常(检测时或运行时),子类可以不声明任何异常。

    【2】父类方法声明没有声明任何异常(检测时或运行时),子类不声明异常或者声明运行时异常。

    【3】父类方法声明了异常(检测时或运行时),子类也声明相同的异常

    2.6 手动抛出异常

     2.6.1 throw

    除了系统自动抛出异常外,有些问题需要开发者自己手动抛出。使用关键字throw

     1 package cn.sxt02.exception06;
     2 
     3 public class Student {
     4     private String name;
     5     private String gender;
     6 
     7     public String getName() {
     8         return name;
     9     }
    10 
    11     public void setName(String name) {
    12         this.name = name;
    13     }
    14 
    15     public String getGender() {
    16         return gender;
    17     }
    18 
    19     public void setGender(String gender) throws Exception{
    20         if(gender.equals("男") || gender.equals("女")) {            
    21             this.gender = gender;
    22         }else {
    23             throw new Exception("性别不合法!");
    24         }
    25     }
    26 
    27     public Student(String name, String gender) {
    28         super();
    29         this.name = name;
    30         this.gender = gender;
    31     }
    32 
    33     public Student() {
    34         super();
    35     }
    36     
    37 }
     1 public class Test01 {
     2     public static void main(String[] args){
     3         Student stu = new Student();
     4         stu.setName("二狗");
     5         try {
     6             stu.setGender("xxx");
     7         } catch (Exception e) {
     8             System.out.println(e.getMessage());
     9         }
    10     }
    11 }

    2.7 自定义异常

      如果开发者需要手动抛出的异常在系统不存在,可以自定义异常。

    如果要自定义异常,首先要确定异常类型,如果异常运行时异常,必须继承RuntimeException其子类;如果异常是检查时异常,必须继承Exception其子类。

      异常的命名方式,参考系统命名方式,以Exception结尾。

     1 public class AgeException extends Exception{
     2 
     3     public AgeException() {
     4         super();
     5     }
     6 
     7     public AgeException(String message) {
     8         super(message);
     9     }
    10     
    11 }
  • 相关阅读:
    一个统计代码行数的简单方法
    关于string的对象引用
    mysql连接的一些问题。
    linux环境初始化 用户问题
    php null o false ''
    php支付宝在线支付接口开发教程【转】
    模拟支付宝服务窗环境
    ctags
    校验全球电话号码 正确性 库 正则表达式
    php短路与 短路或
  • 原文地址:https://www.cnblogs.com/qq308015824/p/10776692.html
Copyright © 2020-2023  润新知