Java各种称呼类详解
  Java有各种各样类,内部类、嵌套类、成员类、局部类(本地类)、静态类、匿名类、文件类以及这些组合起来的称呼类,成员内部类,成员匿名类,成员嵌套类,本地匿名类等,真是多的不行,但有些其实是一个意思,在这里好好理一理。

声明
  1.注意,这些称呼都是翻译过来的,但是同一个英文单词或一个词组翻译过来可能有不同叫法,比如local nested class,local有局部、本地意思,其实是一个意思,local nested class翻译过来就是局部嵌套类(本地嵌套类),又因为非静态嵌套类都称为内部类,所以local nested class又叫为内部局部类(本地内部类),最终又简称为:局部类(本地类)。我个人觉得局部类更加形象点所以下面都优先采用局部类一说。
  2.我通过搜索找到两种不太相同的内部类定义,一种认为:定义在类里面的称为嵌套类(nested class),而非静态嵌套类才是内部类(inner class),也就是说嵌套类包含内部类;另外一种则是认为:定义在类里面的称为内部类,这样静态嵌套类也是内部类,也就是说嵌套类=内部类。但是,第一种才是Java语言规范规定的,我一开始不确定,找到Java7的语言规范验证,结果确实如此,即第一种才是正确的,那么问题来了:依照第一种划分,静态内部类其实是一种错误说法。。。只有静态嵌套类,内部类是没有静态一说的!
  但是对于大多数中国程序员,貌似将定义在类里面的类称为内部类不是更符合文意么?也许这就是为什么会有这么多人一直认为静态内部类的存在。嘛,反正不管怎么称呼,只要知道代表什么意思就好,细节什么的不要在意(光哥:所以不注意细节的你写的代码才这么一大堆bug么?还不赶紧去改(怒吼))。
  我这里采用Java语言规范上说的。

0.文件类
  文件类放在最前面,是因为文件类是与主类(一个文件中public类)关系最不密切的一类。什么是文件类?看代码就知道:

public class Main{}
class Test{}//Test就是文件类
//是的,一个.java文件里面定义在主类外面的就是文件类
//主类、文件类称为顶级类(top level class),Java语言规范中定义:非嵌套类即为顶级类。

【注意】:主类这一定义是我自己按语义称呼的,有的地方称为基本类,但我觉得很不符合语义,Java语言规范我也没找到相关定义。

因为一个.java文件只能有一个主类(public 类),所以文件类默认只能是包访问权限,即:不是同一个包的是无法引入和使用的。
1.嵌套类
  由上面文件类可有类似定义:一个.java文件里面定义在类里面的就是嵌套类,定义在类内部,包括块、静态块、构造器、方法内。这个时候该类也相对来被称为包装类(enclosing class)或外部类。
  嵌套类是可以有层次的,也就是说嵌套类里面还可以定义类,成为嵌套类中的嵌套类。
  在Java语言规范里面,嵌套类定义是:

A nested class is any class whose declaration occurs within the body of
another class or interface.

  说的简单一点,就是定义在类(这里还包括接口,下同)里面的类。所以说,以下所有的类都可以称为嵌套类。嵌套类分为两种:静态嵌套类和非静态嵌套类,非静态嵌套类就是内部类(inner class)。

静态嵌套类
  简称静态类,和主类关系也不大,只是在其他类中引用使用的时候需要加上外部类限定,但在技术上来看,完全是两个独立无关系的类。

public class Main{
    public static class NestClass{}
}
//在外面使用时候形式如下,在Main中使用则不需要加上外部类限定
Main.NestClass nestClass = new Main.NestClass();

  从形式上来看,静态类可以说是类的一个静态成员(所以也可以说是成员类一种),但从技术上来看,其实二者没什么关系,可以看做第三类顶级类。但也因此,静态类不怎么常用,因为它同一般类没什么优势可言。

静态类不能访问外部类的非静态成员和非静态方法(不管是public还是private的);
静态类的实例不需要先实例化外部类成员,可直接实例化。
2.内部类
  Java语言规范里的定义:

An inner class is a nested class that is not explicitly or implicitly
declared static.
//即非静态嵌套类即为内部类

内部类包括:成员类、局部类、匿名类。

内部类中不能有静态修饰的成员(比如块、字段、方法、接口等),总之不能有static关键字,除了一种情况,那就是静态常量,又因为常量成员字段必须在声明的时候初始化,所以形式只能如:public static final int a = 6;
内部类可以访问外部类任何成员,不管是公有的还是私有的,静态的还是非静态的(并且内部类的成员的名字也可以同外部相同,只不过这样会覆盖掉去外部类的),这是因为每一个内部类都保存了一个对外部类的一个引用。这很好理解,因为你要实例化这个内部类,肯定是通过外部类的一个实例,而内部类保留的这个引用就是这个外部类实例。
内部类命名格式:外部类名称+$+[该种类同名类中该类顺序]+[内部类名称],例如成员类,成员类不能同名,所以也就没有同名类顺序:com.fcc.test.OuterClass$MemberClass;局部类:com.fcc.test.OuterClass$1LocalClass;匿名类:匿名类没有名称,所以格式如:com.fcc.OuterClass$1。
成员类
  这里说的是非静态成员内部类(如果静态嵌套类也算是成员类一种的话),non-static member (inner) class。而一般说的也是这种,但从技术上来看,成员类应该还包括静态嵌套类。

A member class is a class whose declaration is directly enclosed in
another class or interface declaration.

  成员类算是最常见最常用的一种内部类,我们一般说的内部类说的就是成员类:在类里面,但不在块、构造器、方法里面。

//成员类,从技术上来说,可以分为两种:成员内部类和成员嵌套类。
//1.成员内部类即这里说的成员类,全称是非静态成员内部类
//2.成员嵌套类即上面的静态嵌套类
public class Main{
    public class MemberClass{}//成员内部类,常简称为成员类
}

  成员类,可以使用public,private,protected访问控制符,也可以用static,final关键字修饰,并且有enclose class属性。
这里题外说明一下:

成员(member),只要是在类里面的(但不在块、构造器、方法内),都是成员:可以是变量,就是成员变量(一般又称为成员字段,Field);可以是方法,好吧,方法都是成员(因为Java中方法不可能位于类外)的;当然,同样的,也可以是接口、枚举、注释类以及类。
关于static理解,有static修饰的是类本身属性(共性),所以访问可以不通过类的实例对象,而非static修饰的,是对象属性(个性),必须通过类的实例对象访问,因为个性是个体的属性啊,当然要创建出个体,然后这个个性才有意义。
关于enclose class,enclose method,enclose constructor属性,可以理解为这个类是被类、还是方法、构造器包装起来的。关于这些属性,可以参考Class类:Java源码解析(2) —— Class(1)。
局部类(本地类)
  local nested class,局部嵌套类,简称局部类,局部类所属范围:在块、构造器以及方法内,这里的块包括普通块和静态块。局部类只在本块范围内有效。
定义:

A local class is a nested class (§8) that is not a member of any class
and that has a name.

翻译过来就是:局部类是嵌套类,但不是成员类,而且有名称(不是匿名类)。

public class Test {
    {
        class AA{}//块内局部类
    }
    public Test(){
        class AA{}//构造器内局部类
    }
    public static void main(String[] args){
    }
    public void test(){
        class AA{}//方法内局部类
    }
}
//注意到了吧,可以同名,编译后,形成诸如:外部类名称+$+同名顺序+局部类名称
//Test$1AA.class/Test$2AA.class/Test$3AA.class

  局部类最多只能有final修饰,但不同的是,块内局部类有enclose class属性,而构造器局部类有enclose constructor属性,方法局部类有enclose method属性,嘛,其实很好理解的吧,一看就知道。

局部类只能访问(使用)这个块中(局部类外)final属性。这里的块包括了上面说的块、构造器、方法。
匿名类
定义:

An anonymous class declaration is automatically derived from a class
instance creation expression by the Java compiler

  匿名类,就是没有名称的类,其名称由Java编译器给出,一般是形如:外部类名称+$+匿名类顺序,没有名称也就是其他地方就不能引用,不能实例化,只用一次,当然也就不能有构造器。
  匿名类根据位于地方不同分为:成员匿名类和局部匿名类。

public class Test {
    InterfaceA a = new InterfaceA() {};//成员匿名类
    public static void main(String[] args){
        InterfaceA a = new InterfaceA() {};//局部匿名类
        //以上两种是通过实现接口实现匿名类,称为接口式匿名类,也可以通过继承类
        Test test = new Test(){};//继承式匿名类
        //还可以是位于参数上
        new Thread(new Runnable() {
            @Override
            public void run() {
            }
        }).start();//属于局部匿名类一种
    }
    private interface InterfaceA{}
}

  匿名类不能使用任何关键字和访问控制符,匿名类和局部类访问规则一样,只不过内部类显式的定义了一个类,然后通过new的方式创建这个局部类实例,而匿名类直接new一个类实例,没有定义这个类。匿名类最常见的方式就是回调模式的使用,通过默认实现一个接口创建一个匿名类然后,然后new这个匿名类的实例。

总结
  本文讨论的是:嵌套类、内部类、成员类、局部类、匿名类相关,这些类的划分主要是根据类声明(或位于)的地方划分的:
1.嵌套类,位于类内部,又分为:静态嵌套类和非静态嵌套类。
2.静态嵌套类即为静态类。静态类只有这一种,技术来说,也可以看成静态成员类。
3.非静态嵌套类即为内部类,又分为:成员类、局部类(本地类)、匿名类。
4.成员类:位于类内部但不包括位于块、构造器、方法内,且有名称的类。
5.局部类:位于块、构造器、方法内的有名称类。
6.匿名类:类内无名称类,又可细分为:成员匿名类和局部匿名类。

Java 内部类、成员类、局部类、匿名类等的更多相关文章

  1. Java 内部类,成员类,局部类,匿名类等

    根据内部类的位置不同,可将内部类分为 :成员内部类与局部内部类. class outer{ class inner{//成员内部类 } public void method() { class loc ...

  2. Java内部类与外部类

    错误提示: 没有任何类型 TestThread 的外层实例可访问.必须用类型 TestThread 的外层实例(例如,x.new A(),其中 x 是 TestThread 的实例)来限定分配. pu ...

  3. java 内部类、匿名内部类、嵌套类的使用

    我们都知道java的类能够由public.default(缺省.不写)来修饰,分别表示的含义是同意公开訪问以及仅仅同意包内其他类訪问,而同一包内的类一般是为完毕同一个功能而协作.      除此之外, ...

  4. Java内部类与外部类的那些事

    昨天去笔试的时候遇到了Java的内部类的创建方式与访问权限的问题,我不懂,没写,故今天起来特意去试验一下,就有了这篇总结性的文章. Java中的内部类又分为非静态内部类(匿名内部类也是非静态的内部类) ...

  5. java 内部类与外部类的区别

    最近在看Java相关知识的时候发现Java中同时存在内部类以及非公有类概念,而且这两个类都可以不需要单独的文件编写,可以与其他类共用一个文件.现根据个人总结将两者的异同点总结如下,如有什么不当地方,欢 ...

  6. java内部类 和外部类的区别

    java 内部类和静态内部类的区别  详细连接https://www.cnblogs.com/aademeng/articles/6192954.html 下面说一说内部类(Inner Class)和 ...

  7. java内部类和外部类

    1.使用static可以声明一个内部类, 可以直接在外部调用 class Outer{ // 定义外部类 private static String info = "hello world& ...

  8. Java内部类和外部类的通信探索

    1.内部类访问外部类的成员和方法 在内部类中,可以无障碍地访问外部类的所有成员和方法. 在下面的实验代码中,可以看到,内部类sl可以访问外部类的私有成员:sz 和 cur. 同时可以访问私有方法:pr ...

  9. 从字节码的角度看Java内部类与外部类的互相访问

    Java中non-static内部类为何可以访问外部类的变量?Java中外部类又为何可以访问内部类的private变量?这两个问题困扰过我一段时间,查了一些网上的答案,大多从“闭包”概念入手,理解起来 ...

  10. Java内部类引用外部类中的局部变量为何必须是final问题解析

    今天编写一个多线程程序,发现在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,百思不得其解,后来想到应该是生命周期的原因,因为方法内定义的变量是局部变量,离开该方 ...

随机推荐

  1. Constructing Tests CodeForces - 938C

    大意: 定义m-free矩阵: 所有$m*m$的子矩阵至少有一个$0$的$01$矩阵. 定义一个函数$f(n,m)=n*n$的m-free矩阵最大$1$的个数. 给出$t$个询问, 每个询问给出$x$ ...

  2. C# 如何判断指定文件是否正被其它程序使用

    C# 如何判断指定文件是否正被其它程序使用 起因:项目中发现在操作文件时,系统经常抛出异常,表示文件正被其它程序占用. 需求:为了事先判断,以确认指定的文件是否正被其它程序使用,需要方法进行判断. 思 ...

  3. mysql-8.0.17-winx64 部署

    1.官网下载mysql-8.0.17-winx64,选择Zip文件格式下载 2.解压到目标路径,我这里是E盘根目录,即E:\mysql8 3.根目录下创建my.ini,内容如下: [mysqld]#端 ...

  4. CentOs 7.6 开启防火墙后 无法显示远程文件夹

    转:https://blog.csdn.net/ygwlove0110/article/details/88232065 遇到了个坑.服务器开启了防火墙后,ftp客户端连接就无法显示目录.关掉防火墙就 ...

  5. 哈希表(Hash table)

  6. window10提交代码到码云

    1.创建项目文件夹,例如创建一个"爬虫项目码云仓库" 2.进入项目文件夹,在地址栏输入cmd然后回车,这样就在该文件夹打开了终端 3.终端输入git init初始化项目仓库,此时会 ...

  7. 爬取快代理的免费IP并测试

    各大免费IP的网站的反爬手段往往是封掉在一定时间内访问过于频繁的IP,因此在爬取的时候需要设定一定的时间间隔,不过说实话,免费代理很多时候基本都不能用,可能一千个下来只有十几个可以用,而且几分钟之后估 ...

  8. python删除数组中元素

    有数组a,要求去掉a所有为0的元素 a = [2,4,0,8,9,10,100,0,9,7] Filter a= filter(None, a) Lambada a = filter(lambda x ...

  9. 设置Linux之CentOS7的网络的两种方式动态IP+静态IP

    1 动态IP 参考之前的文章 点击进入 2 静态IP vi /etc/sysconfig/network-scripts/ifcfg-ens33 详情配置如下,上面半部分是我之前的动态IP的设置 静态 ...

  10. mysoft

    @@a8649fbb56349908b5ca6708fb94b3ddabcf6b97381a9797d3dfb139b8749287117@@##74e02e1207e5a0a8996ba89f1d6 ...