Java模拟闭包实现属性封装

本文介绍了一种使用Java模拟JavaScript闭包特性的方法,通过定义Person类并利用lambda表达式来封装属性,实现了属性的完全封装。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看了js的闭包,仔细想了想,感觉java也可以模拟js的闭包特性实现属性封装,不过看似没什么卵用。

下面,首先定义一个Person类,该类中并没有任何属性,我们将属性 pname和page放到一个静态方法中,作为局部变量,对!你没有看错,局部变量

然后用lambda表达式来setget 这些局部变量。

最后将这些lambda表达式(匿名内部类)放入一个map中做为返回值返回。

具体代码如下:

package com.fly.domain;

import java.util.HashMap;
import java.util.Map;

public class Person {

    //静态方法获取Person的操作接口
    public static Map<String, PersonInterface> getPerson() {

        //定义局部变量 pname和page
        String[] pname = new String[1];
        Integer[] page = new Integer[1];

        //定义操作局部变量的接口
        PersonInterface getName = (v) -> {
            return pname[0];
        };
        PersonInterface getAge = (v) -> {
            return page[0];
        };
        PersonInterface setName = (v) -> {
            pname[0] = (String) v;
            return null;
        };
        PersonInterface setAge = (v) -> {
            page[0] = (Integer) v;
            return null;
        };

        //将操作接口放入map
        Map<String, PersonInterface> person = new HashMap<>();
        person.put("setName", setName);
        person.put("setAge", setAge);
        person.put("getName", getName);
        person.put("getAge", getAge);

        //返回接口map
        return person;
    }

    //定义一个函数式接口,用于lambda表达式
    public static interface PersonInterface {
        Object apply(Object value);
    }
}

下面测试下这个四不像的类吧:

 public static void main(String[] args) {

        //做俩Person出来(其实是两个Map,内部封装了操作pname和page的接口)
        Map<String, Person.PersonInterface> p1 = Person.getPerson();
        Map<String, Person.PersonInterface> p2 = Person.getPerson();

        //给属性赋值
        p1.get("setName").apply("老王");
        p1.get("setAge").apply(66);
        p2.get("setName").apply("老李");
        p2.get("setAge").apply(55);

        //输出
       Object name1 = p1.get("getName").apply(null);
        Object age1 = p1.get("getAge").apply(null);
        System.out.println("p1.name = " + name1 + ", and p1.age = " + age1);

        Object name2 = p2.get("getName").apply(null);
        Object age2 = p2.get("getAge").apply(null);
        System.out.println("p2.name = " + name2 + ", and p2.age = " + age2);
    }

输出结果:

p1.name = 老王, and p1.age = 66
p2.name = 老李, and p2.age = 55

目前看来,这种方法确实可以封装属性,(值得注意的是:封装的属性我用了数组来实现,因为lambda表达式内部无法修改外部变量,我只能采用间接的方法来实现)但是不知道为什么匿名内部类会把一个方法内部的局部变量给带到外边来,关键是:这是否会影响垃圾回收

不过这种方法的确把属性封装的死死的,似乎暴力反射也取不出来。底层原理还在研究中。。。


更新,关于原理初步探讨

废话不多说,上图:
这里写图片描述

可以看到,所有的Lambda表达式都被编译成了一个
Person$lambda的内部类(其中Person是该lambda表达式所在的类),其内部封装了一个属性:**arg$1**,看来,这个属性就是lambda表达式携带的局部变量!!!

从图中可以看出,“老王”,“66”这些属性都被封装到了lambda表达式内部,作为成员属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值