Java基础8:深入理解内部类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础8:深入理解内部类相关的知识,希望对你有一定的参考价值。
Java基础8:深入理解内部类
一、什么是内部类?
内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权限)。内部类主要有以下几类:成员内部类、局部内部类、静态内部类、匿名内部类
二、内部类的共性
(1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
(2)内部类不能用普通的方式访问。
(3)内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。
(4)外部类不能直接访问内部类的的成员,但可以通过内部类对象来访问
内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
因为当某个外围类的对象创建内部类的对象时,此内部类会捕获一个隐式引用,它引用了实例化该内部对象的外围类对象。通过这个指针,可以访问外围类对象的全部状态。
通过反编译内部类的字节码,分析之后主要是通过以下几步做到的:
1 编译器自动为内部类添加一个成员变量, 这个成员变量的类型和外部类的类型相同, 这个成员变量就是指向外部类对象的引用;
2 编译器自动为内部类的构造方法添加一个参数, 参数的类型是外部类的类型, 在构造方法内部使用这个参数为1中添加的成员变量赋值;
3 在调用内部类的构造函数初始化内部类对象时, 会默认传入外部类的引用。
二、使用内部类的好处:
静态内部类的作用:
1 只是为了降低包的深度,方便类的使用,静态内部类适用于包含类当中,但又不依赖与外在的类。
2 由于Java规定静态内部类不能用使用外在类的非静态属性和方法,所以只是为了方便管理类结构而定义。于是我们在创建静态内部类的时候,不需要外部类对象的引用。
非静态内部类的作用:
1 内部类继承自某个类或实现某个接口,内部类的代码操作创建其他外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。
2 使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响
3 如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。 从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了”多重继承”。
三、 那静态内部类与普通内部类有什么区别呢?问得好,区别如下:
(1)静态内部类不持有外部类的引用 在普通内部类中,我们可以直接访问外部类的属性、方法,即使是private类型也可以访问,这是因为内部类持有一个外部类的引用,可以自由访问。而静态内部类,则只可以访问外部类的静态方法和静态属性(如果是private权限也能访问,这是由其代码位置所决定的),其他则不能访问。
(2)静态内部类不依赖外部类 普通内部类与外部类之间是相互依赖的关系,内部类实例不能脱离外部类实例,也就是说它们会同生同死,一起声明,一起被垃圾回收器回收。而静态内部类是可以独立存在的,即使外部类消亡了,静态内部类还是可以存在的。
(3)普通内部类不能声明static的方法和变量 普通内部类不能声明static的方法和变量,注意这里说的是变量,常量(也就是final static修饰的属性)还是可以的,而静态内部类形似外部类,没有任何限制。
==为什么普通内部类不能有静态变量呢?==
1 成员内部类 之所以叫做成员 就是说他是类实例的一部分 而不是类的一部分
2 结构上来说 他和你声明的成员变量是一样的地位 一个特殊的成员变量 而静态的变量是类的一部分和实例无关
3 你若声明一个成员内部类 让他成为主类的实例一部分 然后又想在内部类声明和实例无关的静态的东西 你让JVM情何以堪啊
4 若想在内部类内声明静态字段 就必须将其内部类本身声明为静态
非静态内部类有一个很大的优点:可以自由使用外部类的所有变量和方法
下面的例子大概地介绍了
1 非静态内部类和静态内部类的区别。
2 不同访问权限的内部类的使用。
3 外部类和它的内部类之间的关系
//本节讨论内部类以及不同访问权限的控制
//内部类只有在使用时才会被加载。
//外部类B
public class B{
int i = 1;
int j = 1;
static int s = 1;
static int ss = 1;
A a;
AA aa;
AAA aaa;
//内部类A
?
public class A {
// static void go () {
//
// }
// static {
//
// }
// static int b = 1;//非静态内部类不能有静态成员变量和静态代码块和静态方法,
// 因为内部类在外部类加载时并不会被加载和初始化。
//所以不会进行静态代码的调用
int i = 2;//外部类无法读取内部类的成员,而内部类可以直接访问外部类成员
?
public void test() {
System.out.println(j);
j = 2;
System.out.println(j);
System.out.println(s);//可以访问类的静态成员变量
}
public void test2() {
AA aa = new AA();
AAA aaa = new AAA();
}
?
}
//静态内部类S,可以被外部访问
public static class S {
int i = 1;//访问不到非静态变量。
static int s = 0;//可以有静态变量
?
public static void main(String[] args) {
System.out.println(s);
}