Java基礎 內部類 異常try catch throw RuntimeException
內部類
- 將一個類定義在另一個類的裡面,對裡面那個類就稱為內部類(內建類,巢狀類)。
- 訪問特點:
- 內部類可以直接訪問外部類中的成員,包括私有成員。
- 而外部類要訪問內部類中的成員必須要建立內部類的物件。
內部類訪問規則
- 內部類可以直接訪問外部類中的成員,包括私有。
- 之所以可以直接訪問外部類中的成員,是因為內部類中持有了一個外部類的引用,格式 外部類名.this
- 外部類要訪問內部類,必須建立內部類物件。
訪問格式:
- 當內部類定義在外部類的成員位置上,而且非私有,可以在外部其他類中。可以直接建立內部類物件。
- 格式
- 外部類名.內部類名 變數名 = 外部類物件.內部類物件;
- Outer.Inner in = new Outer().new Inner();
- 當內部類在成員位置上,就可以被成員修飾符所修飾
- 比如,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 修飾
內部類定義在區域性時
- 不可以被成員修飾符修飾
- 可以直接訪問外部類中的成員,因為還持有外部類中的引用。
- 但是不可以訪問它所在的區域性中的變數。只能訪問被 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();
}
}
匿名內部類
- 匿名內部類其實就是內部類的簡寫格式。
- 定義匿名內部類的前提:內部類必須是繼承一個類或者實現介面。
- 匿名內部類的格式: new 父類或者介面(){定義子類的內容}
- 其實匿名內部類就是一個匿名子類物件。而且這個物件有點胖。可以理解為帶內容的物件。
匿名內部類中定義的方法最好不要超過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對不正常情況進行描述後的物件體現。
對於問題的劃分:
- 嚴重的問題
- 非嚴重的問題
對於嚴重的,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.對多異常的處理
- 宣告異常時,建議宣告更為具體的異常,這樣處理的可以更具體。
- 對方宣告幾個異常,就對應有幾個catch塊。不要定義多餘的catch塊。
- 如果多個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)