揭秘内部类
来源:互联网 发布:php7 mysql 一键安装 编辑:程序博客网 时间:2024/06/14 06:08
情景:
当A类中的内容要被B类直接访问,而A类还需要创建B的对象,访问B的内容时,
这时,可以将B类定义到A类的内部,这样访问更为便捷。
将B称之为内部类(内置类,嵌套类)。
访问方式:
内部类可以直接访问外部类中的所有成员,包括私有的。
而外部类要想访问内部类的成员,必须创建内部类的对象。
应用:
当描述事物时,事物的内部还有事物,这个内部的事物还在访问外部事物中的内容。
这时就将这个事物通过内部类来描述。
【内部类被访问的方式】
情况一:内部类在成员位置上的被访问的方式。
成员时可以被指定的修饰符所修饰的。
public:不多见,因为更多的时候,内部类已经被封装到了外部类中,不直接对外提供。
static:详见下面代码体现。
代码:
class Outer/*A类即外部类*/{ private static int num =5; public class Inner/*B类即内部类*/ { void show() { System.out.println("num="+num); }// static void show1(){} //非静态内部类中不允许定义静态成员,仅允许在非静态内部类中定义 静态常量 static final. //如果想要在内部类中定义静态成员,必须内部类也要被静态修饰 } /* 内部类被静态修饰后,随着Outer的加载而加载,可以把一个静态内部类理解为就是一个外部类。 */ static class Inner2 { void show2() { System.out.println("Inner2 show2 run..."+num); } static void staticShow() { System.out.println("Inner2 staticshow run..."); } } void method() { /*Outer.*/Inner in =new /*Outer.*/Inner(); in.show(); }}class InnerClassDemo{ public static void main(String[] args) {/* Outer out=new Outer(); out.method(); */ //情况一:直接访问Outer中的Inner内部类的非静态成员 //创建内部类的对象即可。--内部类作为成员,应该先有外部类对象,再有内部类对象。/* Outer.Inner in=new Outer().new Inner(); in.show();*/ //情况二:对静态内部类中的非静态成员进行调用。 //因为内部类是静态,所以不需要创建Outer的对象,直接创建内部类对象即可。/* Outer.Inner2 in=new Outer.Inner2(); in.show2(); */ //如果静态内部类有静态成员,该如何访问呢?既然惊涛内部类已随外部类加载,而且静态成员随着类的加载而加载。 //就不需要对象,直接类名调用即可。 // Outer.Inner2.staticShow(); }}
问题1:
为什么内部类就能直接访问外部类中的成员呢?
那是因为内部类其实持有了外部类的引用 ->外部类.this
对于静态内部类不持有 外部类.this 而是直接使用 外部类名.
class Outer{ int num=3; class Inner { int num=4; void show() { int num = 5; System.out.println("num ="+num); System.out.println("num ="+this.num); System.out.println("num ="+Outer.this.num); } } void method() { // System.out.println(num); new Inner().show(); }}class InnerClassDemo2{ public static void main(String[] args) { Outer out =new Outer(); out.method(); }}
输出结果为:
num =5
num =4
num =3
内部类其实也可以定义在外部类的局部位置上。
内部类定义在局部时,只能访问被final修饰的局部变量。
为什么呢?
分析内存,可以知道如果访问的局部变量不是常量,其生命周期太短,导致访问失败。
class Outer{ int num=3; void method() { final int x = 5;//局部变量 int y=2; class Inner //局部内部类。不能被成员修饰符修饰 { void show() { System.out.println("y ="y);//访问失败,y的生命周期太短了。 System.out.println("x ="x); System.out.println("num ="+num); } } new Inner().show(); }}class Outer2{ Object obj; public void method() { int y=9; class Inner { public String toString() { return "toString"+y; } } obj =new Inner();//给obj赋一个Inner对象。 } public void fun() { System.out.println(obj.toString()); }}class InnerClassDemo3{ public static void main(String[] args) { Outer2 out =new Outer2(); out.method(); }}
看API中发现类名或者接口名称中有(.)说明内部类,或者内部接口。
内部类的延伸。
内部类是可以继承或者实现外部类其他的类或者接口的。
好处:通过内部类的方式对类进行继承重写,或者接口的方式。
通过公共的方式对其内部类对象进行访问,因为通常内部类很有可能被外部类封装其中。
我们可以通过父类或者接口的方式访问到内部类对象。
abstract class AbsDemo{ abstract void show();}class Outer{ int num=3; private class Inner extends AbsDemo { //重写抽象方法show(). void show() { System.out.println("num ="+num); } } //获取内部类的对象 public AbsDemo getObject() { return new Inner(); } void method() { new Inner().show(); }}class InnerClassDemo4{ public static void main(String[] args) { Outer out =new Outer();// out.method();/* Outer.Inner in =out.getObject(); in.show(); */ //如果Inner被private .可以通过父类型获取。 AbsDemo a=new Outer.getObject();// 多态 a.show(); }}
对代码进行简化
匿名内部类,其实就是一个带有内容的子类对象。
格式:new 父类or接口(){子类的内容}
匿名内部类就是内部类的简化形式。
匿名内部类是有前提,内部类必须要继承父类或者实现接口。
abstract class AbsDemo{ abstract void show();}class Outer{ int num=3;/* class Inner extends AbsDemo { void show() { System.out.println("num ="+num); } } */ void method() {// new Inner().show(); /* 不想创建具体的子类型,还想创建AbsDemo的子类对象。 怎么实现呢?没有子类型,直接使用父类型。 在该例子中是抽象类,怎么可以new对象呢? 抽象类之所以不能new对象是因为抽象方法没重写,直接重写即可。 */ new AbsDemo()//这个是一个AbsDemo的子类对象,只不过这个对象有点胖-这是一个带着内容的子类对象。 { //这就是:匿名内部类 //重写抽象的show方法。 void show() { System.out.println("num ====="+num); } }.show(); }}class InnerClassDemo5{ public static void main(String[] args) { Outer out =new Outer(); out.method(); }}
匿名内部类的使用:
interface Inter{ void show1(); void show2();}class Outer{ int num =4; //在一个类使用一个接口的对象,可以通过内部类来实现。/* class Inner implements Inner { public void show1() {} public void show2() {} } */ public void method() {/* Inner in =new Inner(); in.show1(); in.show2(); */// 进行简化,写出匿名内部类的方式 Inter in =new Inter() { public void show1() {} public void show2() {} } in.show1(); in.show2(); }}class InnerClassDemo6{ public static void main(String[] args) { Outer out =new Outer(); out.method(); }}
匿名内部类的练习:
//匿名内部类练习。interface Inter{ public void show();}class Outer{ //代码补足,要求使用匿名内部类/* public static Inter method() { return new Inter() { public void show(){ System.out.println("hello"); } }; } */ //还原成内部类,当静态方法访问内部类时,内部类必须是静态的。/* static class Inner implements Inter { public void show(){} } */}//面试题。class Outer2{ public Object() { public void show(){} }.show();//可以编译通过。 Object obj =new Object() { public void sho1(){} }; obj.show();//编译失败,因为匿名内部类时子类对象, //当被Object指向时,就被提升为Object类型,而Object中没有show()方法,编译失败。}class InnerClassDemo7{ public static void main(String[] args) { Outer.method().show(); /* Outer.method():Outer类中有一个method的方法,这个方法是静态的。 Outer.method().show(): 能调用show()的必然是对象, 说明method方法运算完应该返回一个对象,而且能调用Inner中的show方法,说明这个这个对象的类型是:Inter */ }}
- 揭秘内部类
- Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“
- Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“
- Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“
- Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“
- Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- 内部类
- JSP数据交互(二)
- pycharm破解码
- Android 沉浸式状态栏把布局顶到状态栏上
- 程序员如何写好技术简历 —— 实例、模板及工具
- 50_面向对象_23_回调的实现_模板方法模式
- 揭秘内部类
- 代码评审
- Codeforces-An impassioned circulation of affection (尺取法)
- printf函数
- js位置存放
- 解决 IIS 安装了.net framework 4.0/4.5 却找不到相应应用程序池
- [YTU]_2638(编程题:多态--动物叫)
- axios基础
- 数组中的冷知识