内部类是指在一个外部类的内部再定义一个类。

内部类分为: 成员内部类、局部内部类、静态嵌套类、匿名内部类 。

1、成员内部类

class Outer {
	private int i = 11;

	class Inner {
		private int i = 22;

		public void show() {
			int i = 33;
			System.out.println("内部类局部变量:" + i);
			System.out.println("内部类成员变量:" + this.i);
			System.out.println("外部类成员变量:" + Outer.this.i);
		}
	}
}
public class TestInner {
	public static void main(String[] args) {
		Outer outer = new Outer();
		Outer.Inner in = outer.new Inner();
		in.show();
	}
}

运行结果:


内部类局部变量:33

内部类成员变量:22

外部类成员变量:11

成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的

在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问。


内部类可以用private、protected、public、default(默认)修饰。

如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。

外部类只能用public、default(默认)修饰。

成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的。

2、局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类。

它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内

(1)定义在方法里的内部类:

class Outer{
	private int i=11;
	public void outShow(final int i){
		class Inner{
			public void inShow() {
				System.out.println("外部类outShow()方法传入参数:"+i);
				System.out.println("外部类成员变量"+Outer.this.i);
			}
		}
		new Inner().inShow();
	}
}
public class TestInner {
	public static void main(String[] args) {
		Outer out=new Outer();
		out.outShow(22);
	}
}

运行结果:


外部类outShow()方法传入参数:22

外部类成员变量11

将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法。如果此时需要往外部类的方法中传入参数,如out.outShow(22);,那么外部类的方法形参必须使用final定义

(2)定义在作用域内的内部类:

class Outer {
	private int i = 11;
	public void outShow(final boolean i) {
		if (i) {
			class Inner {
				public void inShow() {
					System.out.println("外部类outShow()方法传入参数:" + i);
					System.out.println("外部类成员变量" + Outer.this.i);
				}
			}
			new Inner().inShow();
		}		
	}
}
public class TestInner {
	public static void main(String[] args) {
		Outer out = new Outer();
		out.outShow(true);
	}
}

运行结果:

外部类outShow()方法传入参数:true

外部类成员变量11

3、静态内部类

又叫静态局部类、嵌套内部类、静态嵌套类,就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说可以直接引用Outer.Inner,既不需要创建外部类,也不需要创建内部类。

class Outer{
	private static int i=11;//静态内部类只能访问外部类的静态成员变量,具有局限性。
	static class Inner{
		public void inShow() {
			System.out.println("内部类普通方法访问外部类静态成员变量:"+i);
		}
		public static void sinShow() {
			System.out.println("内部类静态方法访问外部类静态变量:"+i);
		}
	}
}
public class TestInner {
	public static void main(String[] args) {
		Outer.Inner in = new Outer.Inner();
		in.inShow();
		Outer.Inner.sinShow();//访问静态内部类静态方法不需要创建对象
	}
}

4、匿名内部类

匿名内部类也就是没有名字的内部类。

程序中有些类只使用一次,就可以使用匿名内部类简化代码书写,省略一个类的书写(如下例,省略Child类书写)。

使用匿名内部类的前提条件:必须继承一个父类或实现一个接口

(1)不使用匿名内部类

abstract class Person {
    public abstract void eat();
} 
class Child extends Person {
    public void eat() {
        System.out.println("Eat Something");
    }
}
public class TestInner {
	 public static void main(String[] args) {
	        Person p = new Child();
	        p.eat();
	    }
}

运行结果:


Eat Something

(2)继承抽象类的匿名内部类

abstract class Person {
    public abstract void eat();
}
public class TestInner {
	 public static void main(String[] args) {
	        Person p = new Person() {
				public void eat() {
					System.out.println("Eat Something");
				}
			};
	        p.eat();
	    }
}

运行结果与上例相同,省略了Child类的书写。

(3)实现接口的匿名内部类

interface Person {
    public abstract void eat();
}
public class TestInner {
	 public static void main(String[] args) {
	        Person p = new Person() {
				public void eat() {
					System.out.println("Eat Something");
				}
			};
	        p.eat();
	    }
}

运行结果与上例相同,同样省略了Child类的书写。