Java各类称呼类详解

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

声明

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

0.文件类

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

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

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

  1. 由于一个.java文件只能有一个主类(public 类),因此文件类默认只能是包访问权限,即:不是同一个包的是没法引入和使用的。

1.嵌套类

  由上面文件类可有相似定义:一个.java文件里面定义在类里面的就是嵌套类,定义在类内部,包括块、静态块、构造器、方法内。这个时候该类也相对来被称为包装类(enclosing class)或外部类。 
  嵌套类是能够有层次的,也就是说嵌套类里面还能够定义类,成为嵌套类中的嵌套类。 
  在Java语言规范里面,嵌套类定义是:spa

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

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

静态嵌套类

  简称静态类,和主类关系也不大,只是在其余类中引用使用的时候须要加上外部类限定,但在技术上来看,彻底是两个独立无关系的类。翻译

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

  从形式上来看,静态类能够说是类的一个静态成员(因此也能够说是成员类一种),但从技术上来看,其实两者没什么关系,能够看作第三类顶级类。但也所以,静态类不怎么经常使用,由于它同通常类没什么优点可言。code

  1. 静态类不能访问外部类的非静态成员和非静态方法(不论是public仍是private的);
  2. 静态类的实例不须要先实例化外部类成员,可直接实例化。

2.内部类

  Java语言规范里的定义:对象

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

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

  1. 内部类中不能有静态修饰的成员(好比块、字段、方法、接口等),总之不能有static关键字,除了一种状况,那就是静态常量,又由于常量成员字段必须在声明的时候初始化,因此形式只能如:public static final int a = 6;
  2. 内部类能够访问外部类任何成员,不论是公有的仍是私有的,静态的仍是非静态的(而且内部类的成员的名字也能够同外部相同,只不过这样会覆盖掉去外部类的),这是由于每个内部类都保存了一个对外部类的一个引用。这很好理解,由于你要实例化这个内部类,确定是经过外部类的一个实例,而内部类保留的这个引用就是这个外部类实例。
  3. 内部类命名格式:外部类名称+$+[该种类同名类中该类顺序]+[内部类名称],例如成员类,成员类不能同名,因此也就没有同名类顺序: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属性。 
这里题外说明一下:

  1. 成员(member),只要是在类里面的(但不在块、构造器、方法内),都是成员:能够是变量,就是成员变量(通常又称为成员字段,Field);能够是方法,好吧,方法都是成员(由于Java中方法不可能位于类外)的;固然,一样的,也能够是接口、枚举、注释类以及类。
  2. 关于static理解,有static修饰的是类自己属性(共性),因此访问能够不经过类的实例对象,而非static修饰的,是对象属性(个性),必须经过类的实例对象访问,由于个性是个体的属性啊,固然要建立出个体,而后这个个性才有意义。
  3. 关于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属性,嘛,其实很好理解的吧,一看就知道。

  1. 局部类只能访问(使用)这个块中(局部类外)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.匿名类:类内无名称类,又可细分为:成员匿名类和局部匿名类。

相关文章
相关标签/搜索