【内部类】JAVA 中的四大内部类【下】

在上一篇博文 【内部类】JAVA 中的四大内部类【上】 中,有介绍到内部类、成员内部类,只说了四大内部类中的其中一个。接下来,此文就来介绍剩下的三种内部类:局部内部类、静态内部类、匿名内部类

2.2 局部内部类

什么是局部内部类?

局部内部类相当于一个局部变量,在一个方法中/局部代码块中定义一个类,称为局部内部类(不能被 public、private 修饰)

那局部内部类和成员内部类的区别就显而易见了 ------ 它们所处的位置不同。

定义、构建局部内部类
public class OuterClass {

    public void getInnerClass() {

        // 定义局部内部类(不能被 public、private 修饰)
        class InnerClass {
            public InnerClass() {

            }

            public InnerClass getInnerClass() {
                return this;
            }
        }
		
		// 只能在局部内部类作用域中 new 一个局部内部类对象
		InnerClass innerClass = new InnerClass();
    }
}

当然,也可以在 if 代码块中定义局部内部类:

public class OuterClass {

    public void getInnerClass() {

        // 定义局部内部类(不能被 public、private 修饰)
        if (true) {
            class InnerClassTwo {
                public InnerClassTwo() {

                }

                public InnerClassTwo getInnerClass() {
                    return this;
                }
            }
        }
    }
}

全部代码:

public class OuterClass {

    public void getInnerClass() {

        // 定义局部内部类(不能被 public、private 修饰)
        class InnerClass {
            public InnerClass() {
                System.out.println("外部类对象引用:" + OuterClass.this);
            }

            public InnerClass getInnerClass() {
                return this;
            }
        }

        InnerClass innerClass = new InnerClass();
        InnerClass instance = innerClass.getInnerClass();
        System.out.println("内部类对象的引用:" + instance);

        boolean flag = true;
        if (flag) {
            class InnerClassTwo {
                public InnerClassTwo() {
                    System.out.println("外部类对象引用:" + OuterClass.this);
                }

                public InnerClassTwo getInnerClass() {
                    return this;
                }
            }

            InnerClassTwo innerClassTwo = new InnerClassTwo();
            InnerClassTwo instanceTwo = innerClassTwo.getInnerClass();
            System.out.println("内部类对象的引用:" + instanceTwo);

            flag = false;
        }

    }

    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        outerClass.getInnerClass();
    }
}

运行代码知:这两个局部内部类的外部类引用是一样的,但各自的内部类对象的引用是不一样的


局部内部类与 final 关键字

局部内部类不能更改局部内部类之外的局部变量的值,否则,会在 IDE 会报错,报错提示为:Variable ‘num’ is accessed from within inner class, needs to be final or effectively final。如:

public class OuterClass {

    public void getInnerClass() {
        int num = 0;

        class InnerClass {
            public InnerClass() {}

            public InnerClass getInnerClass() {
            	// 修改局部内部类之外的局部变量,会报错
                num++;
                return this;
            }
        }
	}
}

由报错提示知:在局部内部类中要使用它之外的局部变量,只能是 final 常量。

那么,为什么会有这个限制呢?

因为局部变量和局部内部类的生命周期不同,所以,编译器就统一要求,如果局部内部类使用了它之外的局部变量,此时,编译器就按 fianl 常量处理。

例如:

先定义一个类,可供局部内部类继承。

public abstract class AbstractTest {
    public abstract void test();
}
public class OuterClass {

    public AbstractTest getLocalClass() {
        // 局部变量
        int num = 10;
		
		// 局部内部类
        class LocalClass extends AbstractTest{

            @Override
            public void test() {
                num++;
            }
        }

        AbstractTest instance = new LocalClass();
        return instance;
    }


    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        AbstractTest localClass = outerClass.getLocalClass();
        localClass.test();
    }
}

如果没有那个限制,这块代码将会这样运行:

1. 创建了一个外部类对象 OuterClass;
2. 外部对象调用一个成员方法 outerClass.getLocalClass()
3. 在成员方法中,会在堆中创建内部类对象 LocalClass;
4. 然后,内部类对象将会调用它自己的成员方法 localClass.test()。在这个方法中,它会使用一个外部类的方法中的局部变量 num 。但这就有一个问题了:这个外部类方法已经执行完毕了,那么,这个方法中的所有的局部变量的生命周期都应该结束,num 也应该被回收。那这个内部类对象按理就无法访问这个 num 了。所以,为了避免上述问题,编译器进行了上述的处理。


2.3 静态内部类

什么是静态内部类?

使用关键字 static 修饰的成员内部类

定义、构建静态内部类

静态内部类不依赖于外部类对象的

public class OuterClass {

    private String name;
    private static int type = 1;

    public static class InnerClass {

        public InnerClass() {
            // 静态内部类不能访问外部类的费静态成员
            System.out.println(type);
        }
    }

    public static void main(String[] args) {
        // 构建静态内部类
        InnerClass innerClass = new OuterClass.InnerClass();
    }
}

静态内部类对象构建规则:new 外部类.静态内部类名();

应用场景

当一个类是另外一个类(外部类)的附属类,它不依赖外部类对象而存在,并且它需要单独在外部类之外的类去使用,此时,就可以定义为静态内部类。

如:

public class User {
    private int id;
    private String name;
    private int age;
}
// 用户查询类
public class UserQuery {

    // 查询用户列表  传入查询条件
    public List<User> listUsers(QueryParam queryParam) {
        return new ArrayList<>();
    }

    // 用户查询条件类  存放用户查询条件(可以根据 Id、name 查询)
    public static class QueryParam {
        private int id;
        private String name;
    }
}

有一个用户信息类 User,现在有一个 UserQuery 类来查询用户信息的,如果根据条件查询的话,还需要给查询方法传入参数。这里将传入的参数封装在了一个内部类类中。

考虑到用户查询条件类 QueryParam 可能不仅用在 UserQuery 类中,还可能用在其它类中,那么,就可以将 QueryParam 类定义为静态内部类

2.4 匿名内部类

什么是匿名内部类?

匿名内部类是一种特殊的局部内部类,它没有名字

定义匿名内部类的规则:

new 父类/接口() {
	// TODO
}

略…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值