前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第二阶段-Java面向对象:【第七章 内部类】

第二阶段-Java面向对象:【第七章 内部类】

作者头像
BWH_Steven
发布2019-08-09 15:52:16
2660
发布2019-08-09 15:52:16
举报
文章被收录于专栏:理想二旬不止理想二旬不止

(一)

内部类概述

把类定义在另一个类的内部,该类就被称为内部类。

举例:把类Inner定义在类Outer中,类Inner就被称为内部类。

代码语言:javascript
复制
  class Outer {
   class Inner {
   }
}

(二)

内部类的访问规则

A:可以直接访问外部类的成员,包括私有

B:外部类要想访问内部类成员,必须创建对象

(三)

内部类的分类

A:成员内部类

B:局部内部类

C:静态内部类

D:匿名内部类

(1) 成员内部类

成员内部类——就是位于外部类成员位置的类 特点:可以使用外部类中所有的成员变量和成员方法(包括private的)

A:格式:
代码语言:javascript
复制
  class Outer {
     private int age = 20;
 //成员位置
     class Inner {
         public void show() {
             System.out.println(age);
         }
     }
 }
 
 class Test {
     public static void main(String[] ages) {
 //成员内部类是非静态的演示
         Outer.Inner oi = new Outer.new Inner();
         oi.show();
     }
 }
B:创建对象时:
代码语言:javascript
复制
  //成员内部类不是静态的:
 外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
 
 //成员内部类是静态的:
 外部类名.内部类名 对象名 = new 外部类名.内部类名();
C:成员内部类常见修饰符:

A:private

如果我们的内部类不想轻易被任何人访问,可以选择使用private修饰内部类,这样我们就无法通过创建对象的方法来访问,想要访问只需要在外部类中定义一个public修饰的方法,间接调用。这样做的好处就是,我们可以在这个public方法中增加一些判断语句,起到数据安全的作用。

代码语言:javascript
复制
  class Outer {
     private class Inner {
         public void show() {
             System.out.println(“密码备份文件”);
         }
     }
     
     public void method() {
      if(你是管理员){
       Inner i = new Inner();
       i.show();
      }else {
       System.out.println(“你没有权限访问”);
      }
     }
 }

下面我们给出一个更加规范的写法

代码语言:javascript
复制
  class Outer {
     private class Inner {
         public void show() {
             System.out.println(“密码备份文件”);
         }
     }
 //使用getXxx()获取成员内部类,可以增加校验语句(文中省略)
     public void getInner() {
   return new Inner();
     }
     
     public static void main(String[] args) {
      Outer outer = new Outer();
         Outer.Inner inner = outer.getInner();
         inner.show();
     }
 }
B:static

这种被 static 所修饰的内部类,按位置分,属于成员内部类,但也可以称作静态内部类,也常叫做嵌套内部类。具体内容我们在下面详细讲解。

D:成员内部类经典题(填空)

请在三个println 后括号中填空使得输出25,20,18

代码语言:javascript
复制
  class Outer {
  public int age = 18; 
  class Inner {
   public int age = 20; 
   public viod showAge() {
    int age  = 25;
    System.out.println(age);//空1
    System.out.println(this.age);//空2
    System.out.println(Outer.this.age);//空3
   }
  }
 }
(2) 局部内部类

局部内部类——就是定义在一个方法或者一个作用域里面的类 特点:主要是作用域发生了变化,只能在自身所在方法和属性中被使用

A 格式:

代码语言:javascript
复制
  class Outer {
     public void method(){
         class Inner {
         }
     }
 }

B:访问时:

代码语言:javascript
复制
  //在局部位置,可以创建内部类对象,通过对象调用和内部类方法
 class Outer {
     private int age = 20;
     public void method() {
         final int age2 = 30;
         class Inner {
             public void show() {
                 System.out.println(age);
 //从内部类中访问方法内变量age2,需要将变量声明为最终类型。
                 System.out.println(age2);
             }
         }
         
         Inner i = new Inner();
         i.show();
     }
 }

C: 为什么局部内部类访问局部变量必须加final修饰呢?

因为局部变量是随着方法的调用而调用使用完毕就消失而堆内存的数据并不会立即消失

所以,堆内存还是用该变量,而该变量已经没有了。为了让该值还存在,就加final修饰。

原因是,当我们使用final修饰变量后,堆内存直接存储的是值,而不是变量名

(即上例 age2 的位置存储着常量30 而不是 age2 这个变量名)

(3) 静态内部类

我们所知道static是不能用来修饰类的,但是成员内部类可以看做外部类中的一个成员,所以可以用static修饰,这种用static修饰的内部类我们称作静态内部类,也称作嵌套内部类. 特点:不能使用外部类的非static成员变量和成员方法

解释:非静态内部类编译后会默认的保存一个指向外部类的引用,而静态类却没有。

简单理解

即使没有外部类对象,也可以创建静态内部类对象,而外部类的非static成员必须依赖于对象的调用,静态成员则可以直接使用类调用,不必依赖于外部类的对象,所以静态内部类只能访问静态的外部属性和方法。

代码语言:javascript
复制
  class Outter {
     int age = 10;
     static age2 = 20;
     public Outter() {        
     }
      
     static class Inner {
         public method() {
             System.out.println(age);//错误
             System.out.println(age2);//正确
         }
     }
 }
 
 public class Test {
     public static void main(String[] args)  {
         Outter.Inner inner = new Outter.Inner();
         inner.method();
     }
 }
(4) 匿名内部类

一个没有名字的类,是内部类的简化写法

A 格式:

代码语言:javascript
复制
  new 类名或者接口名() {
     重写方法();
 }

本质:其实是继承该类或者实现接口的子类匿名对象

这也就是下例中,可以直接使用 new Inner() {}.show(); 的原因 == 子类对象.show();

代码语言:javascript
复制
  interface Inter {
  public abstract void show();
 }
 
 class Outer {
     public void method(){
         new Inner() {
             public void show() {
                 System.out.println("HelloWorld");
             }
         }.show();
     }
 }
 
 class Test {
  public static void main(String[] args)  {
      Outer o = new Outer();
         o.method();
     }
 }    

如果匿名内部类中有多个方法又该如何调用呢?

代码语言:javascript
复制
  Inter i = new Inner() {  //多态,因为new Inner(){}代表的是接口的子类对象
  public void show() {
  System.out.println("HelloWorld");
  }
 };

B:匿名内部类在开发中的使用

我们在开发的时候,会看到抽象类,或者接口作为参数。

而这个时候,实际需要的是一个子类对象。

如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 理想二旬不止 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • (1) 成员内部类
    • A:格式:
      • B:创建对象时:
        • C:成员内部类常见修饰符:
          • B:static
          • (2) 局部内部类
          • (3) 静态内部类
          • (4) 匿名内部类
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档