1 Star 3 Fork 0

老诗人 / jl-tools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

介绍

包含开发编码能用到的一些封装工具,提升开发效率以及代码优雅性。 主要功能含:

  1. spring动态管理bean工具类。
  2. 增强Map。
  3. 增加List。
  4. 线程池工具类。
  5. 抽象数据判断,让任意数据类型基本判断只需使用一个方法即可。
  6. 元祖。
  7. 注解版aes或rsa自动加解密。
  8. lambda引用解析工具,可以根据lambda引用获取类class、方法名、属性名,避免硬编码是开发首要的第一步。
  9. spring接口代理封装,抽象共性,极大减少代码量。
  10. 注解版拦截器。
  11. 注解版过滤器。
  12. 简化版的@validated,一个注解实现99%项目所需的校验功能。
  13. 纯反射实现bean的拷贝,性能是BeanUtils的10-20倍,也解决BeanCopier无法读取有返回值的set方法而导致无法使用@Accessors编程,还实现了常用数据类型的转换。
  14. io工具类。
  15. 注解版项目启动完成后执行任务。

安装依赖

<dependency>
    <groupId>io.gitee.laoshirenggo</groupId>
    <artifactId>tools</artifactId>
    <version>1.6</version>
</dependency>

增强Map

JMap继承Map,JHashMap继承HashMap,JConcurrentHashMap继承ConcurrentHashMap,只做增强,封装了常用方法,让代码更优雅。

支持功能
  1. 常用数据类型的get方法。
  2. lambda方法引用的key。
  3. 链式调用。
  4. 转换为list。
  5. 转换为实体。
  6. 有HashMap以及ConcurrentHashMap两种实现。
//创建HashMap
JMap<String, Object> hashMap = new JHashMap<>();
//创建ConcurrentHashMap
JMap<String, Object> concurrentHashMap = new JConcurrentHashMap<>();
常用数据类型的get方法
  1. getString
  2. getInt
  3. getLong
  4. getDouble
  5. getBigDecimal
  6. getBoolean
  7. getLocalDateTime
  8. getTimestamp
jmap.getString("demo");
lambda方法引用的key
jmap.get(Demo::getName);
链式调用
JMap<String, Object> jmap = new JHashMap<String, Object>()
                .set(Demo::getName, "张三")
                .set("age", 18);
String name = jmap.getString("name");  
Integer age = jmap.getInteger(Demo::getAge);     
转换为list
//key转换为list
JList<String> key = jmap.toList().key();
//value转换为list
JList<Object> value = jmap.toList().value();
转换为实体
Demo demo = jmap.toBean(Demo.class);

增强List

JList继承List,增强封装了常用方法的lambda操作,让代码更优雅。

支持功能
  1. 链式调用。
  2. 转换为map。
  3. 数据去重。
  4. 数据排序。
  5. 获取某个属性集合。
  6. 集合查询。
  7. 随机洗牌。
  8. 根据值获取下标。
  9. 按指定长度切割为N个集合
  10. 求差集。
  11. 求交集。
  12. 有JArrayList一种实现。
JList<Demo> jlist = new JArrayList<>();
链式调用
JList<Demo> jlist = new JArrayList<Demo>()
        .set(new Demo().setAge(18).setName("张三"))
        .set(new Demo().setAge(20).setName("李四"));
转换为map
//age属性为key转换为map,重复分组
JMap<Integer, List<Demo>> group = jlist.toMap(Demo::getAge).group();
//age属性为key转换为map,重复覆盖
JMap<Integer, Demo> cover = jlist.toMap(Demo::getAge).cover();
数据去重
//根据age字段去重
JList<Demo> comparing = jlist.comparing(Demo::getAge);
数据排序
//根据age字段倒序
JList<Demo> desc = jlist.desc(Demo::getAge);
获取某个属性集合
//获取name属性集合
JList<String> property = jlist.getProperty(Demo::getName);
集合查询

条件表达式支持:eq,lt,gt,le,ge,ne,like,in,notIn,isNull,isNotNull。
查询结果支持:list,object。

//查询age>=18 && name=张三 的数据 返回集合
JList<Demo> zhangsan = jlist.filter()
        .ge(Demo::getAge, 18)
        .eq(Demo::getName, "张三")
        .list();

//查询name=李四 的数据 返回对象
Demo lisi = jlist.filter()
        .eq(Demo::getName, "李四")
        .object();
随机洗牌
JList<Demo> shuffle = jlist.shuffle();
根据值获取下标
int index = list.getIndex(new Demo().setAge(18).setName("张三"));
按指定长度切割为N个集合
//按长度1切割
JList<JList<Demo>> partition = jlist.partition(1);
求差集、交集
JList<Demo> jlist1 = new JArrayList<Demo>()
        .set(new Demo().setAge(18).setName("张三"))
        .set(new Demo().setAge(20).setName("李四"));

JList<Demo> list2 = new JArrayList<Demo>()
        .set(new Demo().setAge(18).setName("张三"));
//差集
JList<Demo> diff = jlist1.diff(list2);
//交集
JList<Demo> section = jlist1.section(list2);

线程池工具

更优雅的使用线程池,支持如下:

  1. 链式创建线程池。
  2. 手动执行线程池。

创建线程池:

public ThreadPoolTaskExecutor test() {
    return JThreadPool.newPoll()
            .coreSize(10)
            .maxSize(100)
            .keepAlive(60)
            .queueSize(200)
            .name("test")
            .rejected(new ThreadPoolExecutor.CallerRunsPolicy())
            .builder();
}

手动执行线程池1:

public void demo() {
    //参数1为:线程池名称,参数2为:任务数
    JThreadPool.excPoll("test", 3)
            .execute(() -> System.out.println(1))
            .execute(() -> System.out.println(2))
            .execute(() -> System.out.println(3))
            //阻塞等待
            .await();
    System.out.println("执行完毕~");
}

手动执行线程池2:

public void demo() {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    //参数1为:线程池名称,参数2为:任务数
    JThreadPool.Execute test = JThreadPool.excPoll("test", list.size());
    for (Integer integer : list) {
        test.execute(() -> System.out.println(integer));
    }
    //阻塞等待,最多等5秒
    test.await(5);
    System.out.println("执行完毕~");
}

抽象判断

数据判断的封装,让任意数据类型基本判断只需使用JEmpty.check()这一个方法即可,判断数据变为无脑,支持功能如下:

  1. 任意数据类型判空,注:集合长度=0也算空。
  2. stirng字符 最小长度、最大长度、正则。
  3. 任意数值数据类型 最小值、最大值。
Object obj = null;
String str = "";
BigDecimal number = new BigDecimal(0);
//任意数据类型判空
boolean check = JEmpty.check(obj);
//字符串 最小长度=1 最大长度=10
boolean check2 = JEmpty.check(str, 1, 10);
//字符串 正则匹配
boolean check3 = JEmpty.check(str, "[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)+");
//数值 最小=1 最大=10
boolean check4 = JEmpty.check(number, 1, 10);

元祖

顾名思义就是一组数据,当有多个值且数据类型不同时,使用Map并不能准确的表达值的数据类型,元祖就是为了解决这一问题,一共提供了五维元祖,足够满足大多数需求:

  1. JTuple.Tuple2 二维
  2. JTuple.Tuple3 三维
  3. JTuple.Tuple4 四维
  4. JTuple.Tuple5 五维
//二维元祖,同时放入两种数据类型
JTuple.Tuple2<Integer, String> tuple2 = new JTuple.Tuple2<>(200, "操作成功");
Integer v21 = tuple2.getV1();
String v22 = tuple2.getV2();

注解版aes或rsa自动加解密

加解密

入参自动用aes或rsa私钥解密或返参自动用aes或rsa私钥加密,开发不用做任何加解密操作。
注:启动类上需加上@JEnableSecurity,解密入参方法必须有@RequestBody修饰,加密返参必须为json方式,yml需配置aes密钥或rsa私钥公钥。

  1. @JDecode 解密注解
  2. @JEncode 加密注解
#aes对称
encrypt:
  #是否开启加解密 默认true
  open: true
  #是否将加解密日志输出到控制台 默认false
  showLog: false
  aes:
    #获取密钥可使用类 JAES
    key: GLfx0TH5zhQpnHQnNtrW1w==
#rsa非对称
encrypt:
  #是否开启加解密 默认true
  open: true
  #是否将加解密日志输出到控制台 默认false
  showLog: false
  rsa:
    #获取密钥可使用类 JRSA
    publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv370hnpEizK5IUtTxCQVFsEPz2ZFuys4x6zR/2mpS/MooLecSyqsiF8kLUs+ZLqnZrtTRzuMZ5TowP6QeYqsWiAI9tv7x/Pahxi7BEYx/CQx3T7RZRZsnEuprxbmyCkW5WWjrF7NitMSGMSq8fi8DANUeV0aLV8lVz4b3LhCPqwIDAQAB
    privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOz+7RPUvKUGfWnsWN+p6N27uzkLOuQyAiaMhxVN+IpMR6A+BHzGPSM+je/xLdoJLlaqoZXLhmtyH9EjQlIOcrPlP933OuTGwNDa9rXxjRI9r1nsfhorvVxmWk8Lq2EEP9pSsj4c83ilcoYIMB4dzPf/XN2DEhozNbth+sPZfIE/AgMBAAECgYBbqtr+camp1xHJV66kjG7S3Rs0nEBiJWmpiW9ycR8yNwD5XSOVM4RQTpDN/yZyEF0JDqTDcN6ETrc5yH6NiKMabXHtn4OD7Uciu46c3VOAAT8x3KAWqldMh0XwPWmepu9B1ajtWzEuytFG/aTscWrBd2zf3EBStS7ctLpLZmqmOQJBAP1EA6a3q+Jl2uoQlZSpmqQlfAPtn2gYHLpnbY4mev6TdbHnq0id4dZ5zQIASQgzGDuaG3lyzNWg063+H+nCaqsCQQDvjfHKTirqxH7OViu2+ms9ufJ4zI5AQfTcywE1MP7Hg861gb1BEzqGDlOUkEwbo2YMrBfG6AP7IXRJGU9pG0O9AkBxhshgNhrNTDz6CN8UGYahJ9BUbnKzFYPjJrOcMbGWZgEu8xr7XRI7srNrvzb9fvHQ3b6NDSG2bPYWG0Cw5x4rAkEA0rFMjTuNAalLQl2F20yLD+JBAcAgCSI5pAwkhs0N+RrTrs5qTxcDbS6iklMLrW9cbR7bVsVv4uu8pCJPtskVHQJBAIg0NHL72U8fbRfh2Oo4hYMk2NP1KcH/LscehaNrrIOF71dX5aOYwalX2Q0rEBvawlJptv33xbDP+M8lTB+ecHM=

控制层按需增加@JDecode或@JEncode

//@JEncode
@JDecode
@GetMapping("test")
public Map<String, Object> test(Map<String, Object> map) {
    System.out.println(map);
    return map;
}

启动类加@JEnableSecurity

@JEnableSecurity
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
aes和rsa工具类

提供工具类,方便生成密钥以及加解密调试。
aes例子:

//获取密钥
String aesKey = JAES.getKey();
//加密
String encode = JAES.encode("{\"name\": \"张三\"}", aesKey);
//解密
String decode = JAES.decode(encode, aesKey);

rsa例子:

//获取密钥对
Map<String, String> rsaMap = JRSA.getKey();
//私钥
String privateKey = rsaMap.get("privateKey");
//公钥
String publicKey = rsaMap.get("publicKey");
//公钥加密
String publicEncode = JRSA.publicEncode("{\"name\": \"张三\"}", publicKey);
//公钥解密
String publicDecode = JRSA.publicDecode(publicEncode, publicKey);
//私钥加密
String privateEncode = JRSA.privateEncode("{\"name\": \"张三\"}", privateKey);
//私钥解密
String privateDecode = JRSA.privateDecode(privateEncode, privateKey);

递归生成子级树

根据顶级对象递归获取子级树。
方法:JBean.tree(最顶层父级对象, 全部数据集合, 父级关联子级属性名, 子级关联父级属性名, 存放子级集合属性名)
例子:

public static void main(String[] args) {
        //生成测试数据
        List<Entity> datas = new ArrayList<>();
        datas.add(new Entity().setId(1).setName("顶级1"));
        datas.add(new Entity().setId(3).setName("子级1").setPid(1));
        datas.add(new Entity().setId(4).setName("子级2").setPid(3));
        datas.add(new Entity().setId(5).setName("子级3").setPid(1));

        //获取顶级菜单
        Entity top = datas.get(0);
        //获取子级集合
        List<Entity> tree = JBean.tree(top, datas, Entity::getId, Entity::getPid, Entity::getSonEntitys);
        //存入下级集合
        top.setSonEntitys(tree);

        //转json,方便观察结果
        JSONArray array = JSONUtil.parseArray(list);
        //输出[{"name":"顶级1","id":1,"sonEntitys":[{"pid":1,"name":"子级1","id":3,"sonEntitys":[{"pid":3,"name":"子级2","id":4,"sonEntitys":[]}]},{"pid":1,"name":"子级3","id":5,"sonEntitys":[]}]},{"name":"顶级2","id":2,"sonEntitys":[]}]
        System.out.println(array.toString());
}

@Data
@Accessors(chain = true)
public class Entity {
    //id
    private Integer id;

    private String name;

    //上级id 为null则表示顶级,规则是你自己定义
    private Integer pid;

    //下级集合
    private List<Entity> sonEntitys;
}

lambda引用解析

lambda解析工具,避免硬编码:

  1. 获取class。
  2. 获取方法名。
  3. 获取属性名。
public static void main(String[] args) {
    //获取class
    Class<Demo> claszz = JLambda.getClass(Demo::getId);
    //获取属性名 id
    String property = JLambda.getProperty(Demo::getId);
    //获取方法名 getName
    String getMethod = JLambda.getMethod(Demo::getName);
}

@Data
public class Demo {
    private Integer id;
    private String name;
}

spring bean动态管理工具

类名JSpringBean,运行时动态管理bean,api如下:

getBean(Class<T>)                                                       根据类型获取bean
getBean(String beanName)                                                根据名称获取bean
getBean(String beanName, Class<T> clazz)                                根据名称+类型获取bean
registerBean(T obj)                                                     根据类型注册bean
registerBean(String name, T obj)                                        根据类型注册bean
registerBean(Class<T> clazz, Map<String, Object> args)                  根据类型注册bean,map为bena实体参数列表
registerBean(String name, Class<T> clazz, Map<String, Object> args)     根据名称+类型注册bean,map为bena实体参数列表
removeBean(String name)                                                 根据名称删除bean

例子:

/**
 * bean对象
 */
@Data
public class TestBean {

    private Integer id;

    private String name;

}
@RestController
public class TestService {

    @GetMapping("test")
    public void test() {
        //注册bean
        Map<String, Object> map = new HashMap<>();
        map.put("id", 1);
        map.put("name", "小张");
        TestBean testBean = JSpringBean.registerBean(TestBean.class, map);
        //获取bean
        TestBean testBean1 = JSpringBean.getBean(TestBean.class);
        System.out.println(testBean1);
        Object testBean2 = JSpringBean.getBean("testBean");
        System.out.println(testBean2);
        //删除bean
        JSpringBean.removeBean("testBean");
    }

}

spring接口代理封装

spring接口代理封装,封装抽象了接口代理相关的操作,继承使用即可。

  1. JInvocationHandler 单泛型父类。
  2. JInvocationHandler2 两个泛型父类。
  3. JInvocationHandler3 三个泛型父类。 使用例子:
/**
 * 测试bean,主要演示代理实现类获取spring bean
 */
@Service
public class TestBean {

    /**
     * 输出泛型class名称
     */
    public void test(Class<?> clazz) {
        System.out.println(clazz.getName());
    }

}

下面开始编写代理类:

/**
 * 代理接口,用于给其他接口继承
 * @param <T>
 */
public interface DemoService<T> {

    void test();

}
/**
 * 代理接口实现
 *
 * @param <T>
 */
public class DemoServiceImpl<T> extends JInvocationHandler<T> implements DemoService<T> {

    public DemoServiceImpl(Class interfaceType) {
        super(interfaceType);
    }

    /**
     * 实现接口方法,调用测试bean,输出泛型class名称
     */
    @Override
    public void test() {
        //classa为JInvocationHandler父类提供的泛型实例,JInvocationHandler2对应classa、classb,JInvocationHandler3对应classa、classb、classc
        //因该代理类不受spring管理,所以使用JInvocationHandler提供的getBean()手动获取用于演示的TestBean
        TestBean testBean = getBean(TestBean.class);
        testBean.test(classa);
    }
}

此时代理类已经完成,下面编写测试类:

/**
 * 声明一个接口,并继承代理类,指定泛型String
 */
public interface TestService extends DemoService<String> {
}
/**
 * 测试控制层
 */
@RestController
public class TestServiceImpl {

    @Autowired
    private TestService testService;

    @GetMapping("test")
    public void test() {
        //输出java.lang.String
        testService.test();
    }
}

注解版过滤器

@JFilter一个注解实现过滤器,支持传入基本参数,你只需保证注解参数能强转为形参即可,可选择返回布尔值或抛出异常来实现请求是否继续,如返回false则中断请求并抛出JFilterError异常。

@JLFilter参数:
1. values       方法参数,顺序对应方法参数的顺序,仅支持常用数据类型。
2. excludes[]   过滤的url
3. order        执行顺序
4. error        返回false的异常错误信息
@Service
@AllArgsConstructor
public class Test {

    private HttpServletRequest request;

    @JFilter(error = "test过滤器异常")
    public boolean test() {
        System.out.println("请求url:" + request.getRequestURI());
        return true;
    }
}

注解版拦截器

@JInterceptor一个注解实现拦截器,支持传入基本参数,你只需保证注解参数能强转为形参即可,可选择返回布尔值或抛出异常来实现请求是否继续,如返回false则中断请求并抛出JInrerceptorError异常。

@JLInterceptor参数:
1. values       方法参数,顺序对应方法参数的顺序,仅支持常用数据类型。
2. excludes[]   过滤的url
3. order        执行顺序
4. error        返回false的异常错误信息
5. before       拦截方法之前(默认)
6. after        拦截方法之后
@Service
@AllArgsConstructor
public class Test {

    private HttpServletRequest request;

    @JInterceptor(excludes = {"/login", "/register"})
    public boolean test() {
        System.out.println("请求url:" + request.getRequestURI());
        return true;
    }
}

请求参数校验

注解@Check,简化版的@validated,基本思路和使用同@validated,基于aop,使用更简单,主要功能如下:

  1. 一个注解实现校验,自动根据数据类型判断而不需要和@validated一样由开发人为去根据类型使用不同注解。
  2. 自动封装校验异常返回值,而不用手动一个个属性指定,默认属性名,可自定义属性名称。
@Check参数:  
value       校验不通过抛出异常的属性名称  
max         最大,支持:数值、字符串、List
min         最小,支持:数值、字符串、List
regex       正则表达式,支持:字符串、数值
isValid     是否有效,有效才会校验。
isEmpty     是否可为空
groups[]    分组,同组才会被校验

例子:

public class OrderServiceimpl {

    @PostMapping("test")
    public void test(@RequestBody @Check(min = 1, max = 5) List<User> user) {
        //指定user集合最小长度=1 最大长度=5
    }

    @Data
    @Check//指定全局非空校验
    public static class User {
        //指定数值最小=1 最大=10000
        @Check(min = 1, max = 10000)
        private BigDecimal id;

        //指定字符最小长度=1 最大长度=20
        @Check(min = 1, max = 20)
        private String name;

        //自定义属性名称,校验不通过会使用该名称抛出异常
        @Check("订单集合")
        private List<Order> order;

        //指定集合最小长度=1 最大长度=10 并自定义属性名称
        @Check(min = 1, max = 10, value = "测试名称")
        private List<Integer> ints;

        private Boolean wq;

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime time;
    }

    @Data
    @Check//指定全局非空校验
    public static class Order {
        private BigDecimal id;

        private String no;

        private Money money;
    }

    @Data
    @Check//指定全局非空校验
    public static class Money {
        private BigDecimal id;

        private String cal;
    }
}

使用分组功能:

public class OrderServiceimpl {

    @PostMapping("test")
    public void test(@RequestBody @Check(groups = {TestGroup.class}) List<User> user) {
        //指定校验只被TestGroup分组修饰的属性
    }

    @Data
    @Check
    public static class User {
        @Check(groups = {TestGroup.class})
        private BigDecimal id;

        //该属性就不参与test接口的校验
        private String name;

        @Check(groups = {TestGroup.class})
        private List<Order> order;
    }

    @Data
    @Check
    public static class Order {
        @Check(groups = {TestGroup.class})
        private BigDecimal id;

        //该属性就不参与test接口的校验
        private String no;

        @Check(groups = {TestGroup.class})
        private Money money;
    }

    @Data
    @Check(groups = {TestGroup.class})
    public static class Money {
        private BigDecimal id;

        private String cal;
    }

    /**
     * 分组接口
     */
    interface TestGroup {

    }

}

对象拷贝

方法JBean.copy(),纯反射实现的bean拷贝,支持功能:

  1. 性能是BeanUtils的10-20倍之上。
  2. 解决BeanCopier无法读取有返回值的set方法而导致无法使用@Accessors(chain = true)链式编程。
  3. 实现了常用数据类型的转换,所以无需要求源bean和目标bean的属性数据类型一致,只要能保证数据类型可以强转即可。
  4. 支持对象拷贝、集合拷贝。
public static void main(String[] args) {
        User user = new User()
                .setId("1")
                .setName("test")
                .setMoney(99.99)
                .setTime(LocalDateTime.now());
        //对象拷贝
        UserVo1 userVo1 = JBean.copy(UserVo1.class, user);
        //对象拷贝 属性数据类型不一样,但能保证数据类型可以转换,同样可以拷贝
        UserVo2 userVo2 = JBean.copy(UserVo2.class, user);
        //集合拷贝
        List<UserVo2> userVo2s = JBean.copy(UserVo2.class, Arrays.asList(user));
    }

    @Data
    @Accessors(chain = true)
    public static class User {
        private String id;

        private String name;

        private Double money;

        private LocalDateTime time;
    }

    @Data
    @Accessors(chain = true)
    public static class UserVo1 extends User {

    }

    @Data
    @Accessors(chain = true)
    public static class UserVo2 {
        private Integer id;

        private String name;

        private BigDecimal money;

        private String time;
    }

io工具

类JIo,整合了字节流的操作,链式调用,使用方便些。 api列表:

InputStreamMethod inputStream(String path)                     字节输入流,读取路径,支持项目相对路径、服务器绝对路径、网络url。
InputStreamMethod inputStream(File file)                       字节输入流,读取file
OutputStreamMethod outputStream(String path)                   字节输出流,输出到路径
OutputStreamMethod outputStream(File file)                     字节输出流,输出到File
OutputStreamMethod outputStream(String path, boolean append)   字节输出流,输出到路径,append为是否追加输出
OutputStreamMethod outputStream(File file, boolean append)     字节输出流,输出到File,append为是否追加输出

InputStreamMethod方法列表:

InputStream get()       获取字节输入流
String content()        字符串形式获取读取文件的内容

OutputStreamMethod方法列表:

OutputStream get()                      获取字节输出流
void save(String content)               保存字符串内容到文件
void save(InputStream inputStream)      保存字节输入流到文件

例子:

//获取字节输入流
InputStream inputStream = JIo.inputStream("d://test.txt").get();

//获取字节输入流内容
String testContent = JIo.inputStream("d://test.txt").content();

//读取demo.txt文件内容,追加到test.txt文件
JIo.outputStream("d://demo.txt", true).save(inputStream);

注解版项目启动完成后执行任务

注解JRunner,项目启动成功后执行的方法执行被注解的方法。

@Service
public class Test {
    
    @JLRunner
    public void demo() {
        System.out.println("demo");
    }

    @JRunner({"张三", "18"})
    public void test(String name, Integer age) {
        System.out.println(name);
        System.out.println(age);
    }
}

空文件

简介

包含开发编码能用到的一些封装工具,提升开发效率以及代码优雅性。 展开 收起
Java
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/laoshirenggo/jl-tools.git
git@gitee.com:laoshirenggo/jl-tools.git
laoshirenggo
jl-tools
jl-tools
master

搜索帮助