内部类、异常

内部类(Inner class)

1.内部类的作用 : 一般用于服务于外部类

(1),内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

(2),内部类成员可以直接访问外部类的私有数据;但外部类不能访问内部类的实现细节,如内部类的成员变量;

(3),匿名内部类适合用于创建仅需使用一次的类。

2.概念

内部类也就是定义在类内部的类。

内部类是一个编译时的概念。

编译成功:外部类内部类名.class  (OuterInner.class)

3. 内部类的分类:

  • (1) 成员内部类(Member inner class)、
  • (2) 局部内部类(Local inner class)、
  • (3) 静态内部类(Static inner class)、
  • (4) 匿名内部类(Anonymous inner class)
1. 成员内部类
   class A{
   	int a =10;
   	class B{}
   }
1. 静态内部类
   class A{
   	static int a =10;
   	static class B{}
   }
1. 局部内部类
   class A{
       public void fun(){
           int a =10;
           class B{}
       }
   }
2. 匿名内部类
   new A(new B(){		
   	public void fun(){//重写B接口(抽象类)的方法
   	}
   });
(1)成员内部类(Member Inner Classes)
特征:

      (a)、相当于外部类中的一个普通成员方法;

      (b)、相当于外部类中的一个普通成员属性;

成员定义:

      不能在成员内部类中定义静态属性和静态方法。

 特征:为什么成员内部类中不能定义静态成员?

	 *      因为外部类被加载时,成员内部类还没有被加载。
        从外到内:
              (a)、非静态方法:
                     必须创建内部类的对象,然后通过对象方法,则可以访问内部类中的所有属性和方法
              (b)、静态方法 和 其他的类:
                     必须先创建外部类的对象,然后通过外部类对象再创建内部对象。
                     Inner inner = new Outer().new Inner();
        从内到外:
              (a)、成员内部类可以访问外部类中所有的属性和方法;
              (b)、外部类、内部类、内部类的方法中出现同名
                     temp
                     this.temp
                     Outer.this.temp
  • 示例:

    //成员变量、成员方法、成员内部类 === 为外部类服务
    public class Outer {

      //成员变量
      public int a = 10;
      //成员方法
      public void fun1(){}
      //成员内部类
      class Inner{
          //内部类的 成员变量
          //内部类的成员方法
      }
    

    }

    //测试
    public class TestInnerClass {
    public static void main(String[] args) {
    Outer outer = new Outer();

          outer.a =20;  //成员变量: 对象名.变量名
          outer.fun1(); //成员方法: 对象名.方法名
          outer.new Inner(); //内部类对象 new Inner();   //成员内部类: 外部类对象.内部类对象
      }
    

    }

(2)静态成员内部类(Static Inner Class)
特征:

      (a)、相当于外部类中的一个静态成员方法;

      (b)、相当于外部类中的一个静态成员属性;

成员定义:

      可以在成员内部类中定义静态属性和静态方法。

从外到内:

  (a)、非静态方法 和 静态方法:

          必须创建静态内部类的对象,然后通过对象方法,则可以访问静态内部类中的所有属性和方法;

  (b)、other其他的类:

     

     Inner inner = new Inner();
    Inner inner = new Outer.Inner();

    从内到外:

          (a)、非静态方法:

                  只能访问外部类中的静态属性和静态方法;

          (b)、静态方法:

                  只能访问外部类中的静态属性和静态方法;



public class Outer {
    static  int x = 10;

    static class Inner{}

}

public class TestStaticInnerClass {
    public static void main(String[] args) {

        Outer outer = new Outer();
        Outer.x  = 50;
        //创建静态内部类对象
        Outer.Inner inner = new Outer.Inner();

    }
}
(3)局部内部类(Local Inner Classes):
 定义在某个方法中类, 把局部内部类看作为某个方法中一个普通变量。

 特征:
 *     1、不能被4种访问控制符所修饰,也不能被static修饰,
 *        但是可以被final、abstract所修饰。
 *     2、局部内部类中不能定义静态成员(方法和属性)。

     非静态方法
           特征:
                 相当于一个普通的方法。
       //    成员定义:
        //         可以在成员内部类中定义静态属性和静态方法。
           从内到外:
                 (a)、可以作为一个普通的方法,访问外部类中的所有的成员属性和成员方法;
                 (b)、如果局部内部类要访问所在方法中的定义的变量,则该变量必须为常量;
           从外到内:
                 必须通过外部类的方法(作为入口),并且一定要在方法结束之前将局部内部类的对象创建完成,然后局部内部类中的方法;
     静态方法
           特征:
                 相当于一个静态的方法;
           成员定义:
                 可以在成员内部类中定义静态属性和静态方法。
           从内到外:
                 (a)、可以作为一个静态的方法,访问外部类中的所有的静态属性和静态方法;
                 (b)、如果局部内部类要访问所在方法中的定义的变量,则该变量必须为常量;
           从外到内:
                 必须通过外部类的方法(作为入口),并且一定要在方法结束之前将局部内部类的对象创建完成,然后局部内部类中的方法;
(4)匿名内部类(Anonymous Inner Calsses):
 是一个特殊的局部内部类。

 分析:

        怎么使用匿名内部类继承一个父类?

        怎么使用匿名内部类实现一个接口?

        答:直接new 父类或者接口。

在使用匿名内部类时,要记住以下几个原则:
 ·匿名内部类不能有构造方法。  
 ·匿名内部类不能定义任何静态成员、方法和类。  
 ·匿名内部类不能是public,protected,private,static。  
 ·只能创建匿名内部类的一个实例。
  ·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。  
 ·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。			  

	

	匿名类和内部类中的中的this :

	有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。

public class MainBoard {

    public MainBoard(Cpu cpu){

    }
}

public interface Cpu {
    public void cpuRun();
}

public class DellCpu implements Cpu {
    @Override
    public void cpuRun() {

    }
}

public class TestCpu {
    public static void main(String[] args) {


        Cpu cpu = new DellCpu();
        MainBoard mainBoard1 =   new MainBoard(cpu);

        //匿名内部类
       new MainBoard(new Cpu(){

           @Override
           public void cpuRun() {

           }
       });
    }
}

异常

1. 异常的分类

Throwable有两个子类:Error和Exception。

(1) Error: 硬件故障,程序员无法解决 。一个Error对象表示一个程序错误,指的是底层的、低级的、不可恢复的严重错误。此时程序一定会退出,因为已经失去了运行所必须的物理环境。对于Error错误我们无法进行处理,因为我们是通过程序来应对错误,可是程序已经退出了。

(2)Exception 程序员疏忽造成, 我们可以处理的Throwable类中只有Exception类的对象(例外/异常)。
			  抛出一个异常,就是抛出该异常的对象,如果不对其进行捕捉,就由JVM来捕捉,JVM捕捉到该异常后, 就把异常信息打印到控制台。

 Exception有两类:
(a)Runtime exception(运行时异常)可以在编程时避免,可处理可不处理. 。总是由虚拟机 接管。比如:我们从来没有人去处理过NullPointerException 异常,它就是运行时异常,并且这种异常还是最常见的异常之一。

(b) checked exception(编译时异常)必须进行处理。对于这种异常, JAVA 编译器强制要求我们必需对出现的这些异常进行catch 。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch 块去处理可能的异常
  • 注意:

    当一个方法中出现了异常,没有进行异常处理,方法就会把异常对象作为返回值返回。如果有异常进入虚拟机,那么虚拟机就会立刻中止程序的执行。

  1. 常见异常:

    (1)、ArrayIndexOutOfBoundsException 数组越界异常
    (2)、NullPointerException 空指针引用异常(引用对象指向空)
    (3)、ArithmeticException 除数为0异常

二.自定义异常

示 例

  /**
	- 银行系统异常的超级父类
*/
public class BankSystemException extends RuntimeException{
    public BankSystemException(){
        super("银行系统有异常");
    }

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

/**
 *银行系统中的异常子类,账户余额不足异常
 */
public class BalanceNotEnoughException extends  BankSystemException{
    public BalanceNotEnoughException(){
        super("账户余额不足");
    }
    public BalanceNotEnoughException(String message) {
        super(message);
    }
}

/**
 * 银行账户类
 */
public   class Account {
    //取款
    public Account withdraw(double money) throws BalanceNotEnoughException{
        if(this.accBalance < money)
                throw  new BalanceNotEnoughException("账户余额不足,请重新输入取款金额");
        else
            this.accBalance -= money;
        return this;
    }
    //转账
    public Account transferAccount(Account account,double money) throws BalanceNotEnoughException {
        if(this.accBalance < money)
            throw  new BalanceNotEnoughException("账户余额不足,请重新输入转账金额");
        else
            System.out.println("执行转账业务....");
        return this;
    }
}

测试类中:
	Account account = new Account();
    account.setAccBalance(1000);

    account.withdraw(1300);
    account.transferAccount(null,1200);

1. 自定义异常类:在进行程序开发的过程中,自定义异常类遵循以下四个步骤:

  1)首先创建自定义异常类,语法格式:a. 自定义编译时异常类名 extends Exception。
							     b.自定义运行时异常类名 extends RuntimeException。

  2)在方法中通过关键字throw抛出异常对象。

  3)若是在当前抛出异常的方法中处理异常,可以用try-catch语句捕获并处理;若不是,在方法的声明处通过关键字throws指明要抛出给方法调用的异常。

  4)在出现异常方法的调用中捕获并处理异常。

2. throws关键字

(1)在定义一个方法的时候,可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而是交给方法的调用处去处理。
(2)throws使用格式:
public 返回值类型  方法名称(参数列表)throws 异常类{}

3. throw关键字

throw关键字的作用是在程序抛出一个异常,抛出的是一个异常类的实例化对象。
与throws不同的是,可以直接使用throw抛出一个异常。抛出的时候直接抛出异常类的实例化对象即可。

4. 异常的处理

处理原则: 自己的问题 自己处理。
	(1)抛给调用方处理,在方法处throws XXException
	(2)使用try-catch处理

5. 异常处理try-catch-finally

(1)、try{}  把可能会出现异常的代码放入try块中。
(2)、catch(XX xx){} 捕获异常,并进行相应处理。
	  A.一个try{} 多个catch{}
	  B.万能捕捉器 Exception
	  C.注意使用万能捕捉器的顺序,先子类后父类
(3)finally :写资源释放的代码 。

6. 语法使用:

try{} 和catch(){},catch(){}
try{} 和catch(){}及finally{}
try{} 和finally{}
try{} 和catch(){} .....try{} 和catch(){}

try{
 //捕捉异常的语句
}catch(异常类 异常对象){
 //异常的处理语句
}catch(异常类  异常对象){
 //异常的处理语句
}
[finally{
  //一定会执行的语句
  
  }]
  • 注意:

    try{

    }catch(…Exception e){

    }

    try{

    }catch(…Exception e){

    }

    public void  transfer(Account anotherAccount,double money) throws AccountNotFoundException, ParseException{}
    
      	try {
              account1.transfer(account2, 1000000);
          }catch (AccountNotFoundException e){
             //异常处理
          } catch (ParseException e) {
                //异常处理
          }
    
    1. try{
      try{

      }catch(){

      }
      }catch(){

    }

    (1).catch块一定要与try块一起使用,不能够单独使用catch语句块;
    (2).一个try块可以有多个catch块,但是,多个catch块的排序必须是从特殊到一般异常子类后一个一般是Exception类;
    (3).如果不发生异常,catch语句块永远不会执行;
    (4).一旦某个catch块被执行后,其他catch就都会被忽略;
    (5).try-catch结构是可以嵌套使用的;

    finally:【出现try之后,资源释放的代码 】。
    a)、try 或者 catch代码块执行完成之后。
    b)、finally后的代码块是无论如何都会被执行的代码。
    一般finally()代码块在写释放资源的代码。
    c)finally 代码块中最好不要出现返回语句(return);

    每个异常出现之后,会在程序中产生一个异常类来实例化对象,之后用
    此对象与catch中的异常类型相匹配,如果匹配成功,则执行catch中的内容,
    否则向下继续匹配,如果无法成功,程序就出现中断执行的问题。

    finally 始终能被执行的代码。
    面试题:final\finally\finalize分别用在声明场合?

  1. finally 与 return

    public 基本数据类型 | 引用数据类型 fun(){
    try{
    //…
    return value;
    }catch(…){
    //…
    return value;
    }finally{
    value = 新值;
    }
    }

  • (1)finally 与return 谁先执行
    • finally: 用于释放资源,节省内存,语法上无论是否有异常,都会执行
    • return : 方法结束
    • 先执行return ,再执行finally
  • (2)在finally中,修改return 的返回值变量,最后返回值究竟有没有发生改变?
    • (1)返回值:基本数据类型,finally 中修改返回值变量,返回值不会改变

      • 【值传递】
      • a  -----> 10
        return ---->10 (copy)
        
    • (2)返回值:引用数据类型,finally 中修改返回值变量,返回值会改变

      • 【地址传递】
      • stu 、return  ----->Student("name",'M')
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值