07_JavaSE之OOP--面向对象(内部类)

对象(七)

一、内部类(inner class)的概述

内部类,顾名思义就是定义在一个类中的一个类。如:

1 class OuterClass{
2    
3     class InnerClass{
4         
5     }
6 }

接下来,我们就来谈谈为什么要使用内部类,以及他有什么特点,如何使用等等。

1.为什么要使用内部类呢?

  • 内部类方法可以访问该类定义所在的作用域数据,包括私有数据。
  • 内部类可以对同一个包中的其他类隐藏起来。
  • 当你想定义一个回调函数不想编写大量代码时,使用匿名内部类比较便捷。[1]

2.内部类访问特点以及如何使用

  • 使用原因其实也就是其特点之一:可以访问该类定义所在的作用域数据,包括私有数据
  • 外部类访问内部类成员,则必须要创建对象。
    见代码:
 1 public class Test_InnerClass {
 2     public static void main(String[] args){
 3         //外部类名.内部类名 对象名 = 外部类对象.内部类对象;
 4         OuterClass.InnerClass oi = new OuterClass().new InnerClass();
 5         //调用方法
 6         oi.method();
 7     }
 8 }
 9 
10 class OuterClass{
11     private int num = 10;
12     class InnerClass{
13         public void method(){
14             System.out.println(num);    //可以直接访问外部类的成员变量
15             System.out.println("感谢关注~");
16         }
17     }
18 }

结果:

 

二、成员内部类私有(private) & 静态成员内部类(static)

1.成员内部类私有

所谓成员内部类私有也就是把内部类加个private,变成私有的。如:

1 class OuterClass{
2     private class InnerClass{
3         public void method(){
4             System.out.println("感谢关注~");
5         }
6     }
7 }

InnerClass前面加个private关键字,没错,就是这样。

那么如何使用呢?

talk is cheap,show me the code.来:

 1 class OuterClass{
 2 
 3     private class InnerClass{//成员内部类被私有了
 4         public void method(){
 5             System.out.println("感谢关注~");
 6         }
 7     }
 8 
 9     //通过在外部类当中写一个方法实例化内部类,调用其方法
10     public void invokeMethod(){
11         InnerClass innerClass = new InnerClass();
12         innerClass.method();
13     }
14 
15 }

如果想要调用,那么就在通过在外部类当中写一个方法实例化内部类,调用其方法。

2.静态成员内部类

静态成员内部类,在内部类加static。如:

 1 public class Test_InnerClass {
 2     public static void main(String[] args){
 3         //外部类名.内部类名 对象名 = 外部类名.内部类对象;
 4         OuterClass.InnerClass o =  new  OuterClass.InnerClass();
 5         o.method();
 6     }
 7 }
 8 
 9 class OuterClass{
10     static class InnerClass{
11         public void method(){
12             System.out.println("Hello World");
13         }
14     }
15 }

结果:

可见,通过外部类名.内部类名 对象名 = 外部类名.内部类对象,进行调用。

可能到这里,有一点会产生混淆。就是单纯内部类调用时和静态内部类调用时。

因此做个比较:

普通内部类调用
外部类名.内部类名 对象名 = 外部类对象.内部类对象

OuterClass.InnerClass oi = new OuterClass().new InnerClass();
静态内部类调用

外部类名.内部类名 对象名 = 外部类名.内部类对象

 OuterClass.InnerClass o =  new  OuterClass.InnerClass();

 普通内部类以及静态内部类,了解即可。哈哈

接下来看看这个题目:(要求控制台输出 30,20,10)

 1 class Outer {
 2     public int num = 10;
 3     class Inner {
 4         public int num = 20;
 5         public void show() {
 6             int num = 30;
 7             System.out.println(A);
 8             System.out.println(B);
 9             System.out.println(C);
10         }
11     }
12 }
13 class TestInnerClass{
14     public static void main(String[] args) {
15         Outer.Inner oi = new Outer().new Inner();
16         oi.show();
17     }
18 }

A B C如何填呢?

内部类之所以能获取到外部类的成员,是因为他能获取到外部类的引用。外部类.this,进而获取到他的值。

三、局部内部类(方法里面的内部类)

所谓局部内部类,其实就是方法里面的内部类。如:

 1 public class Test_InnerClass {
 2     public static void main(String[] args) {
 3         OuterClass outerClass = new OuterClass();
 4         outerClass.method();
 5     }
 6 }
 7 
 8 class OuterClass {
 9 
10     public void method() {
11         class InnerClass { //局部内部类
12 
13             public void playChiJi(){
14                 System.out.println("大吉大利,今晚吃鸡~");
15             }
16         }
17         //只能在方法里进行实例化并访问吃鸡方法
18         InnerClass innerClass = new InnerClass();
19         innerClass.playChiJi();
20     }
21 
22     /*
23     这种方法行不通,因为作用域的问题,内部类只存在于方法内,因此在外部类里实例化不了InnerClass
24     public void invoke(){
25         InnerClass innerClass = new InnerClass();
26         innerClass.playChiJi();
27     }
28     */
29 }

结果:

局部内部类访问局部变量呢?

 1 public class Test_InnerClass {
 2     public static void main(String[] args) {
 3         OuterClass outerClass = new OuterClass();
 4         outerClass.method();
 5     }
 6 }
 7 
 8 class OuterClass {
 9     public void method() {
10         final int num = 10;
11         class InnerClass { //局部内部类
12 
13             public void playChiJi(){
14                 System.out.println(num);//局部内部类访问局部成员方法
15             }
16         }
17         //只能在方法里进行实例化并访问吃鸡方法
18         InnerClass innerClass = new InnerClass();
19         innerClass.playChiJi();
20     }
21 
22 }

结果:输出10.

在jdk1.8之前,局部变量前面必须加final修饰,因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。简而言之,就是加了final就延长了局部变量的生命周期方法弹栈可以继续访问。

但是,jdk1.8以后可以不加final。其实是默认替你添加上了。

 四、匿名内部类(没有名字的类?)

1.匿名内部类初识

对,其实就是没有名字的类。哈哈。

实际上是对内部类的一种简写,适合哪种只调用一次方法的情形。

(非匿名内部类)

 1 public class Test_InnerClass {
 2     public static void main(String[] args) {
 3         OuterClass outerClass = new OuterClass();
 4         outerClass.method();
 5     }
 6 }
 7 
 8 //定义一个接口
 9 interface NoNameInter {
10     void playLOL();
11 }
12 
13 class OuterClass {
14 
15     class InnerClass implements NoNameInter {
16         //重写方法
17         @Override
18         public void playLOL() {
19             System.out.println("晚上一起开黑~");
20         }
21     }
22 
23     //这个是有名字的内部类
24     public void method(){
25         InnerClass innerClass = new InnerClass();
26         innerClass.playLOL();;
27     }
28 }
View Code

(匿名内部类)

 1 public class Test_InnerClass {
 2     public static void main(String[] args) {
 3         OuterClass outerClass = new OuterClass();
 4         outerClass.method();
 5     }
 6 }
 7 
 8 //定义一个接口
 9 interface NoNameInter {
10     void playLOL();
11 }
12 
13 class OuterClass {
14 
15     public void method(){
16 
17         new NoNameInter(){//匿名内部类
18             //重写方法
19             @Override
20             public void playLOL() {
21                 System.out.println("晚上一起开黑~");
22             }
23         }.playLOL();
24     }
25 
26 }
View Code

咱们得一个一个进行解释,首先匿名内部类书写的格式是:

new 类名或者接口名(){
            重写方法;
  }

 前提:存在一个类或者接口
 这里的类可以是具体类也可以是抽象类,正如代码中的按个NoNameInter接口。

 他的本质是继承了该类或者实现了该类接口的子类匿名对象。我去,好绕口。就是,

这就是匿名内部类的书写方式,以及用法。

2.匿名内部类作为参数进行传递

3.匿名内部类的一道程序题

如有错误之处,欢迎指正。

邮箱:it_chang@126.com

stay hungry,stay foolish.
原文地址:https://www.cnblogs.com/csiOS/p/8522507.html