java基础-枚举实现机制
枚举类型在编译器处理之后,是由一个final的继承Enum类的类实现的。该类是一个实实在在存在的类。在该类当中,编译器还帮助我们生成了每个枚举类型的实例对象,这些对象分别对应枚举中定义的每个枚举类型本身。
java中的内部类
定义:将一个类的定义放在另一个类的定义内部,即为内部类。
内部类本质上是java的一种"语法糖"。为什么这样说呢?举例说明,假设现在有如下代码:
public class A {
private int a;
static class B {
}
class C {
public void test(){
int b = a;
}
}
}
类A是一个普通的类,在他的内部定义了两个类B,以及C。从代码结构上来看,B类和C类为A类的内部,但是在使用编译器编译之后,它们并不是一个类,而是会变成符合一定名称规则的三个类
它在编译之后会产生三个.class文件,分别是:A.class, A$B.class, A$C.class. 因此,本质上它们还是三个类,只是借助于java编译器的语法糖支持,我们可以写在一个类里面,从这个例子我们不难推断出,在java 里任何一个类,无论是以怎样的形式定义,在编译之后生成字节码文件之后,其必然是一个单独存在的类。理解java的类加载机制的话对这句话理解起来就更加容易,java加载任何一个类的时候都是会首先从加载其class文件开始,若一个类不存在对应的class文件,那么它必然无法被加载也无法被使用。
同时,知道了上述知识之后,我们来看这样两个问题:
内部类可以被继承吗?答案是肯定可以的,只是从java语法来说写起来会稍微有点区别
内部类的方法可以被覆盖吗?答案一样是可以的。
为何java编译器会支持定义内部类这样的使用方式,原因在于当一个类定义在另一个类内部之后,许多操作会变得简单一些,比如一个内部类可以直接访问外部类的任何成员。为什么内部类能直接访问外部类的任何成员呢?原因在于java编译器对内部类的功能t提供了支持,让我们再来看上述代码反编译回来的结果:
public class A {
private int a;
public A() {
}
class C {
C() {
}
public void test() {
int b = A.this.a;//通过类名加this关键字
}
}
static class B {
B() {
}
}
}
可以看到是通过类名跟上.this关键字实现的对外部成员的访问,这相当于是隐式的持有了一个外部类引用,即建立了一个内部类和外部类之间的联系。
同时,这里我们需要注意这里的B类声明成了static的类,C类则没有。我们常常把用static修饰的内部类成为嵌套类。
他们的区别在于,嵌套类与外围类之间是没有联系的。这意味这创建嵌套类无需外部类,当然,也不能从嵌套类的对象中访问非静态的外围类对象。同时,在嵌套类的内部可以使用static关键字,而普通的内部类不能使用static关键字。
用途:从代码的组织结构来说,使用内部类可以把逻辑相关的类组织在一起。内部类访问外部类将非常方便,内部类能访问外围对象的所有成员,且不需要任何特殊条件。但这不是最主要的原因,从设计角度出发,使用内部类最大的原因在于:每个内部类可以独立但继承一个类,这意味着虽然java的类是单继承的,但是通过使用内部类,可以达到类似多重继承的效果。因此,如果不需要解决多重继承的问题,使用内部类就并不是必须的了,因为其他的编码方式都能实现一样的效果。