文档章节

《Java基础知识》Java静态内部类、匿名内部类、成员式内部类和局部内部类

o
 osc_ogi0qclx
发布于 2019/08/23 08:43
字数 1199
阅读 5
收藏 0

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

内部类可以是静态(static)的,可以使用 public、protected 和 private 访问控制符,而外部类只能使用 public,或者默认。
成员式内部类
在外部类内部直接定义(不在方法内部或代码块内部)的类就是成员式内部类,它可以直接使用外部类的所有变量和方法,即使是 private 的。外部类要想访问内部类的成员变量和方法,则需要通过内部类的对象来获取。
public class Outer{
    private int size;
    public class Inner {
        public void dostuff() {
            size++;
        }
    }
    public void testTheInner() {
        Inner in = new Inner();
        in.dostuff();
    }
}

成员式内部类如同外部类的一个普通成员。

成员式内部类可以使用各种修饰符,包括 public、protected、private、static、final 和 abstract,也可以不写。

若有 static 修饰符,就为类级,否则为对象级。类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问。

非静态内部类中不能声明任何 static 成员。

内部类可以相互调用,例如:

class A {
    // B、C 间可以互相调用
    class B {}
    class C {}
}

成员式内部类的访问
内部类的对象以成员变量的方式记录其所依赖的外层类对象的引用,因而可以找到该外层类对象并访问其成员。该成员变量是系统自动为非 static 的内部类添加的,名称约定为“outClassName.this”。

  1. 使用内部类中定义的非静态变量和方法时,要先创建外部类的对象,再由“outObjectName.new”操作符创建内部类的对象,再调用内部类的方法,如下所示:
public class Demo{
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.dostuff();
    }
}
class Outer{
    private int size;
    class Inner{
        public void dostuff() {
            size++;
        }
    }
}
  1. static 内部类相当于其外部类的 static 成员,它的对象与外部类对象间不存在依赖关系,因此可直接创建。示例如下:
public class Demo{
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.dostuff();
    }
}

class Outer{
    private static int size;
    static class Inner {
        public void dostuff() {
            size++;
            System.out.println("size=" + size);
        }
    }
}

 运行结果:

  1. 由于内部类可以直接访问其外部类的成分,因此当内部类与其外部类中存在同名属性或方法时,也将导致命名冲突。所以在多层调用时要指明,如下所示:
public class Outer{
    private int size;
    public class Inner{
        private int size;
        public void dostuff(int size){
            size++;  // 局部变量 size;
            this.size;  // 内部类的 size
            Outer.this.size++;  // 外部类的 size
        }
    }
}

局部内部类
局部内部类(Local class)是定义在代码块中的类。它们只在定义它们的代码块中是可见的。

局部类有几个重要特性:
仅在定义了它们的代码块中是可见的;
可以使用定义它们的代码块中的任何局部 final 变量;
局部类不可以是 static 的,里边也不能定义 static 成员;
局部类不可以用 public、private、protected 修饰,只能使用缺省的;
局部类可以是 abstract 的。

请看下面的代码:

public class Outer {
    public static final int TOTAL_NUMBER = 5;
    public int id = 123;
    public void func() {
        final int age = 15;
        String str = "http://www.weixueyuan.net";
        class Inner {
            public void innerTest() {
                System.out.println(TOTAL_NUMBER);
                System.out.println(id);
                // System.out.println(str);不合法,只能访问本地方法的final变量
                System.out.println(age);
            }
        }
        new Inner().innerTest();
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.func();
    }
}

运行结果:

匿名内部类
匿名内部类是局部内部类的一种特殊形式,也就是没有变量名指向这个类的实例,而且具体的类实现会写在这个内部类里面。

注意:匿名类必须继承一个父类或实现一个接口。

不使用匿名内部类来实现抽象方法:

abstract class Person {
    public abstract void eat();
}

class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}

public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

运行结果:

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类。使用匿名内部类实现:

abstract class Person {
    public abstract void eat();
}

public class Demo {
    public static void main(String[] args){
       
        // 继承 Person 类
        new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        }.eat();
    }
}

运行结果:

可以看到,匿名类继承了 Person 类并在大括号中实现了抽象类的方法。

内部类的语法比较复杂,实际开发中也较少用到,并不打算进行深入讲解,各位读者也不应该将内部类作为学习Java的重点。

参考: https://www.jianshu.com/p/ed3f8b0f0471


 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
什么是JAVA内部类?

1、概念 存在于Java类的内部的Java类。 2、分类 成员内部类 格式 编译之后会生成两个class文件:OuterClass.class和OuterClass$InnerClass.clas 方法内部类 格式 编译之后会生成两个class文件...

ConstXiong
2019/11/09
1
0
夯实Java基础系列18:深入理解Java内部类及其实现原理

本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下Star哈 文章首发于我的个人博客: www.ho...

osc_j6se59id
2019/11/01
2
0
闭包与内部类

闭包与内部类 中英文社区中,比较常见的对闭包的定义是 内部类 按照我的理解,scala/java中虽然并不存在语法级地支持或是定义,对于闭包而言,一些概念和闭包的概念一致。一般理解scala中的一...

osc_c9pkd6zt
05/20
15
0
Java 内部类综述

摘要:   多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承。但有时候,我们确实是需要实现多重继承,而且现实生活中...

osc_yw69wr68
2018/07/11
1
0
Java——内部类详解

说起内部类,大家肯定感觉熟悉又陌生,因为一定在很多框架源码中有看到别人使用过,但又感觉自己使用的比较少,今天我就带你具体来看看内部类。 内部类基础 >所谓内部类就是在类的内部继续定...

death05
2019/11/25
4
0

没有更多内容

加载失败,请刷新页面

加载更多

未捕获ReferenceError:未定义$? - Uncaught ReferenceError: $ is not defined?

问题: How come this code throws an 此代码如何引发 Uncaught ReferenceError: $ is not defined 未捕获的ReferenceError:未定义$ when it was OK before? 以前什么时候可以? $(document......

javail
35分钟前
12
0
263. Ugly Number

题目: 263. Ugly Number 题目地址:https://leetcode.com/problems/ugly-number/ Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers......

JiaMing
58分钟前
60
0
HCIA_ARP01

ARP(地址解析协议) eNSP 常用路由器:AR2220 常用交换机:S5700、S3700 常用终端:PC、MCS(主播服务器) 设备连线:Copper(以太网用到的双绞线)、Serial(串口线,2SA接口)、Auto(自动连...

创业789
今天
25
0
如何在Rails 4中使用问题 - How to use concerns in Rails 4

问题: The default Rails 4 project generator now creates the directory "concerns" under controllers and models. 默认的Rails 4项目生成器现在在控制器和模型下创建目录“Concer”。 ......

fyin1314
今天
19
0
【LeetCode】 57 括号生成

题目: 解题思路: https://leetcode-cn.com/problems/generate-parentheses/solution/hui-su-suan-fa-by-liweiwei1419/ 代码: import java.util.ArrayList;import java.util.List;publ......

JaneRoad
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部