什么是内部类
将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类
分类
- 成员内部类
- 局部内部类
- 匿名内部类
- 静态内部类
用法
成员内部类:
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。
- 没有使用static修饰的内部类
- 在成员内部类中不允许出现静态变量和静态方法的声明,static只能用在静态常量的声明上
- 成员内部类中可以访问外部类中所有的成员(变量,方法),包含私有成员,如果在内部类中定义有和外部类同名的实例变量,访问:OutterClass.this.outerMember;
- 成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
public class Outter {
private int a = 10;
private static int b = 20;
public int c = 30;
public Outter(){
}
class Inner{
private int c = 5;
private static final int d = 50;//static只能用在静态常量的声明上
public Inner(){
}
public void getOutter(){
System.out.println(a); //访问外部类的private成员
System.out.println(b); //访问外部类的静态成员
System.out.println(Outter.this.c); //相同变量名时访问外部类的成员
}
}
}
//测试类
public class TestClass {
public static void main(String[] args) {
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner(); //通过Outter对象来创建
inner.getOutter();
}
}
局部内部类:
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
- 没有使用static修饰的内部类
- 局部内部类是所有内部类中最少使用的一种形式
- 局部内部类可以访问的外部类的成员根据所在方法体不同。
在静态方法中:
可以访问外部类中所有静态成员,包含私有
在实例方法中:
可以访问外部类中所有的成员,包含私有。
局部内部类可以访问所在方法中定义的局部变量,但是要求局部变量必须使用final修饰。
public class Outter {
private int a = 10;
private static int b = 20;
public int c = 30;
public Outter(){
}
public void getInner(){
final int f = 2;
class Inner{
private int c = 5;
private static final int d = 50;//static只能用在静态常量的声明上
public Inner(){
}
public void getOutter(){
System.out.println(a); //外部类的private成员
System.out.println(b); //外部类的静态成员
System.out.println(Outter.this.c); //相同变量名时访问外部类的成员
System.out.println(f); //访问方法中的变量必须使用final修饰
}
}
new Inner().getOutter();
}
}
//测试类
public class TestClass {
public static void main(String[] args) {
Outter outter = new Outter();
outter.getInner();
}
}
匿名内部类:
匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。主要是针对那些不能直接创建对象的抽象类和接口而来的
- 没有名字的局部内部类。
- 没有class,interface,implements,extends关键字
- 没有构造器。
- 一般隐式的继承某一个父类或者实现某一个接口
//接口
interface Pen {
public void write();
}
class Person {
public void user(Pen pen) {
pen.write();
}
}
//测试类
public class Test {
public static void main(String args[]) {
Person person= new Person();
person.user(new Pen() {
@Override
public void write() {
System.out.println("写字");
}
});
}
}
//抽象类
abstract class Animal{
public abstract void bark();
}
class Dog extends Animal{
public void bark() {
System.out.println("汪汪汪");
}
}
//测试类
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.bark();
//相当于定义了该抽象类的一个子类对象,并重写了抽象类中所有的抽象方法
Animal an=new Animal(){
public void bark(){
System.out.println("汪汪汪");
}
};
an.bark();
}
}
//android中button按钮的事件监听
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
静态内部类:
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,并且它不能使用外部类的非static成员变量或者方法。如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象
- 声明在类内部,方法体外,并且使用static修饰的内部类
- 脱离外部类的实例独立创建
在外部类的外部构建内部类的实例
new Outter.Inner();
在外部类的内部构建内部类的实例
new Inner(); - 静态内部类可以直接访问外部类中所有的静态成员,包含私有
public class Outter {
private int a = 10;
private static int b = 20;
public int c = 30;
public Outter(){
}
public static void getInner(){
new Inner();//内部调用直接new
}
public void test(){
System.out.println("Outter test ...");
}
static class Inner{
private int c = 5;
private static final int d = 50;
public Inner(){
}
public void getOutter(){
System.out.println(b); //只能访问外部类的静态成员
new Outter().test();
getInner();
}
}
}
//测试类
public class TestClass {
public static void main(String[] args) {
//外部调用
Outter.Inner inner = new Outter.Inner();
inner.getOutter();
}
}
上面介绍了内部类的四种类型,那么问题来了
静态内部类和非静态内部类的区别
静态内部类可以有静态成员(方法和属性),而非静态内部类则不能有静态成员(方法或属性)
静态内部类只能够访问外部类的静态成员和静态方法,而非静态内部类则可以访问外部类的所有成员(方法和属性)
实例化方式不同
非静态内部类:
OutClass.InnerClass innerClass = new OutClass().new InnerClass();
静态内部类:
OutClass,InnerClass innerClass = new OutClass.InnerClass();
静态内部类随着外部类的加载而加载,而不是随着外部类对象的产生而产生