內部類
內部類的訪問規則:
1,內部類可以直接訪問外部類中的成員,包括私有
格式:外部類名.this
2,外部類要訪問內部類,必須建立內部類對象。
訪問格式:
1,當內部類定義在外部類的成員位置上,而且非私有,可以在外部其他類中直接建立內部類對象。
格式:外部類名.內部類 變量名 = 外部類對象.內部類對象;
Outer.Inner in = new Outer().new Inner();
2,當內部類在成員位置上,就可以被成員修飾符修飾
比如,private:將內部類在外部類中進行封裝。
static:內部類可以被靜態修飾,就具備了靜態的特性
當內部類被static修飾後,只能直接訪問外部類中的靜態成員。出現了訪問侷限。
在外部其他類中,如何直接訪問靜態內部類的非靜態成員呢?
new Outer.Inner().function();
在外部其他類中,如何直接訪問靜態內部類的靜態成員呢?
Outer.Inner.function();
注意:
當內部類中定義了靜態成員,該內部類必須是靜態的。
當外部類中的靜態方法訪問到內部類時,內部類也必須是靜態的。
class Outer
{
private int x=3;
class Inner //內部類
{
int x=4;
void function()
{
int x=6;
System.out.println("inner:"+Outer.this.x);
//打印結果是3,裏面換成this.x打印的是4,直接打印x是6
}
}
void method()
{
Inner in = new Inner();
in.function();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
//Outer out = new Outer();
//out.method();
//直接訪問內部類中的成員
Outer.Inner in = new Outer().new Inner();
in.function();
}
}
內部類定義在局部時,
1,不可以被成員修飾符修飾。如static
2,可以直接訪問外部類中的成員,因爲還持有外部類中的引用
但是不可以訪問它所在的局部中的變量,只能訪問被final修飾的局部變量。
class Outer
{
int x = 3;
void method(final int a)
{
final int y = 4;
class Inner
{
void function()
{
System.out.println(a);
}
}
new Inner().function();
}
}
class InnerClassDemo3
{
public static void main(String[] args)
{
//new Outer().method();
Outer out = new Outer();
out.method(7);
out.method(8);
}
}
匿名內部類
1,匿名內部類其實就是內部類的簡寫格式。
2,定義匿名內部類的前提:
內部類必須是繼承一個類或者實現接口
3,匿名內部類的格式:new 父類或者接口(){定義子類的內容}
4,其實匿名內部類就是一個匿名子類對象。帶內容的對象。
5,匿名內部類中定義的方法最好不要超過三個。
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x = 3;
/*
class Inner extends AbsDemo
{
void show()
{
System.out.println("method:"+x);
}
}
*/
public void function()
{
//new Inner().show();
new AbsDemo()//匿名內部類
//AbsDemo ab = new AbsDemo()
{
void show()
{
System.out.println("x="+x);
}
}.show();
}
}
class InnerClassDemo4
{
public static void main(String[] args)
{
new Outer().function();
}
}
練習:
class Test
{
//補足代碼,通過匿名內部類。
/*
static class Inner implements Inter
{
public void method() //這是有名字的方法,效果與下面的匿名方法一樣
{
System.out.println("method run");
}
}
*/
static Inter function()
{
return new Inter()
{
public void method()
{
System.out.println("method run");
}
};
}
}
class InnerClassTest
{
public static void main(String[] args)
{
//Test.function():Test類中有一個靜態的方法function。
//.method():function這個方法運算後的結果是一個對象,而且是一個Inter類型的對象。
//因爲只有是Inter類型的對象,纔可以調用method方法。
Test.function().method();
Inter in = Test.function();
in.method();
}
}
異常
異常:程序在運行時出現的不正常情況。
異常由來:問題也是現實生活中一個具體的事物,也可以通過java的類的形式進行描述,並封裝成對象。 也就是java對不正常情況進行描述後的對象體現。
對於問題的劃分:一種是嚴重的問題,一種是非嚴重的問題。
對於嚴重的,java通過Error類進行描述。
對於Error一般不編寫針對性的代碼對其進行處理。
對於非嚴重的,java通過Exception類進行描述。
對於Exception可以使用針對性的處理方式進行處理。
無論Error或者Exception都具有一些共性內容
比如:不正常情況的信息:引發原因等
Throwable
|–Error
|–Exception
2,異常的處理
java提供了特有的語句進行處理
try
{
需要被檢測的代碼
}
catch(異常類 變量)
{
處理異常的代碼;(處理方式)
}
finally
{
一定會執行的語句;
}
3,對捕獲到的異常對象進行常見方法操作
String getMessage():獲取異常信息
class Demo
{
int div(int a,int b)
{
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,0);
System.out.println("x="+x);
}
catch(Exception e)//Exception e = new ArithemeticException();
{
System.out.println("feifa");
System.out.println(e.getMessage());// /by zero
System.out.println(e.toString());//異常名稱:異常信息
e.printStackTrace();//異常名稱,異常信息,異常出現的位置。
//其實jvm默認的異常處理機制,就是在調用printStackTrace方法。
//打印異常的堆棧的跟蹤信息。
}
System.out.println("over");
}
}
在函數上聲明異常。
便於提高安全性,讓調用者進行處理,不處理編譯失敗。
1,要麼拋出去
class Demo
{
int div(int a,int b) throws Exception//在功能上通過throws的關鍵字聲明瞭
//該功能可能會有的問題
{ //把問題拋出去
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args) throws Exception
{
Demo d = new Demo();
int x = d.div(4,0);
System.out.println("x="+x);
System.out.println("over");
}
}
要麼try,catch處理
class Demo
{
int div(int a,int b) throws Exception//在功能上通過throws的關鍵字聲明瞭
//該功能可能會有的問題
{ //把問題拋出去
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,0);
System.out.println("x="+x);
}
catch(Exception e)//Exception e = new ArithemeticException();
{
System.out.println("feifa");
System.out.println(e.toString());//異常名稱:異常信息
}
System.out.println("over");
}
}
對多異常的處理
1,聲明異常時,建議聲明更爲具體的異常,這樣處理的更具體。
2,對方聲明幾個異常,就對應有幾個catch塊,不要定義多餘的catch塊
如果多個catch塊中的異常出現繼承關係,父類異常catch塊放在最下面
建議在進行catch處理時,catch中一定要定義具體處理方式。
不要簡單定義一句e.printStackTrace(),
也不要簡單的書寫一條輸出語句。
自定義異常
因爲項目中會出現特有的問題,
而這些問題並未被java所描述並封裝對象
所以對於這些特有的問題可以按照java的對問題封裝的思想
將特有的問題,進行自定義的異常封裝。
自定義異常
需求:在本程序中,對於除數是負數,也認爲是錯誤的,是無法進行運算的
那麼就需要對這個問題進行自定的描述
當在函數內部出現throw拋出異常對象,那麼就必須要給對應的處理動作。
要麼在內部try catch處理
要麼在函數上聲明讓調用者處理。
一般情況下,函數內出現異常,函數上需要聲明。
class FuShuException extends Exception
{
}
class Demo
{
int div(int a,int b)throws FuShuException
{
if(b<0)
throw new FuShuException();//手動通過throw關鍵字拋出一個自定義異常對象。
return a/b;
}
}
class ExceptionDemo3
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
System.out.println("除數是負數");
}
System.out.println("over");
}
}
發現打印的結果中只有異常的名稱,沒有異常的信息
因爲自定義的異常並未定義信息
如何定義異常信息呢?
因爲父類中已經把異常信息的操作都完成了。
所以子類只要在構造時,將異常信息傳遞給父類通過super語句
那麼就可以直接通過getMessage方法獲取自定義的異常信息
class FuShuException extends Exception
{
private int value;
FuShuException(String msg,int value)
{
super(msg);
this.value = value;
}
public int getValue()
{
return value;
}
}
class Demo
{
int div(int a,int b)throws FuShuException
{
if(b<0)
throw new FuShuException("/ by fushu",b);//手動通過throw關鍵字拋出一個自定義異常對象。
return a/b;
}
}
class ExceptionDemo3
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
System.out.println("錯誤的負數是:"+e.getValue());
}
System.out.println("over");
}
}
自定義異常:必須是自定義類繼承Exception
繼承Exception原因
異常體系有一個特點:因爲異常類和異常對象都被拋出
他們都具備可拋性。這個可拋性是Throwable這個體系的獨有特點。
只有這個體系中的類和對象纔可以被throws和throw操作。
throws和throw的區別
throws使用在函數上
throw使用在函數內
throws後面跟的是異常類,可以跟多個,用逗號隔開
throw後面跟的是異常對象。
——————————————————————————————
Exception中有一個特殊的子類異常RunTimeException(運行時異常)
特殊之處:
如果在函數內容拋出該異常,函數上可以不聲明,編譯一樣通過
如果在函數上聲明該異常,調用者可以不用進行處理,編譯一樣通過。
之所以不用在函數上聲明,是因爲不需要讓調用者處理
當該異常發生,希望該程序停止,因爲在運行時,出現了無法繼續運算的情況,希望停止程序後,
對代碼進行修正。
自定義異常時:如果該異常的發生,無法在繼續進行運算
就讓自定義異常繼承RuntimeException
對於異常分兩種,
1,編譯時被檢測的異常
2,編譯時不被檢測的異常(運行時異常。RuntimeException以及其子類)
class FuShuException extends RuntimeException
{
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b) //throws ArithmeticException
{
if(b<0)
throw new FuShuException("出現了除數爲負數了");
if(b==0)
throw new ArithmeticException("被零除了");
return a/b;
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
int x = d.div(4,-9);
System.out.println("x="+x);
System.out.println("over");
}
}