內部類就是在一個已經定義好的類內部再用class關鍵字定義的類
內部類包括:靜態內部類、非靜態內部類(普通內部類);局部內部類、匿名內部類
重要結論:
- 內部類(不論是靜態內部類還是非靜態內部類)都是在第一次使用時才會被加載
- 非靜態內部類對象的創建依賴于外部類對象
- 非靜態內部類的對象隱士持有指向外部類對象的引用
- 非靜態內部類可以無限制地訪問外部類對象的成員變量和方法
- 靜態內部類只是在代碼形式上寫在一個外部類里,但在Java虛擬機中它是作為一個靜態類加載,與外部類無關
普通內部類與靜態內部類
最明顯的特征就是是否用static修飾
public class OutterClass {
//普通內部類
class InnerClass{
}
//靜態內部類
static class InnerClass2{
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
注意:靜態內部類前是用static修飾的。
普通內部類
普通內部類可直接訪問外部類的所有成員,靜態內部類不能直接訪問非static屬性的成員,需要用外部對象的引用才能訪問。
下面分別是普通內部類和靜態內部類的實例化:
普通內部類需要用外部類的實例再進行相應內部類的實例化
靜態內部類則可以直接進行實例化
public class OutterClass {
private int a = 10;
private static int b = 11;
//普通內部類
class InnerClass{
void print(){
//訪問外部private成員
System.out.println(a);
}
}
//靜態內部類
static class InnerClass2{
void print(){
//直接訪問非static變量報錯
//System.out.println(a);
//通過外部對象的引用來訪問非static變量
OutterClass out = new OutterClass();
System.out.println(out.a);
//直接訪問外部static變量
System.out.println(b);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//實例化靜態類InnerClass2
InnerClass2 in2 = new InnerClass2();
in2.print();
//實例化普通內部類
InnerClass in = new OutterClass().new InnerClass();
in.print();
}
}
局部內部類和匿名內部類
局部內部類就是定義在某個方法中的類
局部內部類可以訪問外部類的所有成員、方法的局部變量、方法的形參,不一定需要final修飾(Java SE8),但要保證局部變量不被二次賦值。
局部內部類和普通內部類是相似的因為他們都不能被定義或聲明靜態成員,如果局部內部類在靜態方法內被定義那么這個局部內部類就只能訪問方法的靜態成員。不能在局部內部類中聲明接口,因為接口本身就是靜態的(inherently static)。局部內部類不能包含靜態成員除非這個靜態成員是常量(被final修飾)
public void InnerClassFun(int k){
int min = 70;
class InnerClass3{
//局部類中的靜態變量必須是final型的
final static int c = 12;
void print(){
//訪問外部類的static和非static成員
System.out.println(a);
System.out.println(b);
//訪問方法的形參和局部變量
System.out.println(min);
System.out.println(k);
System.out.println(c);
}
}
}
匿名內部類就是沒有名字的內部類,通常是用來作為抽象類或者接口等不能實例化的類的擴展,最常見的例子便是點擊事件以及線程的開啟:
((Button) findViewById(R.id.start)).setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub
}
}.start();
}
});
匿名內部類是不能加訪問修飾符的。要注意的是,new 匿名類,這個類是要先定義的:
public class OutterClass {
public static void main(String[] args) {
Inner in = new OutterClass().getInner("Beijing");
System.out.println(in.getName());
}
public Inner getInner(final String name){
return new Inner(){
private String nameStr = name;
public String getName(){
return nameStr;
}
};
}
interface Inner{
String getName();
}
}
所在的方法的形參需要被內部類里面使用時,該形參必須為final
1.匿名內部類不能有構造方法。
2.匿名內部類不能定義任何靜態成員、方法和類。
3.匿名內部類不能是public,protected,private,static。
4.只能創建匿名內部類的一個實例。
5.一個匿名內部類一定是在new的后面,用其隱含實現一個接口或實現一個類。
6.因匿名內部類為局部內部類,所以局部內部類的所有限制都對其生效。
參考來自:
http://www.lxweimin.com/p/1faacbd5794f
http://android.blog.51cto.com/268543/384844/
內部類的加載時機
深入理解Java中為什么內部類可以訪問外部類的成員