• 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.
  • 相关阅读:
    SELECT IDENT_CURRENT(tableName)和自增长列的纠结
    [置顶]c# 设计模式(1)一 创建型
    我们互联网生活因家庭服务器改变
    互联网创业不妨先放下平台梦
    影响未来的应用ifttt,互联网自主神经系统的又一个有力证据
    什么是ifttt,ifttt怎么玩? ifttt操作体验具体步骤
    杰出企业家的20个好习惯
    折叠分组表格中重用Cell导致的问题
    使用AChartEngine画折线图
    MSSQL获取当前插入的ID号及在高并发的时候处理方式
  • 原文地址:https://www.cnblogs.com/csiOS/p/8522507.html
Copyright © 2020-2023  润新知