2018.4.22
內部類
成員內部類
人:
成員變量:
體重,性別,血液
成員方法:
睡覺,吃飯,跑步,敲代碼
心臟:
心跳行爲
會使用到人體內的成員變量,血液。
心室和心房
[特徵]
在人類中,有些東西,比如內臟用成員方法或者成員變量描述都閒着有點不太合適,因爲這些內臟是屬於[人類的一部分],而且會使用人體的一些屬性
但是又擁有自己的一些【特徵】
[思考]
能不能把這些器官認爲是一個類,一個屬於人類內部的一個類
內部類:
1.成員內部類
2.局部內部類
3.匿名內部類
內部類和外部類關係:
1.成員內部類可以使用外部類的成員變量和成員方法,不管用什麼權限修飾public private,都可以使用 ,因爲這是在內部類的內部使用。
2.【在外部類的外部創建外部類的內部類對象】
格式如下:
外部類名.內部類名 內部類對象名 = new 外部類().new 內部類名();
例如:
Outer.inner inner = new Outer().new Inner();//第一個new是java虛擬機用的,第二個new是Outer用的
【第一個知識點】:普通的成員變量和成員方法,在沒有對象的情況下,不能在類外使用
3.如果內部類和外部類存在同名的成員變量,這裏默認是就近原則,使用的是內部類的成員變量,如果想要使用外部類的成員的:
格式:
外部類名.this.同名變量;
外部類名.this.同名成員方法(參數列表);
4.在外部類的類內方法中,可以創建內部類的對象。
class Outer {
int num = 100;//外部類的成員變量
private static int s = 10;
public void test() {
System.out.println("外部類的test方法");
}
public void testOuter() {
System.out.println("外部類的成員方法");
}
class Inner {//這是Outer類的一個成員內部類
int i = 10;//成員內部類的成員變量
int num = 50;
public void testInner() {
System.out.println("內部類的成員方法");
//如何調用重名的成員變量。
System.out.println("內部類成員變量:"+num);//請問打印的是50/100(就近原則)
System.out.println("外部類成員變量:"+Outer.this.num);
//如何調用重名的成員方法
//調用自己內部類的成員方法
test();
//調用外部類的成員方法
Outer.this.test();
//內部類調用外部類靜態私有話成員變量
System.out.println(s);
//調用外部類的靜態成員方法
testStatic();
}
public void test() {
System.out.println("內部類的test方法");
}
}
//new Inner().test(); 內部類對象不能在外部類內直接調用方法。
//但是內部類對象可以在外部類的方法中創建,並且在方法中調用內部類方法
//在【外部類】中定義【內部類的類對象】,來完成外部類無法做到的事。
public void createInnerClass() {
//外部類的成員方中調用內部類的構造方法,通過new關鍵字來創建內部類類對象使用
Inner inner = new Inner();
inner.testInner();
}
public static void testStatic () {
System.out.println("外部類的靜態成員方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Outer outer = new Outer();
//outer.createInnerClass();
//想要在這裏創一個Inner類對象
//Entry<K,V> entrySet
//Set<Map.Entry<K,V>>
//數據類型是Outer.Inner 表示是外部類裏面的內部數據類型
//沒有外部類的對象就不能調用成員方法,成員變量或者成員內部類。
//如果創建成員內部類的類對象。
Outer.Inner inner = new Outer().new Inner();
//inner.testOuter();在類外內部類對象不能調用外部類方法
//outer.testInner();在類外外部類對象不能調用內部類的成員方法
inner.testInner();//在類外內部類對象可以直接調用內部類的方法。
outer.testOuter();//在類外外部類對象可以直接調用外部類方法
}
}
結果:
內部類的成員方法
內部類成員變量:50
外部類成員變量:100
內部類的test方法
外部類的test方法
10
外部類的靜態成員方法
外部類的成員方法
局部內部類
局部內部類:放在方法或者函數內的類,稱之爲局部內部類
【第二個知識點】
1.局部變量
【生存期】
從聲明定義位置開始,到代碼塊結束
【作用域】
只能在當前代碼塊內部。
2.類對象的
【生存期】
通過new關鍵字創建的時候開始,JVM垃圾回收機制調用時,銷燬該對象,結束。
【作用域】
哪個引用變量擁有這個對象首地址,哪裏就是他的作用域。
說明:
局部內部類只能函數或者方法中使用,方法或者函數外不能使用。
發現:
局部內部類中,貌似不能【修改】所在方法或者函數中的局部變量
原因:以下內容可以理解。
------------------------------------------------------------------
局部內部類的對象是在函數或者方法的內部通過JVM藉助於New關鍵字,和局部內部類的狗方法,創建
的一個類對象,並且該對象是由JVM的回收機制回收的。
但是局部變量n是在testInner()方法中,而這個局部變量n的生存週期是和testInner()該方法的大括號有關,
生存期和作用域都是在大括號以內。
如果在testInnner的方法內部,MethodInner這個類是方法中的局部內部類,而創建的對象在使用testInner()方法中的局部變量時,
因爲對象的銷燬時間不確定,但是一定是晚於局部變量的銷燬的,
這裏隱含了一個類對象【延遲局部變量中生存週期】的,這個是不符合Java原理的。
這就是爲什麼不能修改,因爲有可能在這個對象吧誒使用的時候,局部變量的內存空間已經被內存收回,
換而言之這個局部變量不存在了!!
爲了解決這個問題
【解決方式】
如果是在局部內部類中使用了蘇在函數或者方法的局部變量,該變量用final修飾
---------------------------------------------------------------------
要求
【第三個知識點】
如果是局部內部類要使用函數或者方法的局部變量,該變量用【final】修飾。
class Test {
int num = 100;
public void testInner() {
//這裏是在方法中定義一個類,這個類只能在當前方法或者函數中使用。
int n = 10;
class MethodInner {
int i = 10;//成員變量在類內任何地方都可以使用。
public void function() {
num = 20;
//n = 20;
System.out.println(i);
System.out.println(num);
System.out.println("局部內部類的成員方法");
}
}
MethodInner inner = new MethodInner();
inner.function();
}
}
public class Demo2 {
public static void main(String[] args) {
// for (int i = 0; i < 10; i++) {
// System.out.println(i);
// }
//System.out.println(i);
new Test().testInner();
}
}
結果:
10
20
局部內部類的成員方法
匿名內部類
【第四個知識點】
類的本體
在類聲明部分,大括號裏面的內容就是類的本體~~
class Test {
//成員變量
//成員方法
}
匿名內部類就是沒有名字的類,但是有類的本體!!!!
【第五個知識點】
看到內部類要認識
哦,這個就是內部類。
//抽象類,所有繼承抽象類的子類都必須實現抽象類的方法。
abstract class Animal {
int age;
public abstract void test();
abstract public void jump();
}
class CodingMonkey extends Animal {//會報錯 必須實現上面兩個方法。
//以下兩個方法是類的本體!!
@Override
public void test() {
System.out.println("這是類本題中的一個成員方法");
}
@Override
public void jump() {
System.out.println("大吉大利,今晚吃雞。");
}
}
interface A {
int i = 0;//默認缺省屬性 順豐 public static final
public void testA();//缺省abstract, 沒有方法體
}
public class Demo3 {
public static void main(String[] args) {
CodingMonkey monkey = new CodingMonkey();
Animal a = new CodingMonkey();//多態,父類的引用指向子類的對象。
a.test();
monkey.test();
monkey.jump();
//抽象類有沒有自己的類對象!? 不能
//原因:抽象類裏面有抽象方法, 抽象方法沒有方法體,假如有自己類對象調用抽象方法如何運行?所以悖論。
//創建了一個匿名內部類的對象賦值給了animal
/*
Animal是一個抽象類,animal是抽象類的一個引用類型變量
new Animal() {
發現這裏面的內容和繼承該抽象類的子類內容一致,都是抽象類,要求子類實現的方法
這裏是類的本體
而這裏可以看做是一個類,但是這個類沒有名字
所以:這個就是【匿名內部類】
這裏創建了一個【匿名內部類】的對象,賦值給了Animal的引用數據類型 animal
這裏隱含了一個【繼承】關係。
};
*/
new Animal() {
@Override
public void test() {
System.out.println("這是匿名內部類裏面的test方法");
}
@Override
public void jump() {
System.out.println("匿名內部類裏面的jump方法");
}
}
.jump();
//匿名內部類的匿名對象直接調用方法,用於接口。
new A() {
//這裏是一個類【遵從】接口之後要求實現接口中的抽象方法,這裏也是一個【匿名內部類】,是類的本體。
@Override
public void testA() {
System.out.println("匿名內部類實現interface A中的testA()方法");
}
}
.testA();
//用於java android開發
Integer[] arr = {3,2,4,5,6,1};
//匿名內部類的匿名對象作爲方法的參數。
Arrays.sort(arr,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
} );
System.out.println(Arrays.toString(arr));
}
}