内部类,静态内部类,匿名内部类这三种类,从名称上来说,他们的共同点就是内部类,即顾名思义为在一个类(以A表示)中定义另外一个类(以B表示),那么B类就叫内部类,A类就叫外部类
内部类
内部类,也称嵌套类,顾名思义就是在一个A类里面嵌套另外一个普通的B类
public class ClazzOuter {
//外部类A
class ClazzInter {//
//内部类B
}
}
- 内部类拥有外部类的所有元素的访问权
public class ClazzOuter {
private String outerData1 = "这是外部类 private 变量";
public String outerData2 = "这是外部类 public 变量";
private String getOuterData() {
return outerData1 + "|" + outerData2;
}
class ClazzInter {
private String interData1 = "这是内部类 private 变量";
public String interData2 = "这是内部类 public 变量";
public ClazzInter() {
System.out.println("interData1:" + interData1 + ",interData2:" + interData1);
String outerData = getOuterData();
interData1 = outerData1;
interData2 = outerData2;
System.out.println("interData1:" + interData1 + ",interData2:" + interData1 + ",outerData:" + outerData);
}
}
public static void main(String[] args) {
//实例化内部类
new ClazzOuter().new ClazzInter();
}
}
输出内容
interData1:这是内部类 private 变量,interData2:这是内部类 private 变量
interData1:这是外部类 private 变量,interData2:这是外部类 private 变量,outerData:这是外部类 private 变量|这是外部类 public 变量
从输出内容,我们可以得出:B类可以直接访问A类中的元素
其中元素包括成员变量、常量、以及方法,甚至对象等,而这些元素,同时还可以是各种作用域下的元素(全文中的元素同指这些内容
)
2. A类要访问B类时,必须使用B类的引用
public class ClazzOuter {
//...
class ClazzInter {
//...
public ClazzInter() {
//...
}
public String getInterData1() {
return interData1;
}
}
public static void main(String[] args) {
//实例化内部类
ClazzInter inter = new ClazzOuter().new ClazzInter();
inter.getInterData1();
}
}
以上可以验证在A类中如果需要使用B类,那么就需要对B类进行实例,然后使用B类的对象引用进行访问B类的成员,其中的原因,如果有阅读过《Java编程思想》中的this关键字
说明,就会明白:其实inter.getInterData1();
这句的调用在编译器中的内部形态是ClazzInter.getInterData1(inter);
也就是说编译器会把所操作对象的引用
作为第一个参数传给getInterData1()
方法
3. 内部类的成员不能被static进行修饰
上述异常包括两点内容:
- 内部类中不能有static修饰的成员
- 被static修饰的成员不能直接使用非static修饰的成员
静态内部类
静态内部类,其实就是在
内部类
的基础上,多了个static修饰符
public class ClazzOuter {
//外部类A
static class ClazzInter {//
//内部类B
}
}
对比内部类,
- 在B类中只能访问A类中被static进行修饰的元素
- 可在B类中可以定义静态元素和非静态元素
- A类可以直接访问B类中被static进行修饰的元素:
A.B.static修饰的元素
,A类对B类中未被static修饰的元素,依然需要使用内部类中A类对B类的访问方式
匿名内部类
匿名内部类,就是一个没有显式的名字的内部类,它的本质就是隐式的继承一个类或者实现一个接口,或者说,匿名内部类是一个继承了该类或者实现了该接口的子类匿名对象
以接口为例,接口本身是不能被New出来的,但是在如果要强行使用New的方式来实例它,我们会发现这个接口会带一对{}
,并且需要实现该接口中定义的内容,那么New出来的这个对象其实是这个接口的实现类,所以它并没有类的名字
public class ClazzOuter {
//待实现的接口,在匿名内部类的定义中,这个接口也可以改为抽象类
interface IClazzInner {
String onTest2Inner();
}
public static void main(String[] args) {
//实现接口的方式的匿名内部类方式一
class ClazzInner implements IClazzInner {
@Override
public String onTest2Inner() {
return "这是一个实现了IClazzInner接口的匿名局部类";
}
}
IClazzInner clazzInner1 = new ClazzInner();
System.out.println(clazzInner1.onTest2Inner());
//实现接口的方式的匿名内部类方式二
IClazzInner clazzInner2 = new IClazzInner() {
@Override
public String onTest2Inner() {
return "这是一个实现了IClazzInner接口的匿名类";
}
};
System.out.println(clazzInner2.onTest2Inner());
}
}