1. 程式人生 > >Java基礎 內部類 異常try catch throw RuntimeException

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)