什么是内部类?
可以将一个类的定义放在另一个类的定义内部,这就是内部类。内部类可以分为四大类:本地(局部)内部类,实例(成员)内部类,静态内部类,匿名内部类
什么是外部,什么是内部?就是类与类相对位置的关系,例如:
//Outer是外部类,相对于Inner而言
public class Outer {
//Inert是内部类
class Inner {
//...
}
}
为什么要是使用内部类?
(一)实例内部类
//外部类
class Outer {
private int outerVariable = 1;
private int commonVariable = 2;
private static int outerStaticVariable = 3;
//成员方法
public void outerMethod() {
System.out.println("我是外部类的outerMethod方法");
}
//静态方法
public static void outerStaticMethod() {
System.out.println("我是外部类的outerStaticMethod静态方法");
}
//内部类
public class Inner {
private int commonVariable = 20;
//错误写法,因为创建Inner对象还是要依赖于Outer,而static修饰的变量是不依赖于对象的
//private static int st = 10;
//只能定义静态常量
private static final int st = 10;
//构造方法
public Inner() {
}
//成员方法,访问外部类信息(属性、方法)
public void innerShow() {
//当和外部类冲突时,直接引用属性名,是内部类的成员属性
System.out.println("内部的commonVariable:" + commonVariable);
//内部类访问外部属性
System.out.println("outerVariable:" + outerVariable);
//当和外部类属性名重叠时,可通过外部类名.this.属性名
System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
System.out.println("outerStaticVariable:" + outerStaticVariable);
//访问外部类的方法
outerMethod();
outerStaticMethod();
}
//返回对外部类的引用,使用外部类的名字后面紧跟圆点和this
public Outer retOuter() {
return Outer.this;
}
}
//外部类访问内部类信息
public void outerShow() {
Inner inner = new Inner();
inner.innerShow();
}
//在Outer中定义get方法,获得Inner对象,那么使用时,只需outer.getInnerInstance()即可
public Inner getInnerInstance() {
return new Inner();
}
}
public class Test14 {
public static void main(String[] args) {
//外部类对象
Outer outer = new Outer();
//创造内部类对象
Outer.Inner inner = outer.new Inner();
inner.innerShow();
}
}
运行结果
实例内部类(Inner)相当于外部类(Outer)的成员一样
我们知道一个类对应的是一个字节码文件,对于普通的类来说,这个字节码文件名就是类名.class,但对于内部类来说,它是外部类+$+内部类.class这样的形式
如果一个类想要继承一个内部类,需要在这个类的构造方法中提供一个外部类对象,并通过外部类对象调用super方法,否则会报错,至于为什么这么做,我也不知道,奇奇怪怪的语法
class exInner extends Outer.Inner {
public exInner(Outer outer){
outer.super();
}
}
小结:
1.在实例内部类中,不能定义静态的成员变量,只能定义静态成员常量,并且不能定义静态方法
2.内部类也是类,和普通类是一样的,也有继承、重写、多态
3.外部类如果需要访问内部类信息,需要通过 new 外部类对象.
内部类创建一个内部类对象
4.实例内部类中,包含两个this,一个是外部类的,一个是自己的
5.实例内部类可以直接使用外部类的任何信息,如果属性或者方法发生冲突,调用外部类.
this.
属性或者方法
(二)静态内部类
在拥有外部类对象之前是不可能创建内部类对象的,因为内部类对象会暗暗地连接到创建它的外部类对象上。创建内部类对象时,需要一个指向其外部类对象的引用,如果编译器访问不到这个引用就会报错。但是,如果你创建的是静态内部类,那就不需要对外部类对象的引用
//外部类
class Outer {
private int outerVariable = 1;
//外部类定义的属性(重名)
private int commonVariable = 2;
private static int outerStaticVariable = 3;
static {
System.out.println("Outer的静态块被执行了……");
}
//成员方法
public void outerMothod() {
System.out.println("我是外部类的outerMethod方法");
}
//静态方法
public static void outerStaticMethod() {
System.out.println("我是外部类的outerStaticMethod静态方法");
}
//静态内部类
public static class Inner {
//成员信息
private int innerVariable = 10;
private int commonVariable = 20;
static {
System.out.println("Outer.Inner的静态块执行了……");
}
private static int innerStaticVariable = 30;
//成员方法,需要通过内部类对象来调用
public void innerShow() {
System.out.println("innerVariable:" + innerVariable);
System.out.println("内部的commonVariable:" + commonVariable);
System.out.println("outerStaticVariable:"+outerStaticVariable);
System.out.println("外部类的commonVariable:" + new Outer().commonVariable);
System.out.println("外部类的outerVariable:" + new Outer().outerVariable);
outerStaticMethod();
}
//静态方法
public static void innerStaticShow() {
//被调用时会先加载Outer类
outerStaticMethod();
System.out.println("outerStaticVariable"+outerStaticVariable);
}
}
//外部类通过静态内部类的类名直接访问内部类的信息
public static void callInner() {
System.out.println(Inner.innerStaticVariable);
Inner.innerStaticShow();
}
}
public class Test14 {
public static void main(String[] args) {
//访问静态内部类的静态方法,Inner类被加载,此时外部类未被加载,独立存在,不依赖于外部类。
Outer.Inner.innerStaticShow();
//访问静态内部类的成员方法
Outer.Inner inner = new Outer.Inner();
inner.innerShow();
}
}
运行结果
小结:
1.内部可以包含任意的信息。
2.静态内部类的方法只能能访问外部类的static关联的信息,如果想要访问外部类的非静态信息,需要创建外部类对象,才能访问
3.用外部类.
内部类 引用 = new 外部类.
内部类(); 然后利用引用.
成员信息(属性、方法)调用。
4.访问内部类的静态信息,直接外部类.
内部类.
静态信息就可以了。
5.静态内部类可以独立存在,不依赖于外部类。
(三)匿名内部类
//外部类
class Outer {
public void test() {
System.out.println("我是Outer类");
}
}
public class Test14 {
public static void main(String[] args) {
new Outer(){
@Override
public void test() {
System.out.println("我重写了test(),我是匿名内部类");
}
}.test();
}
}
运行结果:
new Outer(){
@Override
public void test() {
System.out.println("我重写了test(),我是匿名内部类");
}
}
这段代码就是一个匿名内部类,它相当于继承了Outer,并重写了test()方法
小结:
1.匿名内部类是没有访问修饰符的。
2.使用匿名内部类时,这个new之后的类首先是要存在的,其次我们要重写new后的类的某个或某些方法。
3.匿名内部类访问方法参数时也有和局部内部类同样的限制。
4.匿名内部类没有构造方法
(四)本地内部类
本地内部类不能有访问说明符,因为它不是外部类的一部分。但是它可以访问当前代码块内的常量,
以及此外部类的所有成员。
public class Outer {
private int outerVariable = 1;
private int commonVariable = 2;
private static int outerStaticVariable = 3;
//成员外部方法
public void outerMethod() {
System.out.println("我是外部类的outerMethod方法");
}
//静态外部方法
public static void outerStaticMethod() {
System.out.println("我是外部类的outerStaticMethod静态方法");
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.outerCreatMethod(100);
}
public void outerCreatMethod(int value) {
class Inner {
private int innerVariable = 10;
private int commonVariable = 20;
//内部类方法
public void innerShow() {
//调用内部信息
System.out.println("innerVariable:" + innerVariable);
//调用外部类的信息
System.out.println("outerVariable:" + outerVariable);
System.out.println("内部的commonVariable:" + commonVariable);
System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
System.out.println("outerStaticVariable:" + outerStaticVariable);
outerMethod();
outerStaticMethod();
}
}
//局部内部类只能在方法内使用
Inner inner = new Inner();
inner.innerShow();
}
}
运行结果:
本地内部类只能在当前方法中使用,实际也用得很少,只做了解即可
小结:
1.类前不能有访问修饰符
2.只能在当前方法内使用
3.无法创造静态信息
4.可以随意的访问外部类的任何信息