LuaJava操作Java的方法
最近在学习lua,然后顺便看了下luaj,可能用的人比较少,网上关于luaj的文章较少,其中在网上找到这个博主的相关文章,很详细,对于要学习luaj的小伙伴可以两篇一起查看,本文在此基础上进行扩展。
本文的luaj版本是:luaj-3.0.1
珠玉在前》》》》Luaj学习笔记(二) - 在Lua中操作Java对象
LuaJ源码中org.luaj.vm2.lib.jse.LuajavaLib,是我们在lua中操作java的主要方法库定义。
luajava有五种方法让我们操作java类:bindClas
、 newInstance
、 new
、 createProxy
、 loadLib
先放上源码,然后我们一步步解析,bindClas
、 newInstance
、 new
使用方案和案例在前一篇文章就已经解释过了,这里不做过多赘述,对于前篇不详细的createProxy
和loadLib
做重点介绍:
public Varargs invoke(Varargs args) {try {switch ( opcode ) {case INIT: {// LuaValue modname = args.arg1();LuaValue env = args.arg(2);LuaTable t = new LuaTable();bind( t, this.getClass(), NAMES, BINDCLASS );env.set("luajava", t);env.get("package").get("loaded").set("luajava", t);return t;}case BINDCLASS: {final Class clazz = classForName(args.checkjstring(1));return JavaClass.forClass(clazz);}case NEWINSTANCE:case NEW: {// get constructorfinal LuaValue c = args.checkvalue(1); final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));final Varargs consargs = args.subargs(2);return JavaClass.forClass(clazz).getConstructor().invoke(consargs);}case CREATEPROXY: { final int niface = args.narg()-1;if ( niface <= 0 )throw new LuaError("no interfaces");final LuaValue lobj = args.checktable(niface+1);// get the interfacesfinal Class[] ifaces = new Class[niface];for ( int i=0; i<niface; i++ ) ifaces[i] = classForName(args.checkjstring(i+1));// create the invocation handlerInvocationHandler handler = new ProxyInvocationHandler(lobj);// create the proxy objectObject proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);// return the proxyreturn LuaValue.userdataOf( proxy );}case LOADLIB: {// get constructorString classname = args.checkjstring(1);String methodname = args.checkjstring(2);Class clazz = classForName(classname);Method method = clazz.getMethod(methodname, new Class[] {});Object result = method.invoke(clazz, new Object[] {});if ( result instanceof LuaValue ) {return (LuaValue) result;} else {return NIL;}}default:throw new LuaError("not yet supported: "+this);}} catch (LuaError e) {throw e;} catch (InvocationTargetException ite) {throw new LuaError(ite.getTargetException());} catch (Exception e) {throw new LuaError(e);}}
bindclass
bindclass:返回一个JavaClass的类,该类是对我们参数指定的java类的一个包装。bindClass方法返回类实例class,同时可以调用类实例的new方法生成该class的实例object,然后就可以调用实例方法(实例化的调用这一点和学lua时的面向对象的写法很相似)
该方法适合调用java类的
静态方法
和静态属性
,当然也可以用来实例化对象,但newInstance 和 new更符合语义
源码:
case BINDCLASS: {final Class clazz = classForName(args.checkjstring(1));return JavaClass.forClass(clazz);}JavaClass:static final LuaValue NEW = valueOf("new");static JavaClass forClass(Class var0) {JavaClass var1 = (JavaClass)classes.get(var0);if (var1 == null) {classes.put(var0, var1 = new JavaClass(var0));}return var1;}public LuaValue getConstructor() {return this.getMethod(NEW);}
测试java代码:
public class TestClass {public String s1;protected String s2;private String s3;public static String s4;public String method001(){ return "method001"; }protected void method002(){ }private void method003(){ }public static String method004(){ return "method004"; }
}
lua脚本:
local className = "com.test.luaj.TestClass"local classx = luajava.bindClass(className)
print("静态方法调用:",classx:method004())
print("静态属性值:",classx.s4)local obj = classx:new()
print("实例方法调用:",obj:method001())
print("实例属性值:",obj.s1)
输出结果:
静态方法调用: method004
静态属性值: s4
实例方法调用: method001
实例方法调用: s1
其中,我们在lua脚本中用类实例调用:new()
方法时,实际是invoke JavaClass的new方法,而这个new方法通过getMethod方法拿到的是他的构造器方法(在下一个方法源码中)
newInstance || new
通过源码可以看到 newInstance 和 new方法的大部分逻辑是一致的
入参是有区别的:
- newInstance 方法,接受一个字符串的类路径然后转换为Class实例;
- new方法接受一个LuaValue对象,从中拿出userdata数据,而这个userdata数据是一个Class实例。
而上一个方法bindClass返回的就是一个包装了Class的LuaValue对象,因此我们可知,在使用new方法的时候,需要先用bindClass方法生成一个Class实例出来,而newInstance就不用了
然后代码对我们在lua中传入的参数,截取后边的一段用作构造器参数,然后调用我们在上一个方法看到JavaClass.forClass包装Class实例,然后获取该类的构造器,然后invoke调用构造器方法,生成对象。
源码:
case NEWINSTANCE:case NEW: {// get constructorfinal LuaValue c = args.checkvalue(1); final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));final Varargs consargs = args.subargs(2);return JavaClass.forClass(clazz).getConstructor().invoke(consargs);}JavaClass:public LuaValue getConstructor() {return getMethod(NEW);}LuaValue getMethod(LuaValue key) {
···Map map = new HashMap();Constructor[] c = ((Class)m_instance).getConstructors();List list = new ArrayList();for ( int i=0; i<c.length; i++ ) if ( Modifier.isPublic(c[i].getModifiers()) )list.add( JavaConstructor.forConstructor(c[i]) );switch ( list.size() ) {case 0: break;case 1: map.put(NEW, list.get(0)); break;default: map.put(NEW, JavaConstructor.forConstructors( (JavaConstructor[])list.toArray(new JavaConstructor[list.size()]) ) ); break;}
···
}
测试代码:
local className = "com.test.luaj.TestClass"local classx = luajava.bindClass(className)
local obj = luajava.new(classx)
print("实例方法调用:",obj:method001())
print("实例属性值:",obj.s1)
print("-----------")local obj2 = luajava.newInstance(className)
print("newInstance>实例方法调用:",obj2:method001())
print("newInstance>实例属性值:",obj2.s1)
输出结果:
new>实例方法调用: method001
new>实例属性值: s1
-----------
newInstance>实例方法调用: method001
newInstance>实例属性值: s1
createProxy
createProxy可以像JDKProxy那样的在lua中创建对一个对象的一个或多个方法的代理
事实上,createProxy使用的代理就是JDKProxy,只不过在用法上和我们通常的用法有些许变动,在最终的方法的invoke时,并不是通常的使用JAVA反射中的的Method的invoke,而是Luaj自己LuaValue的invoke,也就是说通过调用在lua脚本中定义的那个扩展方法,去实现代理,实际上的代理逻辑都在lua中定义(下面lua脚本可以看出来)
还有很重要的一点,在lua中通过createproxy生成出来的代理对象,是不能在lua脚本中去直接调用代理对象的方法的,?????只能通过将该代理对象当做参数通过调用类方法或者对象方法之后在java中去触发代理对象的方法。(看下边的测试lua源码)
源码:
case CREATEPROXY: { final int niface = args.narg()-1;if ( niface <= 0 )throw new LuaError("no interfaces");final LuaValue lobj = args.checktable(niface+1);// get the interfacesfinal Class[] ifaces = new Class[niface];for ( int i=0; i<niface; i++ ) ifaces[i] = classForName(args.checkjstring(i+1));// create the invocation handlerInvocationHandler handler = new ProxyInvocationHandler(lobj);// create the proxy objectObject proxy = Proxy.newProxyInstance(getClass().getClassLoader(), ifaces, handler);// return the proxyreturn LuaValue.userdataOf( proxy );}
测试java代码:
public interface Car {void running(String carName);void blow(Integer num);}
-------------------------------------------------
public class Taxi implements Car {@Overridepublic void running(String carName) {System.out.println("The taxi["+carName+"] is running.");}@Overridepublic void blow(Integer num) {for (int i = 0; i < num; i++) {System.out.print("didi\n");}System.out.print("");}public static void triggerProxy(Car car){String carName = UUID.randomUUID().toString();car.running(carName);System.out.println("--------");car.blow((int)Math.random()*10+1);}}
-----------------------------------------------------public class LuaJCreateProxyTest {public static void main(String[] args) throws ScriptException {createProxy002();}static void createProxy002() throws ScriptException {Globals globals = JsePlatform.standardGlobals();globals.loadfile("res/lua/createProxyTest02.lua").call();}
}
lua脚本:
interfaceName = "com.test.luaj.Car"className = "com.test.luaj.Taxi"taxi = luajava.newInstance(className)-- InvocationHandlerlocal exit_cb = {running = function (carname)print("这是对Car的代理逻辑----前")taxi:running(carname)print("这是对Car的代理逻辑----后")end,blow = function(num)print("Car--blow----前")taxi:blow(num)print("Car--blow----后")end}proxyObj = luajava.createProxy(interfaceName ,exit_cb)-- proxyObj.running() -- 会报错,不能这样使用--必须通过传参给java方法,在java代码中去调用代理对象的方法luajava.bindClass(className):triggerProxy(proxyObj)
输出结果:
这是对Car的代理逻辑----前
The taxi[74f253d1-c0d8-47ea-9799-01401174abe4] is running.
这是对Car的代理逻辑----后
--------
Car--blow----前
didi
Car--blow----后
loadLib
关于loadLib
这个方法,前边文章可能由于历史更新的原因,在luaj-3.0.1版本中代码是不对的
loadLib通过源码查看我,我们其实可以看到,他只用两个参数,第一个是类路径,第二个是静态方法名,这个方法要么返回一个LuaValue类型的结果,要么不返回或者其他返回类型都会被loadLib转为nil
。
源码:
case LOADLIB: {// get constructorString classname = args.checkjstring(1);String methodname = args.checkjstring(2);Class clazz = classForName(classname);Method method = clazz.getMethod(methodname, new Class[] {});Object result = method.invoke(clazz, new Object[] {});if ( result instanceof LuaValue ) {return (LuaValue) result;} else {return NIL;}}
测试java源码:
public static LuaInteger xxx() throws ScriptException {System.out.println("xxx执行啦!\t"+(int)Math.pow(14,2));return LuaValue.valueOf((int)Math.pow(14,2));}static void test007() throws ScriptException {Globals globals = JsePlatform.standardGlobals();globals.loadfile("res/lua/loadLibTest.lua").call();}
lua脚本
local className = "com.yangsong.luaj.LuaJTest"
local method = 'xxx'
local _, result = luajava.loadLib(className, method)
print(_,result)
输出结果:
xxx执行啦!
196 nil
总结
bindClass
适合做类的静态方法和静态属性的取值的操作,也是使用new
方法的前置操作。
newInstance
和new
适合用作java对象实例化之后对实例对象的操作和取值
createProxy
适合用作JDKProxy的替代用法,需要注意的是在被代理对象和代理对象都在脚本中生成,且代理对象不能直接在lua中去调用代理方法执行,需要以传参的形式给到java方法调用java方法触发。
loadLib
用于类的无参静态方法的调用,如果需要返回值,则需要定义方法返回类型为LuaValue
相关文章:
LuaJava操作Java的方法
最近在学习lua,然后顺便看了下luaj,可能用的人比较少,网上关于luaj的文章较少,其中在网上找到这个博主的相关文章,很详细,对于要学习luaj的小伙伴可以两篇一起查看,本文在此基础上进行扩展。 …...
oracle怎样才算开启了内存大页?
oracle怎样才算开启了内存大页? 关键核查下面三点: 1./etc/sysctl.conf vm.nr_hugepages16384这是给了32G,计划sga给30G,一般需多分配2-4G sysctl -p生效 看cat /proc/meminfo|grep Huge啥结果? 这种明显是配了…...
【halcon深度学习之那些封装好的库函数】determine_dl_model_detection_param
determine_dl_model_detection_param 目标检测的数据准备过程中的有一个库函数determine_dl_model_detection_param “determine_dl_model_detection_param” 直译为 “确定深度学习模型检测参数”。 这个过程会自动针对给定数据集估算模型的某些高级参数,强烈建议…...
跟着我学Python进阶篇:01.试用Python完成一些简单问题
往期文章 跟着我学Python基础篇:01.初露端倪 跟着我学Python基础篇:02.数字与字符串编程 跟着我学Python基础篇:03.选择结构 跟着我学Python基础篇:04.循环 跟着我学Python基础篇:05.函数 跟着我学Python基础篇&#…...
neo4j-Py2neo使用
neo4j-Py2neo(一):基本库介绍使用 py2neo的文档地址:https://neo4j-contrib.github.io/py2neo/ py2neo的本质是可以采用两种方式进行操作,一种是利用cypher语句,一种是使用库提供的DataTypes,Data类的实例需要和远程…...
uint29传输格式
前言 不知道谁想出来的。 反正我是想不到。 我看网上也没人讲这个。 写篇博客帮一下素未谋面的网友。 uint29 本质上是网络传输的时候,借用至多4字节Bytes,表达29位的无符号整数。 读8位数字,判断小于128? 是的话,返回末7位…...
Linux:终端定时自动注销
这样防止了,当我们临时离开电脑这个空隙,被坏蛋给趁虚而入 定几十秒或者分钟,如果这个时间段没有输入东西那么就会自动退出 全局生效 这个系统中的所有用户生效 vim /etc/profile在末尾加入TMOUT10 TMOUT10 这个就是10 秒,按…...
STM32F103RCT6开发板M3单片机教程06--定时器中断
前言 除非特别说明,本章节描述的模块应用于整个STM32F103xx微控制器系列,因为我们使用是STM32F103RCT6开发板是mini最小系统板。本教程使用是(光明谷SUN_STM32mini开发板) STM32F10X定时器(Timer)基础 首先了解一下是STM32F10X…...
数据库故障Waiting for table metadata lock
场景:早上来发现一个程序,链接mysql数据库有点问题,随后排查,因为容器在k8s里面。所以尝试重启了pod没有效果 一、重启pod: 这里是几种在Kubernetes中重启Pod的方法: 删除Pod,利用Deployment重建 kubectl delete pod mypodDepl…...
Springboot数据校验与异常篇
一、异常处理 1.1Http状态码 HTTP状态码是指在HTTP通信过程中,服务器向客户端返回的响应状态。它通过3位数字构成,第一个数字定义了响应的类别,后两位数字没有具体分类作用。以下是常见的HTTP状态码及其含义: - 1xx(信…...
第三十六章 XML 模式的高级选项 - 创建子类型的替换组
文章目录 第三十六章 XML 模式的高级选项 - 创建子类型的替换组创建子类型的替换组将子类限制在替换组中 第三十六章 XML 模式的高级选项 - 创建子类型的替换组 创建子类型的替换组 XML 模式规范还允许定义替换组,这可以是创建选择的替代方法。语法有些不同。无需…...
堆与二叉树(上)
本篇主要讲的是一些概念,推论和堆的实现(核心在堆的实现这一块) 涉及到的一些结论,证明放到最后,可以选择跳过,知识点过多,当复习一用差不多,如果是刚学这一块的,建议打…...
HBase查询的一些限制与解决方案
Apache HBase 是一个开源的、非关系型、分布式数据库,它是 Hadoop 生态系统的一部分,用于存储和处理大量的稀疏数据。HBase 在设计上是为了提供快速的随机读写能力,但与此同时,它也带来了一些查询上的限制: 没有SQL支持…...
软件开发 VS Web开发
我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情 目录 介绍: 角色和职责: 软件开发人员: Web开发人员: 技能: 软件开发人员: Web开发人…...
基于Springboot的旅游网站设计与实现(论文+调试+源码)
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…...
【从零开始学习--设计模式--策略模式】
返回首页 前言 感谢各位同学的关注与支持,我会一直更新此专题,竭尽所能整理出更为详细的内容分享给大家,但碍于时间及精力有限,代码分享较少,后续会把所有代码示例整理到github,敬请期待。 此章节介绍策…...
条款6:若不想使用编译器自动生成的函数,就该明确拒绝
有些场景我们不需要编译器默认实现的构造函数,拷贝构造函数,赋值函数,这时候我们应该明确的告诉编译器,我们不需要,一个可行的方法是将拷贝构造函数和赋值函数声明为private。 class HomeForSale { ... }; HomeForSal…...
零基础也能制作家装预约咨询小程序
近年来,随着互联网的快速发展,越来越多的消费者倾向于使用手机进行购物和咨询。然而,许多家装实体店却发现自己的客流量越来越少,急需一种新的方式来吸引顾客。而开发家装预约咨询小程序则成为了一种利用互联网技术来解决这一问题…...
Mybatis的插件运⾏原理,如何编写⼀个插件?
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…...
C++复合数据类型:字符数组|读取键盘输入|简单读写文件
文章目录 字符数组(C风格字符串)读取键盘输入使用输入操作符读取单词读取一行信息getline使用get读取一个字符 读写文件 字符数组(C风格字符串) 字符串就是一串字符的集合,本质上其实是一个“字符的数组”。 在C中为了…...
Windows11环境下配置深度学习环境(Pytorch)
目录 1. 下载安装Miniconda2. 新建Python3.9虚拟环境3. 下载英伟达驱动4. 安装CUDA版Pytorch5. CPU版本pytorch安装6. 下载并配置Pycharm 1. 下载安装Miniconda 下载安装包:镜像文件地址 将Miniconda相关路径添加至系统变量的路径中。 打开Anaconda Powershell Pr…...
泛型深入理解
泛型的概述 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。 泛型的格式:<数据类型>; 注意:泛型只能支持引用数据类型。 集合体系的全部接口和实现类都是支持泛型的使用的。 泛型的…...
Linux内核模块
文章目录 一、内核模块介绍二、模块讲解1、最简模块代码:2、模块三要素3、常用操作命令3.1、 lsmod:显示已加载模块状态3.2、 insmod:载入模块3.3、rmmod:卸载模块3.4、dmesg:显示信息3.5、modinfo:显示ker…...
Java 栈和队列的交互实现
文章目录 队列和栈的区别一.用队列模拟实现栈1.1入栈1.2出栈1.3返回栈顶元素1.4判断栈是否为空 二.用栈模拟实现队列2.1 入队2.2出队2.3peek2.4判断队列是否为空 三.完整代码3.1 队列模拟实现栈3.2栈模拟实现队列 队列和栈的区别 栈和队列都是常用的数据结构,它们的…...
HarmonyOS应用开发者高级认证满分指南
声明:由于HarmonyOS应用开发者高级认证的题库一直在变,所以文章中的题目直做参考。 1. 判断题 云函数打包完成后,需要到APPGallery Connect创建对应函数的触发器才可以在端侧中调用。 【错】每一个自定义组件都有自己的生命周期。 【对】基…...
CSharp中Blazor初体验
Blazor 是一个由微软开发的开源 Web 框架,用于构建富客户端 Web 应用程序使用 C# 语言和 .NET 平台。Blazor 允许开发人员使用 C# 语言来编写前端 Web 应用程序,而不需要像传统的 JavaScript 框架(如 Angular、React 或 Vue.js)那…...
Linux下新建用户,并进行授权
注意:以下操作需要在root用户下! 新增用户 adduser 用户名设置密码 passwd 用户名更改目录所有者命令 chown -R 用户名:用户名 目录更改目录权限命令 chmod -R 755 目录...
STM32为基础的模拟I2C通用8bit和16bit读取以及多字节读取
GPIO模拟I2C驱动的通用代码,I2C的寄存器地址有8位和16位的,主要解决了同一个MCU同时处理8位和16位寄存器地址芯片时候的驱动问题。 typedef enum {IIC_8BIT_BASE_ADDR,IIC_16BIT_BASE_ADDR }iic_bits_e; typedef struct {uint8_t DevAddr;uint16_t RegA…...
算法训练营Day19
#Java #二叉树 #双指针 开源学习资料 Feeling and experiences: 二叉搜索树的最小绝对差:力扣题目链接 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数,其数值等于两值之差的…...
C++数据结构——二叉搜索树详解
目录 一,关于二叉搜索树 1.1 概念 1.2 基本结构 二,二叉搜索树接口实现 2.1 插入 2.2 查找 2.3 打印 2.4* 删除 三,二叉搜索树接口递归实现 3.1 查找 3.2 插入 3.3 删除 四,二叉搜索树的默认成员函数 五,…...
网站建设和网站开发的区别/免费建站建站abc网站
本文实例分析了jQuery对象与DOM对象的转换方法。分享给大家供大家参考,具体如下: jQuery对象转换为dom对象 只有jQuery对象才能调用jQuery类库的各种函数,同样有些dom对象的属性和方法在jQuery上也是无法调用的,不过基本上jQuery类…...
wordpress分页目录编辑/互动营销名词解释
首先, equality 等同, identity 恒等。, 两边值类型不同的时候,要先进行类型转换,再比较。,不做类型转换,类型不同的一定不等。下面分别说明:先说 ,这个比较简单。下面的…...
衡水专业做网站/武汉网站推广优化
push()/pop() -- shift()/unshift() 不建议使用delete concat() sort()排序 reverse()反转 数组迭代 Array.map()创建一个和原数组一一对应的新数组 Array.Filter()过滤掉不符合条件的元素 Array.every() / Array.some()返回bool类型值 Array.find()返回值 返回索引...
wordpress远程ftp/企业营销策划有限公司
前几天做项目的时候,需要实现一个动态锚点的效果 如果是传统项目,这个效果就非常简单。但是放到 Vue 中,就有两大难题: 1. 在没有 jQuery 的 animate() 方法的情况下,如何实现平滑滚动? 2. 如何监听页面滚…...
建站行业现状探讨/优化网站有哪些方法
隐式意图在很多app中应用广泛,使用隐式意图不仅可以启动自己程序中的Activity,还可以启动其他程序中的Activity,使得程序之间可以共享某种功能。以下将对于用过的setAction()的方法作以归纳整理,持续更新… 1、android.intent.ac…...
wordpress浮动标签云/小程序开发需要哪些技术
ListView的下拉刷新很常见,很多开源的框架都能做到这个效果,当然也可以自己去实现。本篇案例是基于xlistview的。 布局: <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android" xmlns:tools"http:/…...