内部类: 定义在内部的类,不一定非得是定义在类的内部, 可以分为4种类型。
第一: 静态内部类(定义在类中)
- 静态的内部类与其外部类是编译成 两个.class文件 的,注意的是外部类是不可以定义为静态的。
为什么外部的类不可以定义为静态的
解释:静态类是没有实际意义的,而且运行初始化还要占用大量内存,而且假如有静态类,不能被重写,不能创建对象,没啥实际意义。
备注:其实只需要定义静态变量、静态方法、静态内部类等完全可以满足需求的。 只能访问外部类的静态成员变量与静态方法,
为什么静态的只能访问静态的?
解释: 静态的变量或者方法是在类被加载的时候被构造的,而非静态的则是在生成对象的时候创建的,当在静态里面调用非静态的时候,可能非静态的还没有没创建,会发生非法访问。所以静态的只能访问静态的。生成静态内部类对象的方式为:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
// B是A的静态内部类
public class A{
public static class B{
}
}
第二: 成员内部类(内部的非静态的类)(定义在类中)
1. 可以访问外部类的静态与非静态的方法与成员变量。
2. 生成成员内部类对象的方式为: (和静态内部类是不同的)
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
为啥这样写:
因为是非静态的类,可以类比成非静态的一个成员方法,必须通过一个实例化的对象来调用,而静态的内部类可以直接通过类名来调用,所以静态的内部类可以直接通过 外部类名.内部类名 调用 ; 而成员内部类必须通过 new 外部类().内部类() 调用。 通过外部类的一个对象来调用内部类
- 也是生成两个.class 文件
- 若想在局部内部类中访问外部类的成员变量,语法 OuterClass.this.a;
// B是A的成员内部类, 与静态内部类的区别是有无static关键字
public class A{
private int a;
public class B{
private int a;
public void set(){
a= A.this.a; // 内部类中 使用 OuterClass.this.a; 访问外部的成员
}
}
}
第三: 局部内部类(定义在方法中的)用的比较少
类似于一个局部变量,不能定义成 public private,protected 访问修饰符的变量, 原因是局部变量前面不能带有访问修饰符,访问修饰符只能修饰成员变量。
我们是没有办法在外部类中使用的,只能在其所定义的成员方法内使用。
局部内部类中是不能访问外部类的成员或者方法的,只能访问方法中声明的 final类型的变量
第四: 匿名内部类 (Anonymous inner class )
内部类,但是没有名字 没有名字就意味着没有构造方法, 是一种特殊的局部内部类。
匿名内部类会隐式地继承一个父类或实现一个接口。最重要的特点
// 一个测试类
public class AnonymousInnerClass {
@SuppressWarnings("deprecation")
public String getTime(Date date){
return date.toLocaleString();
}
public static void main(String[] args) {
AnonymousInnerClass annoymousClass = new AnonymousInnerClass();
// 传给 getTime方法中的对象是一个Date类的对象
String str = annoymousClass.getTime(new Date());
// 在这里new Date(){ } 就是定义了一个内部类,
// 这个内部类继承了 Date 这个类,但是没有重写 Date类中的任何方法
// 然后传给 getTime方法中的对象是一个继承了Date类的子类的对象
// 可以看生成的.class 文件,会多了一个,而且内部类因为没有名字,所以就 $num 以数字的方式表示了内部类
String strInner = annoymousClass.getTime(new Date(){ } );
System.out.println(str);
System.out.println(strInner);
}
}
通常也是用在方法内的,一般作为参数传递进去
Swing 使用匿名内部类实现了监听接口,为一个事件添加一个监听器,适用于 该内部类实现的功能只会被使用一次,或者被一个对象使用的情况,不必要再为其单独的写一个类。
public static void main (){
JFrame frame = new JFrame("JFrame");
JButton button = new JButton("click me");
// 使用内部匿名类的形式为button添加了一个监听器,
// 有人可能有疑问ActionListener不是一个接口吗?怎么还可以new 出来一个对象,这是内部匿名类的机制,这个地方创建的对象是一个实现了ActionListener接口的具体的实例的对象,并不是一个ActionListener接口对象。
button.addActionListener (new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("welcome");
}
})
}