day09(上)_内部类
成员内部类:
/* 内部类的访问规则: 1.内部类(局部内部类和成员内部类)可以直接访问外部类中的成员,包括private 之所以可以直接访问外部类中的成员,是因为内部类中持有了一个 外部类的 引用-->外部类.this 2.外部类访问内部类非静态成员,必须建立内部类对象 访问格式: 当内部类定义在外部类的成员位置上,而且非私有,可以再外部其他类中, 直接建立内部类对象来访问内部类成员
外部类名.内部类名 变量名=外部类对象.内部类对象 Outer.Inner oi=new Outer().new Inner(); 3.当内部类在成员位置上,就可以被成员修饰符所修饰. 比如,private:将内部类在外部类中进行封装 static: 内部类就 具备static特性 当内部类被static修饰后,只能直接访问外部类中的static成员. 在外部其他类中,如何直接访问static内部类的非静态成员呢? new Outer.Inner().inMethod(); 注意:1.当内部类中定义了静态成员,该内部类必须是static的 2.当外部类中的静态方法访问内部类时,内部类也必须是静态的. 当描述事物时,事物的内部还有事物,该事物用内部类来描述. 因为内部事物在使用外内部事物的内容. 例如: class Body//人体 { private class Heart//更能反应事物之间的特性 { //这样心脏可以直接访问人体内的东西(例如血液) } public void show() { new Heart(); } } 什么时候定义内部类? 因此当一个类需要直接访问到另一个类中的成员时. 把这个类写到该类里面,把内部类封装不对外暴露, 对外提供方法来访问内部事物 */ class Outer { private int x=3; private static int y=7; class Inner { int x=5; public void inMethod() { int x=6; System.out.println("this.x="+this.x+"\n"+"Outer.this.x="+Outer.this.x);//Outer.this.x访问外部类的x,Outer标识this是Outer的this //内部类可以直接访问外部类中的成员,包括private } } public static void outerMethod() { //当外部类中的静态方法访问内部类时,内部类也必须是静态的. //new inner().inMethod();//报错,inner加上静态 } static class Inner_2 { void function() { System.out.println("Inner_2 y="+y); } } static class Inner_3 { static void inMethod()//静态内部类的静态方法 { System.out.println("Inner_3 y="+y); } } } class InOutDemo { public static void main(String[] args) { new Outer().new Inner().inMethod();//非静态内部类 new Outer.Inner_2().function();//静态内部类 //new Outer().new Inner_2().function();//不能通过对象访问静态内部类 //报 限定的新静态类 Outer.Inner_3.inMethod();//访问静态内部类中的静态方法 } }
局部内部类:
/* 局部内部类 1.不可以被成员修饰符修饰 2.可以直接访问外部类中的成员,因为持有外部类中的引用. 但是不可以访问它所在局部中的变量.只能访问被final修饰的局部变量 */ class Outer { int x=3; void method(final int a)//a必须为finnal才能被内部类访问 { class Inner//局部内部类 { final int y=6;//必须为final 原因在下面 void function()//不能为static { //如果为static,Inner必须为static //static为成员修饰符,不能修饰局部Inner System.out.println("x="+Outer.this.x+"\ny="+y+"\na="+a); } } new Inner().function(); } } class Demo { public static void main(String[] args) { new Outer().method(10); } } /* 局部类访问局部变量,该变量必须被声明为final 1. 经研究,Java虚拟机的实现方式是, 编译器会探测局部内部类中是否有直接使用外部定义变量的情况, 如果有访问就会定义一个同类型的变量(也有final修饰),然后在构造方法中用外部变量 给自己定义的变量赋值。 2.局部内部类对象中包含有 要访问的final型局部变量的一个拷贝, 成为它的数据成员。因此,正是在这个意义上,final型局部变量的生命期,超过其方法的一次调用。 严格来说,方法调用结束,所有的局部变量(含final)全死亡了。但:局部内部类对象中有final型局部变量的拷贝。 以上为两种理解方式(大体相同) */
3.匿名(无名)内部类
/* 匿名(无名)内部类: 1.匿名内部类其实就是内部类的简写格式 2.匿名内部类前提: 内部类必须继承一个类或实现接口 3.匿名内部类格式: new 父类或者接口(){定义子类的内容} 4.其实匿名内部类就是一个匿名子类对象 (带内容的对象) 5.匿名内部类中定义的方法最好<3个(超出3个代码将变得冗长) */ abstract class AbsDemo//抽象类 { abstract void show(); } class Outer { int x=5; /* ① class Inner extends AbsDemo { void show() { System.out.println("show:"+x); } } */ public void function() { //② new Inner().show(); //把① ②注释简写为: new AbsDemo()//匿名对象 { void show() { System.out.println("x="+x); } }.show(); //以上是一个对象,是AbsDemo子类的对象 //通过匿名对象调用子类特有方法 new AbsDemo() { void show() { System.out.println("x="+x); } void son()//子类特有方法 { System.out.println("son"); }}.son(); //通过父类的引用来调用 AbsDemo ab= new AbsDemo()//多态 父类引用指向子类对象 { void show() { System.out.println("x="+x); } void son() { System.out.println("son"); } }; ab.show(); //ab.son();//编译失败,父类中无son() //并且无法通过向下转型来调用son(); } //因为子类没名字! } class AnonyInnerDemo { public static void main(String[] args) { new Outer().function(); } }
4.根据Test.function().method();填充代码:
interface Inter { public abstract void method(); } class Test { //法一:通过匿名内部类实现 public static Inter function() { return new Inter() { public void method() { System.out.println("success"); } };//整体为一个匿名子类对象,返回该对象 } //法二:通过成员内部类来实现 static class Inner implements Inter { public void method() { System.out.println("Inner success"); } } public static Inter function_2() { return new Inner(); //如果不想把该Inner用static修饰,还可以通过外部类实例.内部类实例.method();//return new Test().new Inner().method(); } } class InnerTest { public static void main(String[] args) { Test.function().method();Test.function_2().method(); show( new Inter() { public void method() { System.out.println("show success"); } } );//可采用这种方式调用函数 } //什么时候用匿名内部类? //当参数类型为接口类型,并且接口中的方法<3个 public static void show(Inter in)//形参为接口类型 { in.method(); }}
/* 分析过程: Test.function()-->通过类名直接调用-->function一定有静态修饰符 Test.function().method()-->说明function返回值为类 类型(对象) -->这里要用匿名内部类-->一定为Inter类型 */ //当一个类没有声明父类,也可以用匿名内部类 class Inner { public static void main(String[] args) { new Object()//Object所有类的父类 { void function()//子类特有方法 { System.out.println("function()"); } }.function(); } }
易错例子:
//例一 class Outer { class Inner { } public void func() { new Inner(); } public static void main(String[] args) { Outer d=new Outer(); new Outer().new Inner();//ok // new Inner();//不可以,内部类必须为static //类似于 d.func();//ok,因为func()属于对象new Outer(),指明了对象 func();//必须为static //new d.Inner();//格式错误->new new Outer().new Inner(); } } //例二 interface Test { public abstract void func(); } class Demo { public static void main(String[] args) { //补足代码,匿名内部类-->调用show() new Demo().show( new Test() { public void func(){} }); } void show(Test t) { } }