一、内部类

1、引入

类的成员包括:

(1)属性:成员变量;

(2)方法:成员方法;

(3)构造器;

(4)代码块;

(5)内部类;

其中1、2是代表这类事物的特征;

其中3、4是初始化类和对象用的;

其中5是协助完成2的功能的实现,表现;

2、内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。

Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。

Inner class的名字不能与包含它的外部类类名相同;

3、分类

根据内部类的所在的位置不同:

(1)成员内部类:(static成员内部类和非static成员内部类)外部类中方法外;

(2)局部内部类:匿名内部类,方法体内(也可以在代码块内)

4、

二、成员内部类

1、概述及分类

成员内部类:定义在 类中方法外 的类。

(1)有 static 修饰的:静态成员内部类,简称 静态内部类;

(2)没有 static 修饰的:非静态成员内部类,简称 成员内部类;

思考:什么情况下会用到成员内部类(方法外声明的?)

当描述一个事物时,发现它的内部还有一个完整的结构需要用一个类来描述;

并且发现这内部的结构,如果独立存在是没有意义的,必须在这个外部类中才有意义。而且这个内部结构只为这个外部类服务。

例如:Body身体,发现它内部还有完整的结果,如:心脏,发现心脏单独创建对象没有意义,只有在 Body 对象中才有意义,而且只为 Body 对象服务。

2、成员内部类的特点

(1)成员内部类作为类的成员的角色:

① 和外部类不同,Inner class 还可以声明为 private或 protected;

② 可以调用外部类的结构;

③ Inner class 可以声明为 static的,但此时就不能再使用外层类的非static 的成员变量;

(2)成员内部类作为类的角色:

① 成员内部类,可以出现原本类中能够定义的所有的成员:

属性:可以有静态属性和非静态属性;

方法:可以有静态方法和非静态方法,如果静态内部类是抽象类,还可定义抽象方法;

构造方法:有参方法、无参方法;

代码块:可以有静态代码块和非静态代码块;

内部类:允许,但很少再写内部类(臃肿)

② 可以声明为 abstract 类,因此可以被其他的内部类继承;

③ 可以声明为 final 类;

④ 编译以后生成 OuterClass$InnerClass.class 字节码文件(也适用于局部内部类)

(3)注意

① 非 static 的成员内部类中的成员不能声明为 static 的,只有在外部类或 static 的成员内部类才可声明 static 成员;

② 外部类访问成员内部类的成员,需要“内部类.成员” 或 “内部类对象.成员” 的方式;

③ 成员内部类可以直接使用外部类的所有成员,包括私有的数据;

④ 当想要在外部类的静态成员部分使用内部类时, 可以考虑内部类声明为静态的;

2、静态成员内部类(静态内部类)

(1)语法格式

【修饰符】 class 外部类 【 extends 父类】 【implements 父接口们】{

【其他修饰符】 static class 内部类 【 extends 父类】 【implements 父接口们】{

}

}

注意:

① 只有成员内部类才能用 static 修饰,其他的外部类,局部内部类等够不可以用 static 修饰。

② 外部类,内部类的父类,父接口都没有关系,各是各自的。

(2)特点

① 静态内部类中不能使用外部类的非静态的成员;

② 在外部类中,使用静态内部类,和使用其他的类一样的原则;

如果使用静态内部类的静态成员,直接“静态内部类名.”

如果使用静态内部类的非静态成员,直接“静态内部类对象名.”

③ 在外部类的外面,使用静态内部类:

如果使用静态内部类的静态成员,直接“类名”;

使用 外部类名.静态内部类名.静态方法;

使用 import 包.外部类名.静态内部类名; 然后在代码中使用“静态内部类名”

④ 静态内部类不会随着外部类的初始化一起初始化,而是要在使用到这个静态内部类才会初始化;

(3)小节

① 同级的来说静态的不能直接使用非静态的;

② 访问一个类的静态成员,用 “类名.” 即可;访问一个类的非静态成员,用“对象名.”即可;

③ 当使用到这个类时,这个类才会进行初始化;

(4)Demo:

1 packagecom.java.test;2 //import com.java.test.Outer.Inner;

3

4 public classTestStaticInner {5 public static voidmain(String[] args) {6 //访问内部类的静态方法

7 //Inner.test();//上面有导包语句,import 包.外部类名.静态内部类名;

8

9 Outer.Inner.test();//外部类名.静态内部类名.静态方法(不使用导包语句)

10

11 //访问内部类的非静态方法

12 //Inner in = new Inner();//上面有导包语句,import 包.外部类名.静态内部类名;

13 Outer.Inner in = newOuter.Inner();14in.method();15

16 Outer out = new Outer(); //内部类不会初始化

17 out.outMethod(); //该方法中用到内部类,内部类会进行初始化

18}19}20 classOuter{21 private int i = 1;22 private static int j = 2;23

24 static{25 System.out.println("外部类的静态代码块");26}27

28 static classInner{29 static{30 System.out.println("静态内部类的代码块");31}32

33 public voidmethod(){34 System.out.println("静态内部类的非静态方法");35 //System.out.println(i);//错误,不能访问非静态的

36System.out.println(j);37}38

39 public static voidtest(){40 System.out.println("静态内部类的静态方法");41}42}43 //外部类访问内部类

44 public voidoutMethod(){45 Inner in = newInner();46 in.method();//非静态方法,用对象名.访问

47

48 Inner.test();//静态方法,用类名.访问

49}50 }

(5)

3、成员内部类(非静态内部类)

(1)语法格式

【修饰符】 class 外部类 【 extends 父类】 【implements 父接口们】{

【其他修饰符】 class 内部类 【 extends 父类】 【implements 父接口们】{

}

}

(2)特点

① 在非静态内部类中,不能出现任何和 static 有关的声明;

② 在非静态内部类中,可以随意访问外部类的所有的成员,包括静态的和非静态的;

③ 在外部类的静态成员中,不能使用非静态的成员内部类;

④ 在外部类的外面使用

第一步:先创建外部类的对象

第二步:要么通过外部类的对象,去创建内部类的对象

Outer out = new Outer();

Outer.Inner in = out.new Inner();

要么通过外部类的对象,去获取内部类的对象

Outer out = new Outer();

Outer.Inner in = out.getInner();

(3)Demo

1 public classTestNonStaticInner {2 public static voidmain(String[] args) {3 //Outer.Inner in = new Outer.Inner();//错误的

4

5 //在这里使用Inner,因为此时的Inner是Outer的非静态成员,所以需要用到Outer的对象

6 Outer out = newOuter();7 //Outer.Inner in = out.new Inner();

8 Outer.Inner in =out.getInner();9in.method();10}11}12 classOuter{13 private int i = 1;14 private static int j = 2;15

16 classInner{17 public voidmethod(){18 System.out.println("非静态内部类的非静态方法");19System.out.println(i);20System.out.println(j);21}22}23

24 public static voidoutTest(){25 //Inner in = new Inner();//静态的方法不能访问非静态的成员

26}27 public voidoutMethod(){28 Inner in = newInner();29in.method();30}31

32 publicInner getInner(){33 return newInner();34}35 }

(4)练习案例:创建一个外部类,里面有一个抽象内部类,并有一个抽象方法,要求写一个类去继承该内部类;

代码:

1 public classTest {2 public static voidmain(String[] args) {3 MySub my = new MySub(newOuter());4my.test();5}6}7 classOuter{8 abstract classInner{9 public abstract voidtest();10}11}12 class MySub extendsOuter.Inner{13MySub(Outer out){14 out.super();//需要外部类的对象,才能调用非静态内部类的构造器

15}16

17@Override18 public voidtest() {19 System.out.println("hello");20}21 }

(5)小节

① 使用非静态内部类名时,可以使用:import 包.外部类名.内部类名; 或 外部类名.内部类名;

② 要调用非静态内部类的构造器,需要用到外部类的对象;

③ 因为子类的构造器的首行一定要调用父类的构造器,默认调用父类的无参构造(需要借助外部类对象);

④ 继承抽象内部类,要重写抽象类的抽象方法;

注意:内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的 .class 文件,但是前面冠以外部类的类名和 $ 符号。如:Person$Heart.class

三、局部内部类

1、概述

局部内部类:定义在类中方法中(方法内、代码块内、构造器内)的类,就是局部内部类。

即只有当前所属的方法才能使用它,出了这个方法外面就不能使用了。

2、分类

(1)有名字的局部内部类:简称局部内部类;

(2)没名字的局部内部类:简称 匿名内部类。

3、语法格式

局部内部类定义格式:

【修饰符】 class 外部类名称 {

【修饰符】 返回值类型 外部类方法名称(参数列表) {

【修饰符】 class 有名字的局部内部类名称 {

// ...

}

}

}

说明:如果子类调用的是父类的无参构造,那么()中实参列表不用写;

如果子类调用的是父类的有参构造,那么()中传入实参列表;

定义一个类的时候,权限修饰符规则:

(1)外部类:public / default

(2)成员内部类:public / protected / default / private

(3)局部内部类:不加任何修饰符

4、特点

(1)局部内部类的修饰符,只能有 abstract 或 final;

(2)局部内部类有使用的作用域;

(3)如果局部内部类在静态方法中,不能使用外部类的非静态成员;

(4)在局部内部类中,可以使用当前局部内部类所在方法的局部变量,但是要求,这个局部变量必须是 final的常量。

5、扩展

在Java8时,如果某个局部变量被局部内部类使用了,会自动添加final变为常量,一旦变为常量,它的值就不能修改了。

为什么它要这么要求?给局部变量加 final呢?

避免局部内部类对象被返回到外部类的外面使用时,访问不到这个局部变量,所以要把这个局部变量变为final的常量。(常量在方法区中)

原因:

① new出来的对象在堆内存当中。

② 局部变量是跟着方法走的,在栈内存当中。

③ 方法运行结束之后,立刻出栈,局部变量就会立刻消失。

④ 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。

Demo:

1 public classTestLocalInner {2 public static voidmain(String[] args) {3 Outer out = newOuter();4 Father in = out.test();//在外部类的外面虽然不能使用局部内部类,但是可以得到它的对象

5System.out.println(in.getClass());6 in.method();//在这里仍然可以访问到这个a,那么这个a就不能存在栈中,得挪到方法区,变为常量

7}8}9 abstract classFather{10 public abstract voidmethod();11}12 classOuter{13 private int i = 1;//成员变量,实例变量,非静态成员变量

14 private static int j = 2;//成员变量,类变量,静态变量

15

16 publicFather test(){17 //Inner in = new Inner(); 现在还没有声明该类,不能使用

18

19 final int a = 10;//局部变量==>局部的常量

20

21 //局部内部类

22 class Inner extendsFather{23 public voidmethod(){24System.out.println(i);25System.out.println(j);26System.out.println(a);27}28}29

30 Inner in = newInner();31in.method();32

33 returnin;34}35

36 public voidmethod(){37 //Inner in = new Inner(); 超过了作用域

38}39

40 public static voidfun(){41 //局部内部类

42 classInner{43 public voidmethod(){44 //System.out.println(i);//是因为fun方法是静态的

45System.out.println(j);46}47}48}49 }

6、

四、匿名内部类【重要】

1、概述

匿名内部类:是内部类的简化写法。它的本质是一个 带具体实现的  父类或者父接口的 匿名的 子类对象。

匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在 new 的后面,用其隐含实现一个接口或实现一个类。

开发中,最常用到的内部类就是匿名内部类了,以接口为例,当你使用一个接口时,都得做如下几步操作:

(1)定义子类

(2)重写接口中的方法

(3)创建子类对象

(4)调用重写后的方法

而匿名类就可以把以上四步合成一步。

前提:匿名内部类必须继承一个父类或者实现一个父接口

2、语法格式

定义格式:

new 父类名或者接口名(){

// 方法重写

@Override

public void method() {

// 执行语句

}

};

特殊:声明匿名内部类与创建它的对象是一起完成的,即匿名内部类只有唯一的对象。

匿名内部类的特点:

(1)匿名内部类必须继承父类或实现接口;

(2)匿名内部类只能有一个对象;

(3)匿名内部类对象只能使用多态形式引用;

3、使用案例

以接口为例,匿名内部类的使用。

定义接口:

1 public abstract class FlyAble{

2 public abstract void fly();

3 }

创建匿名内部类,并调用:

1 public class InnerDemo {

2 public static void main(String[] args) {

3 /*

4 1.等号右边:是匿名内部类,定义并创建该接口的子类对象

5 2.等号左边:是多态赋值,接口类型引用指向子类对象

6 */

7 FlyAble f = new FlyAble(){

8   public void fly() {

9   System.out.println("我飞了~~~");

10   }

11 };

12 //调用 fly方法,执行重写后的方法

13 f.fly();

14 }

15 }

通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。如下所示

1 public class InnerDemo2 {

2 public static void main(String[] args) {

3 /*

4 1.等号右边:定义并创建该接口的子类对象

5 2.等号左边:是多态,接口类型引用指向子类对象

6 */

7 FlyAble f = new FlyAble(){

8   public void fly() {

9   System.out.println("我飞了~~~");

10   }

11 };

12 // 将f传递给showFly方法中

13 showFly(f);

14 }

15 public static void showFly(FlyAble f) {

16 f.fly();

17 }

18 }

将以上两步,也可以简化为一步:

1 public class InnerDemo3 {

2 public static void main(String[] args) {

3 /*

4 创建匿名内部类,直接传递给showFly(FlyAble f)

5 */

6 showFly( new FlyAble(){

7 public void fly() {

8 System.out.println("我飞了~~~");

9 }

10 });

11 }

12 public static void showFly(FlyAble f) {

13 f.fly();

14 }

15 }

4、

五、

类的成员包含 java_Java 面向对象(十五)类的成员 之 内部类相关推荐

  1. 设计一个汽车类Auto,其中包含一个表示速度的double型成员变量speed和表示启动的start0方法、表示加速的speedUp()方法以及表示停止的stop()方法。

    设计一个汽车类Auto,其中包含一个表示速度的double型成员变量speed和表示启动的start0方法.表示加速的speedUp()方法以及表示停止的stop()方法.再设计一个Auto的子类Bu ...

  2. Java学习之设计一个汽车类Auto,其中包含一个表示速度的double型成员变量speed和表示启动的start()方法、表示加速的speedUp()方法以及表示停止的stop()方法。

    案例介绍: 请设计一个汽车类Auto,其中包含一个表示速度的double刑的成员恋量speed,表示启动的start()方法.表示加速的speedUp()方法以及表示停止的 stop()方法.再设计一 ...

  3. Python学习笔记整理(十五)类的编写细节

    类代码编写细节 一.class语句 一般形式 class    <name>(superclass,...):     data=value     def mothod(self,... ...

  4. class unity 定义类_Unity 游戏框架搭建 2019 (二十五) 类的第一个作用 与 Obselete 属性...

    在上一篇我们整理到了第七个示例,我们今天再接着往下整理.我们来看第八个示例: #if UNITY_EDITORusing UnityEditor; #endif using UnityEngine; ...

  5. PHP面向对象学习五 类中接口的应用

    类中接口的应用 接口:一种成员属性全部为抽象的特殊抽象类,在程序中同为规范的作用 抽象类:1.类中至少有一个抽象方法.2.方法前需要加abstract 接口: 1.类中全部为抽象方法,抽象方法前不用加 ...

  6. 【Java学习笔记之二十五】初步认知Java内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人对内部类也只是略知一二). 第一次见面 内部类我们从外面看是非常容易理解的,无非就是在 ...

  7. python类定义的讲解_python面向对象、自定义类等使用实例讲解

    python 面向对象相对别的语言来说缺少两个功能: 1.python不具备重载,重载是指在同一个类中,使得方法有相同的名称,但是有不同的参数列表,但由于python函数具有强大的参数处理功能,因此这 ...

  8. Java集合可分成什么类_java.util包含Java中大量工具类、集合类等,例如Arrays、List、Set等。...

    [论述题]1.观看市川昆的电影<野火>1958,分析该电影的主旨思想 2.观看市川昆的电影<细雪>1983,能结合时代分析该电影中四姐妹角色的意义. 二题选一题作答 [单选题] ...

  9. 五类、超五类、六类跳线

    五类线的标识是"CAT5",带宽100M ,适用于百兆以下的网:超五类线的标识是"CAT5E",带宽155M,是目前的主流产品:六类线的标识是" CA ...

最新文章

  1. 让delphi程序不受WINDOWS日期格式的影响
  2. Python爬虫应用实战案例-xpath正则表达式使用方法,爬取精美壁纸
  3. poj 1061 (扩展欧几里德算法)
  4. python字符串逆序输出代码_一行代码实现字符串逆序输出
  5. python将2个列表list合并到1个列表使用appenden_【新手入门】20个很实用的 Python 学习小技巧...
  6. java.lang.Class.isPrimitive()用法解析
  7. bzoj3224 普通平衡树(splay 模板)
  8. 安装英伟达驱动,提示驱动和windows版本不兼容或是硬件不兼容的问题
  9. 上传多张图片到oss服务器
  10. 求助:PostgreSQL崩溃问题
  11. oppo手机html文件管理,oppo手机文件管理里面的文件可不可以删除
  12. 罗永浩:我对3月27日那场锤子发布会非常懊悔
  13. 项目--静态资源cdn的引入
  14. 谷歌翻译不能用了,怎么办
  15. 为什么用抓包工具看HTTPS包是明文的
  16. iOS 健康 获取运动步数 距离 时间
  17. 这可能是全网最简单的KMP了
  18. 黑莓之殇:曾经接过地气,可惜地气已变
  19. 如何判断团队是否真正实施Scrum -- Scrum方法二十问(一) Scrum 使用者强烈推荐
  20. 网站服务器怎么恢复原来数据库,五步骤完成WordPress网站和数据库备份、搬迁恢复访问...

热门文章

  1. 验证码识别技术(1) - 边缘检测
  2. 如何监听Canvas上滚动条的出现或隐藏
  3. Android实例-解决虚拟键盘遮挡问题(XE8+小米2)
  4. Win7安装软件,界面上中文显示乱码的解决方案
  5. Myeclipse中导入项目后java类中汉字注释出现乱码问题(已解决)
  6. Oracle安装ORA-12154和ORA-12169问题的解决
  7. 解决vue在ios或android中用webview打开H5链接时#号后面的参数被忽略问题angular同样适用
  8. ERROR:org.apache.hadoop.hbase.PleaseHoldException: Master is initializing 解决方案
  9. 如何将C#对象转换为.NET中的JSON字符串?
  10. 如何替换所有出现的字符串?