• 内部类、异常


    内部类

    1、定义

    在一个类中,定义另一个类的代码结构,通常定义在类内部的类称为“内部类”,外面的类称为“外部类”,在逻辑上 内部类与外部类是从属关系,比如 一个People类存 在收货地址类(收货人,收货联系方式)

    2、分类

    2.1、普通内部类(inner class),一个类A中定义一个类B,其中类B就是类A的内部类,也是类A的一部分

    public class People {
        private String pname="张三";
        public void sayHello(){
            System.out.println("Let us say Hello");
            // 知识点1 :外部类的方法中,可以使用内部类的属性、方法
            Address address = new Address();
            address.addressName ="湖北武汉";
            address.contentName="张某某";
            address.showAddressInfo();
        }
    
        /**
         * 定义普通内部类   收货地址
         */
        class Address{
            private String addressName;// 收货地址
            private String contentName;// 联系人
    
            public void showAddressInfo(){
                System.out.println("联系人:"+contentName + "--收货地址:"+addressName);
                // 内部类的方法 可以直接访问外部类的属性  (由于通常情况属性的访问必须通过对象才可以使用,而)
                System.out.println("访问外部类的属性:"+pname);
            }
        }
    }
    

    注意:外部类的方法中,可以直接访问内部类的所有成员(包括私有);
    内部类的方法中,也可以直接访问外部类的所有成员,当外部类和内部类的成员名相同时,就近原则访问成员,或者引入外部类的对象访问

    2.2、静态内部类(static inner class)

    在普通内部类的基础上,增加“static”关键字,与静态方法相似,满足静态的需求
    
    public class People{
    /**
         * 2、定义静态内部类
         *   卡信息
         */
        static  class Card{
            private static String cardNo="4200018888000022";
            private String cardName="身份证";
    
            // 定义静态方法
            public static void showCard(){
                System.out.println("身份证号:"+ cardNo);
            }
            // 定义非静态方法
            public void showCard2(){
                System.out.println("cardName:"+cardName + "----"+ cardNo);
            }
       
        }
    
    	// 外部类的方法 
        public void method2(){
            Card card = new Card();
            // 对于静态方法可以直接类名.方法名
            // 对于非静态方法,需要创建Card类的对象访问
            card.showCard2();
    
    
        }
    }
    
    使用:
            // 2 创建静态内部类的对象
            People.Card.showCard();
            // 创建静态内部类的对象
            People.Card  card = new People.Card();
            card.showCard2();
    

    2.3、方法内部类

    在一个方法中定义的类,其中这个类只属于该方法,也只能在该方法中使用

     /**
         * 3、方法内部类 (将一个类定义在方法里面)
         */
        public void method3(){
             int score = 98;
    
             // 在这里定义一个类
            class MyClass{
                String subject="Java";
                public void getSubjectScore(){
                    //方法内部类中 也可以使用方法的属性
                    System.out.println(pname+"的"+subject+":"+score);
                }
            }
    
            //调用方法里面的类
            MyClass  mycls = new MyClass();
            mycls.getSubjectScore();
        }
    

    注意:内部类剩的class文件 命名 外部类$内部类名.class

    2.4匿名内部类

    定义一个没有类名,只有对方法的具体实现。通常它依赖于实现关系(接口)或继承关系(父类)
    a、基于实现关系

    public interface MyInterface {
        // 学习
        public void  study();
        //  工作
        public void work();
    }
    
      // 创建一个匿名类(让接口的引用 指向匿名类的对象)
            MyInterface  person = new MyInterface() {
                @Override
                public void study() {
                    System.out.println("这个人也好好学习");
                }
    
                @Override
                public void work() {
                    System.out.println("这个人也好好工作");
                }
            };
    
            person.study();
            person.work();
    

    b、基于继承关系

    public class MyClass {
    
       public void service(){
            System.out.println("提供服务的方法。");
        }
    }
    
     // 父类 new 一个 匿名类,这个匿名类是它的子类
            MyClass cls = new MyClass(){
                @Override //匿名类重写父类的方法 service
                public void service() {
                    System.out.println("这是子类的方法");
                }
            };
            cls.service();
    

    二、异常

    1、异常的概述

    异常定义:在程序中,发生“不正常”的事件,导致程序无法正常运行,并使JVM中断,称为异常
    生活中的异常:早上起床上课,平时骑车20分钟可以到达教室,由于天气原因或者闹钟响了自动关闭,不能按时到达教室上课,迟到了,此时就属于异常现象。
    捕获异常:当程序在运行时,发生了异常,为了让程序正常执行,需要对异常捕获(catch),称之为捕获异常
    java是面向对象的语言,异常本身很就是一个类(Exception),当发生异常时会创建异常对象,捕获的就是该对象。

      System.out.println("请输入一个数字");
            Scanner sc = new Scanner(System.in);
            // 对可能发生的异常 进行处理
            int num = sc.nextInt();
            if(num%2==0){
                System.out.println("这个数是偶数");
            }
    

    异常代码可能发生异常,当用户输入非数字时,导致程序抛出一个异常对象:

    Exception in thread "main" java.util.InputMismatchException
    	at java.util.Scanner.throwFor(Scanner.java:864)
    

    2、异常关键字 以及层次关系

    a、try:试一试,将可能发生的代码用try包裹,try不能单独出现
    b、catch: 捕获异常,当发生指定的异常对象时,执行catch代码

      System.out.println("请输入一个数字");
            Scanner sc = new Scanner(System.in);
            // 对可能发生的异常 进行处理
            try {
                int num = sc.nextInt();  // 发生异常后,try里面的代码不再执行
                if (num % 2 == 0) {
                    System.out.println("这个数是偶数");
                }
                System.out.println("结束");
            }catch(Exception ee){// 对应的异常类 来捕获对应的异常对象  ,不能确定异常类,可以使用父类Exception
                System.out.println("你的输入不正确");
            }
    
            System.out.println("程序继续运行直到结束。。。。");
    

    一个try+多个catch

     	//  抛出的异常 不能被catch捕获,会发生什么?
            try {
                int[] num = {1, 2, 3};
                System.out.println(num[1]); // 没有捕获该异常对象,JVM依然终止运行
                System.out.println(10/0);
            }catch(NullPointerException ee){
                System.out.println("这是空指针异常");
            }catch(ArrayIndexOutOfBoundsException  ee){
                System.out.println("数组下标越界异常");
            }catch(Exception ee){
                // 输出异常 堆栈消息  方便程序员排错(尽可能避免用户看见)
                ee.printStackTrace();
                System.out.println("系统繁忙!"+ee.getMessage());
            }
            System.out.println("程序结束");
    

    c、finally:异常之后的最终处理(无论是否发生异常,程序都执行)
    try...finally结构

    	 try{
                System.out.println("请输入两个数 ,计算两个数相除");
                Scanner sc = new Scanner(System.in);
                int  num1 =  sc.nextInt();
                int num2 = sc.nextInt();
                double  s = num1/num2; // 可能出错
                System.out.println(" try里面结束,结果:"+s);
            }finally{
                System.out.println("无论是否发生异常,都会执行这个语句块,一般用于资源回收");
            }
    
      try...catch...finally结构
    
     try {
                System.out.println("请输入两个数 ,计算两个数相除");
                Scanner sc = new Scanner(System.in);
                int num1 = sc.nextInt();
                int num2 = sc.nextInt();
                double s = num1 / num2; // 可能出错
                System.out.println(" try里面结束,结果:" + s);
            }catch(ArithmeticException ee){
                ee.printStackTrace();
                System.out.println("除数不能为0 !!");
            }catch(Exception ee){
                ee.printStackTrace();
                System.out.println("系统繁忙!!!");
            }finally {
                System.out.println("用于资源回收。");
            }
    

    3、捕获异常

      try...catch...finally
    

    4、抛出异常

      /**
         * 根据下标访问数组元素
         * @param array
         * @param index
         * @return
         */
        public static int getEleByIndex(int [] array , int index){
             // 抛出异常: 可以在异常发生时 或发生之前 创建一个异常对象并抛出
            //  手动抛出一个异常  throw new 异常类([异常消息]);
            if(index <0 || index > array.length-1){
                //抛出异常
                throw new ArrayIndexOutOfBoundsException("你的下标越界了");
            }
            int n =  array[index];
            return n;
        }
    
    public static void main(String[] args) {
              //数组
            int  [] array = {2,1,4,5};
            int index=4;
            // 定义方法访问下标的元素  此时会产生异常 并抛出给方法的调用者
            try {
                int num = getEleByIndex(array, index);
                System.out.println("访问的元素:" + num);
            }catch(ArrayIndexOutOfBoundsException ee){
                System.out.println(ee.getMessage());
            }
            System.out.println("结束。。。");
    
        }
    

    5、异常分类

    由于有些异常时不能直接抛出的,需要先声明才可以抛出,异常可以分为两大类:
    1、编译期异常(check异常或者检查异常):在编译期间检查异常,如果没有处理异常,则编译出错。

     //创建一个文件类的对象
            File  file = new File("d:/aaa.txt");
             // 在写代码(编译之前)时 一定要处理的异常(try..catch 或者 throws),就是编译时异常 
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
    

    2、运行期异常(rentime异常或者运行异常):在运行期间检查异常,编译期可以不处理异常

     // 在运行期间抛出异常  不需要事先处理的  NullPointException是运行异常
            String str=null;
            System.out.println(str.length());
    

    exception中常用的异常类:

    • runtimeException
      • ArrayIndexOutOfBoundsException:数组下标越界异常
      • NullPointerException:空指针异常
      • ArithmeticException:算数异常
      • NumberFormatException :数字格式化异常
      • ClassNotFoundException:类没有找到异常
      • ClassCastException:类转换异常
    • 检查异常(check Exception)
      • IOException:IO操作
      • FileNoteFoundException:文件未找到异常
      • SQLException:
      • EOFException:读写文件尾异常
      • DateFormatException:日期格式化异常
      • SocktException:SocktException

    注意: 对于抛出检查异常,需要使用throws声明,对于抛出运行时异常,必须要使用throws声明
    声明抛出异常语法:

    声明抛出异常语法:  
             public ...  方法名([参数]) throws 异常类1,异常类2{
                 
                  // 通过throw抛出   或 处理 检查异常 
          }
    

    面试题:关于finally和return的执行顺序?

    回答: 当方法有返回值时,先执行fianlly,再return, 但是 finally的代码不会改变return结果

      /**
         *  方法有返回值 有 finally
         * @param n
         * @return
         */
        public static  int  getNum(int n){
              try{
                    if(n%2==0){
                        n++;
                    }else{
                        n--;
                    }
          
                 return n;    
              }catch(Exception ee){
                  System.out.println("catch--"+n);
                return 0;
              }finally {
                  // return 如果放在 try或catch中,不会受finally的改变
                  //  如果放在最下面,会受finally的改变
                  n++; // 5
                  System.out.println("fially----n:" + n); // 5
              }
        }
    

    结果返回

    fially----n:5
    4
    

    6、自定义异常

    1、为什么需要使用自定义异常

    在java中每一个异常类都表示特定的异常类型,例如NullPointException表示算术异常,但是 sun公司提供的APP中不可能将实际项目中的业务问题全部定义为已知的异常类,这是需要程序员根据业务需求来定制异常类,例如用户注册,可以定义用户注册异常(RegesterException),分数不能为负数也可以定义异常(ScoreException)

    2、什么是自定义异常

    在开发中根据自己的业务情况来定义异常类,灵活性搞,且方便使用

    3、如何实现自定义异常

    a、定义编译期异常类,创建一个类继承java.lang.Exception;
    b、定义运行期异常类,创建一个类继承java.lang.Exception;

    4、案例分析

    要求:模拟用户注册操作,用户输入用户名,验证用户名是否存在,如果存在,则抛出一个异常消息“亲,该用户已存在,不能注册”,通过自定义异常提示消息

    public class RegisterException  extends  Exception {
        public RegisterException(){
    
        }
    
        public RegisterException(String message){
            // 将message 赋值给父类的构造
            super(message); //  将message赋值给父类的 属性,可通过getMessage()方法
    
        }
    }
    
    public class TestRegister {
         // 模拟已存在的用户
        String []  users = {"袁魏巍","王麻子","王小花"};
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入你要注册的用户:");
            String uname = sc.next();
            TestRegister obj = new TestRegister();
    
            try {
                // 调用方法
                obj.checkUserName(uname);
                System.out.println("注册成功");
            } catch (RegisterException e) {
                System.out.println("注册失败");
                System.out.println(e.getMessage());
            }
    
    
        }
        /**
         * 检查用户是否存在
         * @param username
         * @return   true  表示通过
         *    异常表示不通过
         */
        public boolean  checkUserName(String username) throws RegisterException{
             // 使用foreach遍历
            /**
             *   for(数据类型 变量名  : 数组名/集合名 ){
             *        循环中的 变量名代表的就是数组的元素
             *   }
             */
            for(String  u : users){
                // 判断u是否与 username相等 ,相等说明用户存在,需要抛出异常
                if(u.equals(username)){
                    throw new RegisterException("亲,"+username+" 已存在,不能注册");
                }
            }
            return true;
        }
    }
    
  • 相关阅读:
    R-时空可视化
    zz温故知新:Tomcat调优&JVM内存性能调优
    《CarbonData》
    《RocketMQ》
    《LinuxTools》
    《为什么说 Prometheus 是足以取代 Zabbix 的监控神器?》
    《Zabbix》
    zz《百度地图商业选址》
    《Dapper》
    BZOJ 1601: [Usaco2008 Oct]灌水 最小生成树_超级源点
  • 原文地址:https://www.cnblogs.com/zzk201/p/13854684.html
Copyright © 2020-2023  润新知