内部类(本质上还是一个类)
类的五大成员:属性、方法、构造器、代码块、内部类
内部类有四种:局部内部类、匿名内部类 ||| 成员内部类、静态内部类
-
内部类的分类:
-
定义在外部类的局部位置上(比如方法内):
-
局部内部类(有类名)
-
可以直接访问外部类的所有成员,包含私有的
-
不能添加访问修饰符,因为它的地位就是一个局部变量。
局部变量不能使用访问修饰符。但可以使用final修饰,因为局部变量也可以使用final
-
作用域:仅仅在定义它的方法中或者代码块中
-
局部内部类访问外部类成员----->直接访问
-
外部类在方法中可以创建对象实例 然后调用方法即可
-
外部其他类不能局部内部类
-
如果外部类和局部内部类的成员重名时,默认遵循就近原则。
如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
外部类名.this 本质就是外部类对象 即哪个对象调用了m1,Outer.this就是哪个对象
/** * @author caicai * 演示局部内部类的使用 */ public class LocalInnerClass { public static void main(String[] args) { Outer outer = new Outer(); outer.m1(); System.out.println("外部outer hashcode" + outer.hashCode()); } } /** * 外部类 */ class Outer { private int n1 = 100; private void m2() { System.out.println("这是m2方法"); } public void m1() { /* * 局部内部类是定义在外部类的局部位置上的 通常在方法 */ final class InnerOuter { // 局部内部类(本质仍是一个类) // 可以直接访问外部类的所有成员 包括私有的 private int n1 = 800; public void f1() { // 局部内部类访问外部类成员----->直接访问 System.out.println("n1 = " + n1); System.out.println("外部类的n1 = " + Outer.this.n1); System.out.println("内部Outer.this hashcode" + Outer.this.hashCode()); m2(); } } InnerOuter innerOuter = new InnerOuter(); innerOuter.f1(); } }
-
-
匿名内部类(没有类名,重点)
(本质还是一个类、是内部类、没有名字的类、同时还是一个对象)
/** * @author caicai * 基于接口、类、抽象类的匿名内部类 */ public class AnonymousInnerClass { public static void main(String[] args) { Outer01 outer01 = new Outer01(); outer01.method(); } } class Outer01 { private int n1 = 10; public void method() { /** * 基于接口的匿名内部类 * tiger的编译类型是 接口A * tiger的运行类型是 匿名内部类 ---?XXX Outer01$1 * jdk底层在创建匿名内部类 Outer01$1 就立马创建了 Outer01$1 实例 并把地址返回给tiger * 匿名内部类使用一次 就不能再使用 但是tiger可以重复使用 因为tiger是对象 * * 看底层 系统会分配类型 * class XXX(匿名内部类) implements A{ * @Override * public void cry() { * System.out.println("老虎叫唤...."); * } * } */ // 基于接口的匿名内部类 A tiger = new A() { @Override public void cry() { System.out.println("老虎叫唤...."); } }; System.out.println("tiger的运行类型是:" + tiger.getClass()); tiger.cry(); // 基于类的匿名内部类 /** * 分析: * father的编译类型是 Father * father(需要带大括号)的运行类型是 匿名内部类 Outer01$2 * father如果不带大括号 就跟以前的一样 */ Father father = new Father("Jack") { @Override public void fatherTest() { System.out.println("匿名内部类father重写了fatherTest方法"); } }; father.fatherTest(); System.out.println("father的运行类型是:" + father.getClass()); // 基于抽象类的匿名内部类 Animal animal = new Animal() { @Override void eat() { System.out.println("小狗吃骨头"); } }; animal.eat(); System.out.println("animal的运行类型是:" + father.getClass()); } } interface A { public void cry(); } class Tigher implements A { @Override public void cry() { } } class Father { public Father(String name) { } public void fatherTest() { } } abstract class Animal { abstract void eat(); }
-
细节:匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征。
-
可以直接访问外部类的所有成员,包括私有成员
-
不能添加访问修饰符
-
作用域:仅仅在定义它的方法或代码块中
-
外部其他类不能访问匿名内部类
-
如果外部类和匿名内部类重名时,匿名内部类访问时也遵循就近原则
-
匿名内部类实践:
public class InnerClassTest02 { public static void main(String[] args) { CellPhone cellPhone = new CellPhone(); // 传递实现了 Bell接口的匿名内部类 // 重写了ring方法 /** * 相当于: * Bell bell = new Bell() { * @Override * public void ring() { * System.out.println("懒猪起床了"); * } * } */ cellPhone.alarmClock(new Bell() { @Override public void ring() { System.out.println("懒猪起床了"); } }); cellPhone.alarmClock(new Bell() { @Override public void ring() { System.out.println("小伙伴们上课了"); } }); } } interface Bell { void ring(); } class CellPhone { public void alarmClock(Bell bell) { bell.ring(); } }
-
-
-
定义在外部类的成员(属性、方法)位置上:
-
成员内部类(没用static修饰)
-
可以直接访问外部类的所有成员,包括私有成员
-
可以添加任意的修饰符 因为它也是一个类的成员
-
使用成员内部类直接在外部类中new就可以了
-
外部类访问成员内部类:先创建成员内部类对象 再调用
-
就近原则 外部类名.this.属性
/** * @author caicai * 成员内部类(没用static修饰) */ public class MemberInnerClass { public static void main(String[] args) { Outer04 outer04 = new Outer04(); outer04.f1(); // 外部其他类使用成员内部类的三种方式 // outer04.new Inner04(); 相当于把 new Inner04() 当作是outer04的成员 Outer04.Inner04 inner04 = outer04.new Inner04(); // 第二种方式 在外部类中写一个方法 返回一个inner04的对象实例 Outer04.Inner04 inner041 = outer04.f2(); inner041.say(); } } class Outer04 { // 外部类 private int n1 = 10; public String name = "张三"; private void hi() { System.out.println("这是Outer04的私有方法"); } // 注意:成员内部类是定义在外部类的成员位置上 class Inner04 { // 成员内部类 既没在方法中也没在代码块中 public void say() { // 可以直接访问外部类的所有成员,包括私有成员 System.out.println("名字是:" + name + " n1是:" + n1); hi(); } } public void f1() { // 使用成员内部类 直接在外部类中new就可以了 Inner04 inner04 = new Inner04(); inner04.say(); } public Inner04 f2() { return new Inner04(); } }
-
-
静态内部类(使用static修饰)
-
可以访问外部类的所有静态成员 包含私有的 但不能直接访问非静态成员
-
可以添加任意修饰符
-
在外部类外部 创建静态内部类
语法: 外部类.内部类 内部类对象 = new 外部类.内部类(); 举例: Outer.Inner in = new Outer.Inner();
/** * 静态内部类 * * @author caicai */ public class StaticInnerClass { public static void main(String[] args) { Outer05 outer05 = new Outer05(); outer05.mi(); Outer05.Inner05 inner05 = new Outer05.Inner05(); inner05.say(); outer05.getInner(); } } class Outer05 { // 外部类 private int n1 = 10; public static String name = "张三"; private void hi() { System.out.println("这是Outer05的私有方法"); } /** * Inner05是静态内部类 * 1. 放在外部类的成员位置 * 2. 使用static修饰 */ static class Inner05 { public void say() { System.out.println(name); } } public void mi() { Outer05 outer05 = new Outer05(); System.out.println(outer05.n1); } public Inner05 getInner() { return new Inner05(); } }
-
-
-