概念
内部类,顾名思义就是定义在类内部的类。
特别之处:外部类可以访问内部类的所有元素【包括私有元素】
优点
- 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据
- 内部类不为同一包下的其他类所见,具有很好的封装性
- 内部类有效实现类“多重继承”,优化java单继承的缺陷
- 匿名内部类可以很方便的定义回调
应用场景
- 适当使用内部类,使得代码更加灵活富有扩展性
- 当某个类除了它的外部类,不在被其他的类所使用
分类
内部类可以分为:
- 静态内部类:定义在类内部的静态类
- 成员内部类:定义在类内部的非静态类
- 匿名内部类:定义在类内部没有名字的内部类【日常开发中使用较多】
- 局部内部类:定义在类内部的方法中的内部类
静态内部类
- 创建方式: Outer.StaticInner = new Outer.StaticInner();
- 变量:静态内部类中可以定义静态变量与实例变量
- 方法:静态内部类中可以定义静态方法与实例方法
- 访问外部类:静态内部类的只能访问外部类的静态元素【静态变量与静态方法】
/**
* 静态内部类
* 创建方式: Outer.StaticInner = new Outer.StaticInner();
* 变量:静态内部类中可以定义静态变量与实例变量
* 方法:静态内部类中可以定义静态方法与实例方法
* 访问外部类:静态内部类的只能访问外部类的静态变量
*/
public class Outer {
private static int i=1;
private int j=1;
public static void go(){
System.out.println("我是外部类的go方法,我直接访问了内部类的私有静态变量 age"+
StaticInner.age);
}
static class StaticInner{
private static int age = 20;
private String name="zhangsan";
public static void run(){
System.out.println("直接访问外部类的私有静态成员:"+i);
Outer.go(); //访问静态方法
}
public void hello(){
System.out.println("直接访问外部类的私有静态成员:"+i);
go(); //访问静态方法
}
}
}
测试
public class Test {
public static void main(String[] args) {
// 静态内部类测试
Outer.StaticInner staticInner =new Outer.StaticInner();
staticInner.run();
staticInner.hello();
}
}
结果
成员内部类
- 创建方式: 外部类名.内部类名=nwe 外部类实例.内部类名();
- 变量:成员内部类中只能定义实例变量,不能定义静态变量
- 方法:成员内部类中只能定义实例方法,不能定义静态方法
- 访问外部类:可以直接访问外部类的所有元素【静态元素,实例元素】
/**
* 成员内部类
* 创建方式: 外部类名.内部类名=nwe 外部类实例.内部类名();
* 变量:成员内部类中只能定义实例变量,不能定义静态变量
* 方法:成员内部类中只能定义实例方法,不能定义静态方法
* 访问外部类:可以直接访问外部类的所有元素【静态元素,实例元素】
*/
public class Outer1 {
private static int i=1;
private int j=1;
public static void go(){
System.out.println("我是外部类的静态方法");
}
public void run(){
System.out.println("我是外部类的实例方法");
}
class Inner{
private int age=20;
public void hello(){
System.out.println("访问外部类的静态变量:"+i);
System.out.println("访问外部类的实例变量:"+j);
go();
run();
}
}
}
测试:
public class Test {
public static void main(String[] args) {
// 成员内部类测试
Outer1 outer1 = new Outer1();
Outer1.Inner inner = outer1.new Inner();
inner.hello();
}
}
结果:
匿名内部类
/**
* 匿名内部类
* 须知:匿名内部类必须继承一个抽象类或者实现一个接口
* 变量:匿名内部类只能定义实例变量,不能定义静态变量
* 方法:匿名内部类只能定义实例方法,不能定义静态方法
*/
public class Outer2 {
public void test(){
new Animal(){
@Override
public void run() {
System.out.println("我是匿名内部类");
}
}.run();
}
}
//定义一个抽象类用于匿名内部类继承
abstract class Animal{
public abstract void run();
}
测试:
public static void main(String[] args) {
Outer2 outer2 = new Outer2();
outer2.test();
}
结果:
局部内部类
- 创建方式:在对应方法内 new 内部类();
- 定义在实例方法中的内部类可以访问外部类的所有变量和方法
- 定义在静态方法中的内部类只能访问外部内的静态变量和方法
/**
* 局部内部类
* 创建方式:在对应方法内 new 内部类();
* 定义在实例方法中的内部类可以访问外部类的所有变量和方法
* 定义在静态方法中的内部类只能访问外部内的静态变量和方法
*/
public class Outer3 {
private int age=20;
private static String name="zhangsan";
public void find(){
System.out.println("我是外部类的实例方法");
}
public static void found(){
System.out.println("我是外部类的静态方法");
}
public void test(){
// 定义在实例方法中的内部类
class Inner{
private String address="岳阳";
public void run(){
System.out.println("我是局部内部类的run方法");
System.out.println("访问外部内的实例变量"+age);
System.out.println("访问外部内的静态变量"+name);
find();
Outer3.found();
}
}
Inner inner = new Inner();
inner.run();
}
public static void testStatic(){
// 定义在静态方法中的内部类
class InnerStatic{
private String address="岳阳";
public void run(){
System.out.println("我是局部内部类的run方法");
// System.out.println("访问外部内的实例变量"+age); 不能访问外部类的实例变量
System.out.println("访问外部内的静态变量"+name);
// find(); 不能访问外部类的实例方法
Outer3.found();
}
}
InnerStatic inner = new InnerStatic();
inner.run();
}
}
测试
public static void main(String[] args) {
Outer3 outer3 = new Outer3();
outer3.test();
Outer3.testStatic();
}
结果
总结【个人理解】
- 静态内部类是所属于类的范围的,所以可以定义静态元素【静态变量以及静态方法】,其他非静态的内部类是所属于对象的,所以不能定义静态元素,只能定义实例变量与实例方法。
- 静态的可以访问父类静态的,因为类加载的时候实例还没被创建
- 实例的既可以访问父类静态的,也可以访问父类实例的,因为创建实例一定是在类加载后,也就是静态元素已经全部加载完成后,所以可以访问静态元素。