[用js写java jvm]1.js解析java bean中的属性和基本类型
来源:互联网 发布:第三次工业革命 知乎 编辑:程序博客网 时间:2024/06/06 09:32
前几天看到国外有报道说js实现了大部分的jvm功能,最近也一直在考虑如何用js实现一个jvm功能。
后来想了下,还是可行的,其实只是用js实现jvm规范,例如对于java来说有一个System.out,println("test");这样的语句一出现就会在控制台输出:"test"
这个语法对应javascript也就是
var System ={};
System.out={
println:function(val){
//实现具体的功能
alert(val);
}
}
如java中java.lang.String 也可以参照上术方式实现,api按此方式慢慢实现
那对于如何转换一个java bean对象也是今天所要讲的重点,不知道如果将一个java bean转换为javascript object的方法,那么即使实现了api也没有环境让java语言运行起来。
接着将介绍转换方法:
首先我们先来看一个简单的java bean和javascript object有什么区别
public class Test{ private int a; public int getA(){ reutrn a; }}
function Test{ }Test.prototype.a = 0;Test.prototype.getA = function(){ return this.a;}看到这2种写法,应该能比较清楚的看出朝着这个方法转变就行。
好了,现在开始进行解析
解析过程:
1.类名的提取
根据java规范,我们知道一个类的命名必须是class name{...}这种方式,前面要有修饰符,内部类也是这种方式
可以写一个正则匹配这种内容,只需要匹配第一个出现{的字符串,提取里面的classname
或者采用正则(public|private|protected)?\s*class\s*\w+?{ 或者 class(.+?){ 匹配出所有符合规则的数据,将内部类名字也匹配出来
具体代码可参考Class.getName();
2.属性的提取
也可以采用正则方法处理,java成员变量的特点:修饰符(可有可无)+变量类型+成员名称+";"(注意后面还有一个;结束符)
和局部变量的区别在于有返回值类型,和method的区别在于没有(){...}代码片段
所以属性的提取可以采用正则
/(private|public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s|_]+;
在处理属性的过程中,我们需要对变量类型做处理,如java中int类型的成员变量默认值是0等等。。。
于是我们定义一个于成员变量类型对应的var Type = {
"int":0,
"boolean":false
}
假设我们匹配到了"public int a;"这个字符串
接着我们就可以处理成这样了
classname.prototype.a =Type[int];
3.方法的提取(先介绍主函数main方法的处理)
method的提取相对比较麻烦点,需要考虑{}标签闭合的处理
main方法也是主入口函数,如果存在则会执行里面的内容,必须是public void static main(String[] args)...{....}这种方式,而且在一个类中只有一个,期中args是参数入口,对应arguments
转换成对应的js就是
classname.prototype.ininv = function(){....};
对于复杂方法的提取,这里暂时先不展开。
4.执行转换后代码
以Test.java为例
public class Test{ public void static main(String[] args){ System.out.println("test"); }}
转换成js后的var source = "function Test(){};"
source += "Test.prototype.initv = function(){System.out.println(\"test\")}";
然后<script>document.write(source)</script>,
这样就能在window["Test"]下拿到这个Test对象,执行他的方法了。
具体源码可以参考Class._creatInitV()
另外还需要模拟一个很重要的入口,Class.forname方法,实现这个方法可以帮助我们很好的寻找处理java类
源码:
<script>/* * 扩展jtrim方法,使用方法有下面几种 * trim() 去除字符串左右两端的空格 * trim("xyz") 去除字符串左右两端的字符xyz * trim(/[0-9]/g) 去除字符串左右两端的数字 * trim(2) 去除字符串左端2个字符 * trim(0,3) 去除字符串右端3个字符 * trim(2,3) 去除字符串左端2个字符右端3个字符 */String.prototype.trim = function(){ var _argument = arguments[0] == undefined ? " " : arguments[0]; if(typeof(_argument) == "string"){ if (_argument == " ") { return this.replace(/(^(\s|\u3000)*)|((\s|\u3000)*$)/g, ""); } else { return this.replace(new RegExp("(^" + _argument + "*)|(" + _argument + "*$)", "g"), ""); } }else if(typeof(_argument) == "object"){ return this.replace(_argument, ""); }else if(typeof(_argument) == "number"){ if (arguments.length == 1) { return this.substring(arguments[0]) } else if(typeof(arguments[1]) == "number") { return this.substring(arguments[0], this.length-arguments[1]); } } return this;};//对应java种的system类,这种类的功能只需要按下面这种格式逐个翻译成js class即可var System = {}System.out ={println:function(val){this.print(val + "\r\n");},print:function(val){val = val == undefined ? "undefined" : val;if(typeof(val) == "string"){ alert(val);}}}//js jvm对应的基础类型,目前先支持这4种基础类型var Type = {"int" : 0,"boolean" : false,"float" : 0.0,"double" : 0.0,"String" : null,"void" : null,}//获取解析java对象核心的功能,相当于java中的class.forname获得一个对象var Class = {source : "",//处理初始化对象javasource : "",forName:function(javasource){this.javasource = javasource;//记录javasource,分析过程中会需要原始数据var classname = this.getName();this.source += "function "+classname+"(){}";//类名解析,转换到js obj上的时候classname是创建jsobj的关键//this.source += classname+"prototype."+this.source += this._createInitV(classname);//主main方法识别创建this.source += this._createAttributes(classname);//创建属性//this.getDeclaredFields();this.source += this._createMethods(classname);//todo 创建方法return this;},//初始化函数的创建,检测是否存在public static void main方法_createInitV:function(classname){ var str = "";var initv = String.trim(this.javasource).match(/public static void main\(String\[\].+?\){(.+?)}/); if(initv.length >= 1){ str += classname+".prototype.initv=function(){"; str += (initv.length == 2)? initv[1]:"";//init[1]是匹配后main方法内的数据 str += "};"; }return str;},//创建对象属性//这个正则对方法内的变量申明不能很好识别//todo public void getXXX(){int xxx;}这里的int xxx;也会被识别,需要先处理method后再处理attribute//todo 还不支持abstract字段_createAttributes : function(classname){var value = "";var attrs = String.trim(this.javasource).match(/(private|public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s|_]+;/g); var attr="";for(var i=0,length=attrs.length;i<length;i++){ attr = String.trim(attrs[i]); if(attr != ""){ //先去除开头的public private protected,以及末尾的;符号 if(attr.indexOf("public") == 0){ attr = attr.substring("public".length,attr.length-1).trim(); }else if(attr.indexOf("private") == 0){ attr = attr.substring("private".length,attr.length-1).trim(); }else if(attr.indexOf("protected")){ attr = attr.substring("protected".length,attr.length-1).trim(); } //接着剩下的都是类型+名称的变量字符串了。。。 //根据类型要赋一些初始值 var typevalue = Type[attr.substring(0,attr.indexOf(" "))];//获取type对应的默认value var attrname = attr.substring(attr.indexOf(" ")).trim();//获取attribute name //开始组装js对应的属性 value += classname + ".prototype."+ attrname; value += "="; value += typevalue; value += ";"; } }return value;},//为对象创建method//(private|public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s]+\((void|int|float|boolean|double|String)?(.+)?\)\s+{\s+([\r|\n|\t])?.+\s+([\r|\n|\t])?}//理论上只需要转换public方法即可,private方法无法调用转换,转换后采用_methodname表示私有方法_createMethods : function(classname){var value = "";//处理public方法var methods = String.trim(this.javasource).match(/(public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s]+\((void|int|float|boolean|double|String)?(.+)?\)\s+{\s+([\r|\n|\t])?.+\s+([\r|\n|\t])?}/ig);if(methods){for(var i=0,length = methods.length;i<length;i++){value = this.javaMethodTojsFunction(methods[i]);}}//处理private方法return "";},//java method转为js function//public int getXXX(){} --> getXXX : function(){}//todo 如果不带修饰符的时候如何处理?目前当作public处理,也是符合java规范的_javaMethodTojsFunction : function(val){if(val.indexOf("public") == 0){val = val.substring("public".length).trim();//去掉开始的public,public在js中没有这种关键字,默认已经是public}val = val.substring(val.indexOf(" ")).trim();//去除typevar methodname = val.substring(0,val.indexOf("(")).trim();//根据(符合决定方法名,因为method定义后面必须要有() var functioncontent = val.substring(val.indexOf("(")).trim();//除方法名外,其他都是function内容 functioncontent = "function"+ functioncontent;//改变为function(){} (){}这种之后在java中是执行代码片段,这种代码可以直接转换为js代码片段 },//解析return方法_returnCompile : function(val){},getDeclaredFields:function(){this.source += "Test.prototype = {";this.source += "initv:function(){";//initv逻辑解析-->检测入口,方法,字段等等//...//处理system.out.println method -->alertthis.source += "alert(\"hello world\");";this.source += "}";this.source += "}";},//获取对象名字getName:function(){//类的名字可以根据 class name {匹配,找到第1个就是类名, //如果有多个,那么后面的属于内部类var names = String.trim(this.javasource).match(/class(.+?){/g);var name = names[0].substring("class".length,names[0].length-1);return String.trim(name);}}function JVM(){}JVM.prototype ={compile:function(javasource){var obj = new Object();obj = Class.forName(javasource);//obj = eval(obj.source);///obj.initv();document.write("<script>"+obj.source+"<\/script>");//todo 需要改进为在自己的package下,引入namespaces后再扩展这部分return window[obj.getName()]; //classname还是比较好分析获取的}}var javasource = "public class Test { ";javasource += "private int tmpa;";javasource += "private boolean tmpb;";javasource += "private float tmpc;";javasource += "private double tmpd;";javasource += "private String tmpe;";javasource += "private Object tmpf;";javasource += "public int getTmpa(){";javasource += " return tmpa;";javasource += "}";javasource += "public static void main(String[] args){";javasource += "System.out.println(\"hello world\");";javasource += "System.out.println(\"world is round\");";javasource += "}";javasource += "class Test2 {";javasource += "private int tmpz;";javasource += "};"javasource += "}";//创建一个jsjvmvar jsjvm = new JVM();//编译java源代码var obj = jsjvm.compile(javasource);//创建对象var tes = new obj();//调用方法,main方法转为init方法,改天写这个解析逻辑tes.initv();alert(tes.tmpb);alert(tes.tmpe);//alert(" 123".trim())//(public)?\s*(void|int|float|boolean|double|String)[A-Za-z0-9|\s]+\((void|int|float|boolean|double|String)?(.+)?\)\s*{\s*([\r|\n|\t])*.+\s*([\r|\n|\t])?*}</script>
今天先介绍到这里,下周继续介绍如何处理成员方法和控制bean对象的加载卸载
如果没周写一篇这样贴代码的文章,然后后面再跟着http://ditu.alibaba.com,不知道又能赚多少外链。
Google 作者:陈旭东 email:wzucxd@gmail.com 2011.12.25
- [用js写java jvm]1.js解析java bean中的属性和基本类型
- java和Js中的类型转换
- js中的基本类型和引用类型
- Java中的基本类型和引用类型
- JS中的变量:引用类型和基本类型
- 理解js中的基本类型和引用类型
- JS中的属性类型理解
- js中的基本类型与包装类型
- java中的基本类型
- java中的基本类型
- JAVA中的基本类型
- java后台Date类型与js中的Date类型转化
- JS和JAVA使用JSON方法解析
- JS和JAVA使用JSON方法解析
- JS基本类型与Java的区别复习
- java 解析js脚本
- Java ScriptEngine 解析js
- Android&Java解析JS
- JAVA连接池
- JavaScript性能陷阱
- VirtualBox 提示虚拟硬盘空间不足( Host system reported disk full.)
- 内存回收
- C++中模拟委托事件的方法(三)
- [用js写java jvm]1.js解析java bean中的属性和基本类型
- JSB 表单操作和txt文件上传
- 小软件项目开发的管理
- 中文分词?
- Stack模板
- 技术人员成长
- 复制CSDN代码(blog) 去掉前面的行号
- android中的数据存取 之 File
- break,return,continue区别