一:基本介绍
一个类的内部又完整的嵌套了另一个类结构,被嵌套的类成为内部类
嵌套其他类的类称为外部类( outer class )。是类的第五大成员。
:::danger
类的五大成员!!!!!
属性,方法,构造器,代码块,内部类
:::
内部类的最大特点是可以直接访问私有属性,迫切可以直接提现类与类之间的包含关系
在看底层源码时,有大量的内部类
1:内部类的分类
- 定义在外部类局部位置上
- 局部内部类
- 匿名内部类
- 定义在外部类的成员位置上
- 可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,但是可以使用final修饰,因为局部变量也可以使用final
- 作用域:仅仅在定义他的方法或者代码中
- 局部内部类可以直接访问外部类的成员
- 外部类 —> 访问 —> 局部内部类的成员
- 访问方式:创建对象,再访问,(注意必须在作用域中)作用域:定义的方法或者代码块中。
外部其他类不能访问局部内部类(因为局部内部类是一个局部变量) ```java public class InnerCLass { public static void main(String[] args) {
Outer outer = new Outer();outer.Sakura();//执行sakura()方法时,在方法体内定义局部内部类//定义完之后再执行下面的创建对象
}
} class Outer { //外部类 private int n1 = 10; //属性
private void Test(){ //私有方法System.out.println("Test方法");}public void Sakura(){ //方法//可以用final修饰final class Inner{ //局部内部类private int n1 = 100;public void F(){//局部内部类:访问--> 外部类的成员//[ 访问方式:直接访问 ]System.out.println(n1);Test();//如果有重名的,就近原则//若想访问外部类的成员使用:外部类名.this.成员//因为外部类名.成员 只有在静态的时候才这样//非静态,非共有。需要加this表明是这个对象的属性System.out.println("内部类的成员"+ n1);System.out.println("外部类的的n1" + Outer.this.n1);}}//外部类在局部内部类作用域(定义局部内部类-的方法体或者代码块)//中,可以创建对象,然后调用方法即可Inner inner = new Inner();inner.F();}
}
<a name="Bxmuj"></a>### 五:匿名内部类<a name="kbDUw"></a>#### 1:基本使用1. 本质是类2. 内部类3. 该类没有名字4. 同时还是一个对象:::danger说明:匿名内部类是定义在外部类的局部位置,比如方法中并且没有类名:::```javapublic class AnonymousInnerClass {public static void main(String[] args) {outer outer = new outer();outer.method();}}class outer{private int n1 = 10;public void method(){//需求:使用A接口,并创建对象//传统写法:创建类实现接口,创建对象调用方法// A cat = new cat();//cat.cry();//需求:类只使用一次,后面不在使用//使用匿名内部类//编译类型:A 运行类型:匿名内部类 Onter&1//底层/*class Outer04$1 implements IA {@Override public void cry() {System.out.println("猫叫了");}}*///jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例//并且把地址返回给 tigerA cat = new A(){@Overridepublic void cry() {System.out.println("猫叫了");}};//通过getclass来查看当前的运行类型System.out.println("Cat的运行类型:"+ cat.getClass());cat.cry();}}interface A{public void cry();}/*class cat implements A{@Overridepublic void cry() {System.out.println("猫叫了");}}*/class father{public father(String name) {System.out.println("接收到name"+ name);}}
2:匿名内部类的细节
匿名内部类即时一个类的定义,同时也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征。
public class TestClass {public static void main(String[] args) {Test T = new Test();T.A();}}class Test{//创建一个基于类的匿名对象public void A(){//第一种匿名内部类创建方法Person person = new Person(){@Overridepublic void speak() {System.out.println("重写Person里的speak方法");}};person.speak(); //动态绑定 运行类型是Test&1//第二种匿名内部类创建方法//底层 class 匿名内部类 extends Personnew Person(){@Overridepublic void speak() {System.out.println("重写Person里的speak方法");}@Overridepublic void eat(String name) {// super.eat(name); 调用父类也就是Person的eat方法System.out.println(name+"吃饭了");}}.eat("sakura");}}class Person{public void speak(){System.out.println("人说话");}public void eat(String name){System.out.println("人吃饭");}}
:::danger 其他和局部内布类一样:
可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,因为它的地位就是一个局部变量
- 作用域:仅仅在定义它的方法或代码块
- 匿名内部类—-访问——>外部类成员
- 外部其他类—- 不能访问——->匿名内部类(因为匿名内部类地位是一个局部变量)
如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问 :::
六:匿名内部类的最佳实践
1:当做实惨传递
```java public class Test00 { public static void main(String[] args) {
//当做实惨直接传递,简洁高效Test(new AA() {@Overridepublic void eat() {System.out.println("人吃饭");}});//传统方法Test(new Person());
}
public static void Test(AA aa){
aa.eat();
} }
interface AA{ public void eat(); }
//传统方法 class Person implements AA{ @Override public void eat() { System.out.println(“吃饭吃饭吃饭”); } }
<a name="Inq7H"></a>##### 2:```javapublic class Test01 {public static void main(String[] args) {Cellphone cellphone = new Cellphone();//1. 传递的是实现了 Bell 接口的匿名内部类 InnerClassExercise02$1// 2. 重写了 ring//Bell bell = nee Bell(){// @Override// public void Ring() {// System.out.println("起床了");// }//}cellphone.alarmClock(new Bell() {@Overridepublic void Ring() {System.out.println("起床了");}});cellphone.alarmClock(new Bell() {@Overridepublic void Ring() {System.out.println("不起床");}});}}interface Bell {public void Ring();}class Cellphone{public void alarmClock(Bell bell){bell.Ring();}}
七:成员内部类的使用
:::danger 说明:成员内部类定义在外部类的的成员位置,并且没有static修饰 :::
- 可以直接访问外部类的所有成员,包含私有的属性
- 可以添加任意访问修饰符
- 作用域
- 和外部类的其他成员一样,为整个类体。
- 成员内部类访问外部类对象(比如:属性)
- 访问方式:直接访问
- 外部类访问成员内部类
- 访问方式:创建对象,再访问
外部其他类访问 ```java public class Test02 { public static void main(String[] args) {
Outer outer = new Outer();outer.UseInnerClass();//外部其他类访问成员内部类的三种方式//(前提要先创建外部类)//第一种outer.new Inner();//new Inner()当做是 outer 成员Outer.Inner inner = outer.new Inner();//第二种 在外部类中编写一个方法,可以返回Inner对象//接收通过InnerInstance返回的Inner对象Outer.Inner innerInstance = outer.getInnerInstance();
} }
class Outer{ //外部类 private int Num = 10; private void Test(){ System.out.println(“外部类的Test方法”); } public class Inner{ //成员内部类 //可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员 private int Num = 100; public void Say(){ System.out.println(“外部类的Num:”+ Outer.this.Num); System.out.println(“成员内部类Num:” + Num); } } //使用成员内部类 //通过写方法,创建成员内部类的对象,然后使用相关的方法 public void UseInnerClass(){ Inner inner = new Inner(); inner.Say(); } public Inner getInnerInstance(){ //返回一个Inner实例,但是没有对象接收 return new Inner(); } }
<a name="SLwM1"></a>### 七:静态内部类的使用:::danger**_说明:静态内部类是定义在外部类的成员位置,并且有static修饰_**:::1. **_可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员_**2. **_可以添加任意访问修饰符(pubic,protected,默认,private)因为它的地位就是一个成员_**3. **_作用域:_**1. **_同其他的成员一样,为整个类体_**4. **_静态内部类访问外部类(比如:静态属性)_**1. **_访问方式:直接访问所有静态成员_**5. **_外部类访问静态内部类_**6. **_外部其他类范文静态内部类_**7. **_如果外部类和静态内部类的成员,泽可以使用(外部类。成员)去访问_**```javapublic class Tets00 {public static void main(String[] args) {Outer outer = new Outer();outer.UseInnerClass();//第一种://因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)Outer.Inner inner = new Outer.Inner();//第二种//编写一个方法,可以返回静态内部类的对象实例.Outer.Inner inner1 = outer.getInner();}}class Outer{ //外部类private static int Num = 10;private void Test(){System.out.println("外部类的Test方法");}public static class Inner{ //成员内部类//可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员private int Num = 100;public void Say(){System.out.println("外部类的Num:"+ Outer.Num);System.out.println("成员内部类Num:" + Num);}}//外部类访问静态内部类//通过写方法,创建成员内部类的对象,然后使用相关的方法public void UseInnerClass(){Inner inner = new Inner();inner.Say();}public Inner getInner(){//返回一个Inner实例,但是没有对象接收return new Inner();}}
:::danger
非静态成员内部类创建对象
new Inner( )当做是 outer 成员
Outer.Inner inner1 = outer.new Inner( );
静态成员内部类创建对象
因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
Outer.Inner inner2 = new Outer.Inner( );
:::
七:练习
public class Test {//外部类public Test() {//构造器Inner s1 = new Inner();s1.a = 10;Inner s2 = new Inner();System.out.println(s2.a);}class Inner { //内部类,成员内部类public int a = 5;}public static void main(String[] args) {Test t = new Test();//5//正常情况是要应该是Test.InnerInner r = t.new Inner();System.out.println(r.a);//5}}
