Java基础 内部类 异常try catch throw RuntimeException

内部类

  • 将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
  • 访问特点:
    • 内部类可以直接访问外部类中的成员,包括私有成员。
    • 而外部类要访问内部类中的成员必须要建立内部类的对象。

内部类访问规则

  1. 内部类可以直接访问外部类中的成员,包括私有。
    • 之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
  2. 外部类要访问内部类,必须建立内部类对象。

访问格式:

  1. 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。可以直接建立内部类对象。
    • 格式
    • 外部类名.内部类名 变量名 = 外部类对象.内部类对象;
    • Outer.Inner in = new Outer().new Inner();
  2. 当内部类在成员位置上,就可以被成员修饰符所修饰
    • 比如,private:将内部类在外部类中进行封装。
    • static:内部类就具备static的特性
    • 当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
    • 在外部其他类中,如何直接访问static内部类呢?
    • Outer.Inner.function();

注意:

  • 当内部类中定义了静态成员,该内部类必须是static的。
  • 当外部类中的静态方法访问内部类时,内部类也必须是static的。

package 内部类1;

class Outer
{
    private int x=10;

    class Inner//内部类
    {
        int x=1;//内外有同名变量时
        void function(){
            System.out.println("inner:"+Outer.this.x);
            //用"外部类名"调用外部类的成员变量供内部类使用
        }
    }
    /*
    class Inner
    {
        void function(){
            System.out.println("inner:"+x);//内部类可以直接使用外部类的成员变量
        }
    }
    */
    void method()
    {
        Inner in=new Inner();//外部类使用内部类,需要创建对象
        in.function();
    }
}



public class InnerClassDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Outer out=new Outer();
        out.method();
    }

}

输出:
inner:10


//直接访问内部类的成员。
        Outer.Inner in=new Outer().new Inner();
        in.function();
内部类可以使用 private 修饰

内部类定义在局部时

  1. 不可以被成员修饰符修饰
  2. 可以直接访问外部类中的成员,因为还持有外部类中的引用。
  3. 但是不可以访问它所在的局部中的变量。只能访问被 final 修饰的局部变量。
class Outer
{
    int x=3;

    void method()
    {
        final int y=4;
        class Inner
        {
            void function()
            {
                System.out.println(y);
            }
        }
        new Inner().function();
    }
}

class InnerClassDemo3
{
    public static void main(String[] args)
    {
        new Outer().method();
    }
}

匿名内部类

  1. 匿名内部类其实就是内部类的简写格式。
  2. 定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
  3. 匿名内部类的格式: new 父类或者接口(){定义子类的内容}
  4. 其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。
  5. 匿名内部类中定义的方法最好不要超过3个。

    abstract class AbsDemo
    {
         abstract void show();
    }
    
    class Outer
    {
         int x=3;
    
         public void function()
         {
             new AbsDemo()//匿名内部类
             {
                 void show()
                 {
                     System.out.println("x==="+Outer.this.x);
                 }
             }.show();
         }
    }
    class Test
    {
         public static void main(String [] args)
         {
             Outer ot=new Outer();
             ot.function();
         }
    }
静态方法获取内部类
题目:
interface Inner
{
    public abstract void method();
}

class Outer
{
    //补充代码
    static  function()
    {

    }
}

class InnerDemo
{
    public static void main(String [] args)
    {
        Outer.function().method();
    }
}
实现
interface Inner
{
    public abstract void method();
}

class Outer
{

    static Inner function()
    {
        return new Inner()
        {
            public void method()
            {
                System.out.println("Inner method.");
            }
        };  
    }
}

class InnerDemo
{
    public static void main(String [] args)
    {
        Outer.function().method();//调用类静态方法得到一个内部类引用,并使用他的方法method();
    }
}

异常

1.异常概述

异常:就是程序在运行时出现不正常情况
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。
其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分:
  1. 严重的问题
  2. 非严重的问题

对于严重的,java通过Error类进行描述.
对于Error一般不编写针对性的代码对其进行处理。

对于非严重的,java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。


2.异常的处理 try catch

java提供了特有的语句进行处理。

try
{
    需要被检测的代码;
}
catch(异常类  变量)
{
    处理异常的代码;(处理方式)
}
finally
{
    一定会执行的语句;
}

对捕获到的异常对象进行常见方法操作
String getMessage();获取异常信息

class Demo
{
    int div(int a,int b)
    {
        return a/b;
    }
}

public class ExceptionDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Demo d=new Demo();
        try
        {
            int x=d.div(4, 0);
            System.out.println("x=="+x);
        }
        catch(Exception e)
        {
            System.out.println("除零了");
            System.out.println(e.getMessage());//   /by zero;
            System.out.println(e.toString());// 异常名称:异常信息。

            e.printStackTrace();//异常名称,异常信息,异常出现的位置
                                //其实jvm默认的异常处理机制,就是在调用printStackTrace()方法,打印异常的堆栈的跟踪信息。
        }

        System.out.println("Over");
    }

}

输出:
除零了
/ by zero
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zeroOver

at 异常.异常概述.Demo.div(ExceptionDemo.java:7)
at 异常.异常概述.ExceptionDemo.main(ExceptionDemo.java:18)

3.异常声明throws

class Demo
{
    int div(int a,int b)throws Exception//在功能上通过throws的关键字声明了该功能有可能会出现问题。
    {
        return a/b;
    }
}

public class ExceptionDemo 
{
    public static void main(String[] args)throws Exception //main把Exception抛出给虚拟机处理
    {
        // TODO Auto-generated method stub
        Demo d=new Demo();
        int x=d.div(4, 0);
        System.out.println("x="+x);
    }
}
也可以去掉main的throws 自己使用try catch处理异常
try
        {
            int x=d.div(4, 0);
            System.out.println("x=="+x);
        }
        catch(Exception e)//Exeption e = new ArithmeticException();
        {

            e.printStackTrace();//异常名称,异常信息,异常出现的位置
                                //其实jvm默认的异常处理机制,就是在调用printStackTrace()方法,打印异常的堆栈的跟踪信息。
        }

4.对多异常的处理

  1. 声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
  2. 对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。
  3. 如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
    建议在catch处理时,catch中一定要定义具体处理方式。
    不要简单定义一句 e.printStackTrace();
    也不要简单的就书写一条输出语句。
class Demo
{
    int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//丢出指定异常
    {
        int[] arr = new int[a];
        System.out.println(arr[4]);
        return a/b;
    }
}
public class ExceptionDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Demo d=new Demo();

        try
        {
            int x=d.div(4, 0);
            System.out.println("x=="+x);
        }
         //捕获指定异常
        catch(ArithmeticException e)//Exeption e = new ArithmeticException();
        {
            System.out.println(e.toString());
            System.out.println("被零除了");
        }
        catch(ArrayIndexOutOfBoundsException e)
        {
            System.out.println(e.toString());
            System.out.println("角标越界");
        }
        catch(Exception e)
        {
            System.out.println(e.toString());
        }

        System.out.println("Over");
    }

}

5.自定义异常

因为项目中会出现特有的问题,而这些问题未被java所描述并封装对象。
所以对于这些特有的问题可以按照java的对问题封装的思想。
将特有的问题,进行自定义的异常封装。

需求:在本程序中,对于除数是-1,也视为是错误的是无法进行运算的。
那么就需要对这个问题进行自定义的描述。

当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
要么在内部try catch处理。
要么在函数上声明让调用者处理。

一般情况下函数内出现异常,函数上需要声明。

如何定义异常信息?

自定义异常:
必须是自定义类继承 Exception

继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。
只有这个体系中的类和对象才可以被throws和throw操作

package 异常.自定义异常;

class FuShuException extends Exception
{
    private int value;
    FuShuException()
    {
        super();
    }
    FuShuException(String msg)
    {
        super(msg);
    }
    FuShuException(String msg,int value)
    {
        super(msg);
        this.value=value;
    }
    int getValue()
    {
        return this.value;
    }
}
class Demo
{

    int div(int a,int b)throws FuShuException
    {
        if(b<0)
            throw new FuShuException("出现负数.",b);
        return a/b;
    }
}


public class ExceptionDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Demo d=new Demo();
        try
        {
            d.div(5, -2);
        }
        catch(FuShuException e)
        {
            System.out.println(e.toString());
            System.out.println("负数是:"+e.getValue());
        }
    }

}

输出:
异常.自定义异常.FuShuException: 出现负数.
负数是:-2


throws和throw的区别

throws使用在函数上。
throw使用在函数内。

throws后面跟的异常类,可以跟多个。用逗号隔开。
throw后面跟的是异常对象。

RuntimeException

Exception中有一个特殊的子类异常RuntimeException运行时异常。
RuntimeException的子类使用throw在函数内抛出,不需要在函数上使用throws声明。编译一样通过。
并且在调用函数内不用try catch处理。编译一样通过。

之所以不用在函数声明,是因为不需要让调用者处理。
当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正。

自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException.

对于异常分两种:
1. 编译时被检测的异常。
2. 编译时不被检测的异常(运行时异常。RuntimeException以及其子类)

package 异常.RuntimeException;

class FuShuException extends RuntimeException
{
    FuShuException(String msg)
    {
        super(msg);
    }
}
class Demo
{
    int div(int a,int b)
    {
        if(b<0)
            throw new FuShuException("出现了除数为负数");
        if(b==0)
            throw new ArithmeticException("被零除了 /0");
        return a/b;
    }
}

public class ExceptionDemoR {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Demo d=new Demo();
        int x=d.div(4, -1);
        System.out.println("x="+x);
    }

}

Exception in thread “main” 异常.RuntimeException.FuShuException: 出现了除数为负数
at 异常.RuntimeException.Demo.div(ExceptionDemoR.java:15)
at 异常.RuntimeException.ExceptionDemoR.main(ExceptionDemoR.java:27)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值