1.內部類
A:內部類概述: 把類定義在其他類的內部,這個類就被稱爲內部類。
舉例:在類A中定義了一個類B,類B就是內部類。
B:內部類訪問特點
a:內部類可以直接訪問外部類的成員,包括私有。
b:外部類要訪問內部類的成員,必須創建對象。
public class MyTest {
public static void main(String[] args) {
//內部類:將一個類A 定義到另一個類B 當中,我們就稱類A爲內部類,我們可以把類B 叫做外部類
//根據內部類定義的位置不同,分爲:成員內部類和局部內部類
//成員內部類:將內部類定義到成員位置
//局部內部類:將內部類定義到外部類的方法中
}
}
class B{
//成員位置:類中方法外
class A {
//成員內部類
}
public void show(){
class C{
//局部內部類
}
}
}
2.內部類分類及成員內部類的直接使用
- A:按照內部類位置分類
成員位置:在成員位置定義的類,被稱爲成員內部類。
局部位置:在局部位置定義的類,被稱爲局部內部類。 - B:成員內部類
如何在測試類中直接訪問內部類的成員。
格式: 外部類名.內部類名 對象名 = 外部類對象.內部類對象;
3.成員內部類的常見修飾符及應用
- A:成員內部類的修飾符:
private 爲了保證數據的安全性
static 爲了方便訪問數據
注意事項:
a:靜態內部類訪問的外部類數據必須用靜態修飾。
b: 成員方法可以是靜態的也可以是非靜態的 - B:成員內部類被靜態修飾後的訪問方式是:
格式: 外部類名.內部類名 對象名 = new 外部類名.內部類名();
public class MyTest {
public static void main(String[] args) {
//我要訪問內部類的成員
//創建內部類的對象
Outer.Inner inner= new Outer().new Inner();
inner.neiShow();
System.out.println(inner.bb);
//內部類的特點:他可以直接訪問外部類的成員,包括私有的
//外部類想要訪問內部類的成員,就要創建內部類對象
Outer outer = new Outer();
outer.test();
}
}
class Outer{
int num=20;
private int aa=100;
//定義成員內部類
class Inner{
int bb=20;
public void neiShow(){
System.out.println("這是內部類的show方法");
System.out.println(num);
System.out.println(aa);
waiShow();
waiTest();
}
public void neiTest(){
System.out.println("這是內部類的test方法");
}
}
public void waiShow(){
System.out.println("這是外部類的show方法");
}
private void waiTest(){
System.out.println("這是外部類私有的方法");
}
public void test(){
//創建內部類的對象
Inner inner = new Inner();
System.out.println(inner.bb);
inner.neiTest();
}
}
4.成員內部類的面試題
要求:使用已知的變量,在控制檯輸出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);//30
System.out.println(this.num);//20
System.out.println(new Outer().num); //10
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
5.局部內部類訪問局部變量的問題
- A: 可以直接訪問外部類的成員
- B: 可以創建內部類對象,通過對象調用內部類方法,來使用局部內部類功能
- C:局部內部類訪問局部變量必須用final修飾
爲什麼呢?
因爲局部變量會隨着方法的調用完畢而消失,這個時候,局部對象並沒有立馬從堆內存中消失,還要使用那個變量。
爲了讓數據還能繼續被使用,就用fianl修飾,這樣,在堆內存裏面存儲的其實是一個常量值。
JDK1.8之後,final會默認加上,你不用手動去加,但是你要知道
6.匿名內部類
- A:匿名內部類: 就是局部內部類的簡化寫法。
- B:前提: 存在一個類或者接口;這裏的類可以是具體類也可以是抽象類。
- C:格式:
new 類名或者接口名(){
重寫方法;
} ; - D:本質是什麼呢?
是一個繼承了該類或者實現了該接口的子類匿名對象。
7.匿名內部類的方法調用
匿名內部類的方法調用
public class MyTest {
public static void main(String[] args) {
//匿名內部類:他是局部內部類的簡寫形式
//匿名內部類:本質上是一個對象,是誰的對象,是繼承了該抽象類,或實現了該接口的子類對象
//匿名內部類的語法
/* new 抽象類名/接口名(){
重寫抽象類/接口 中的抽象方法
};
*/
new AA() {
@Override
public void show() {
System.out.println("重寫了抽象類中的show方法22222222222222");
}
}.show();
}
public static void set(AA aa){
aa.show();
}
}
abstract class AA{
public abstract void show();
}
8.匿名內部類在開發中的應用
首先回顧我們曾經講過的方法的形式參數是引用類型的情況,
我們知道這裏需要一個子類對象。而匿名內部類就是一個子類匿名對象,
所以,可以使用匿名內部類改進以前的做法。
//這裏寫抽象類,接口都行
public class MyTest3 {
public static void main(String[] args) {
new EE() {
@Override
public void hehe() {
System.out.println("呵呵");
}
@Override
public void haha() {
System.out.println("哈哈");
}
}.haha();
new EE() {
@Override
public void hehe() {
System.out.println("呵呵222");
}
@Override
public void haha() {
System.out.println("哈哈2222");
}
}.hehe();
//用多態的方式 給對象起個名字
EE ee = new EE() {
@Override
public void hehe() {
System.out.println("呵呵222333");
}
@Override
public void haha() {
System.out.println("哈哈22223333");
}
};
ee.haha();
ee.hehe();
}
}
abstract class EE {
public abstract void hehe();
public abstract void haha();
}
9.匿名內部類中this關鍵字
interface Inter {
public static final int a = 23 ;
}
public class Test {
public static void main(String[] args) {
new Inter() {
public void show() {
//this 匿名內部類
System.out.println(this.a);//23
System.out.println(Inter.a);//23
}
}.show();
}
}
10.匿名內部類的面試題
要求在控制檯輸出”HelloWorld”
interface Inter {
void show();
}
class Outer {
//補齊代碼
public static Inter method() {
return new Inter() {
@Override
public void show() {
System.out.println("HelloWorld");
}
};
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}