`
wzucxd
  • 浏览: 26551 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

[用js写java jvm]1.js解析java bean中的属性和基本类型

 
阅读更多

前几天看到国外有报道说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();//去除type
			var 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 -->alert
			this.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 += "}";


//创建一个jsjvm
var 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

分享到:
评论

相关推荐

    Professional.Java.JDK.6.Edition

    此外,还引入了动态类型语言支持,通过JSR 223(Java Scripting API)允许在Java程序中嵌入和执行其他脚本语言,如JavaScript和Groovy。 在类库和API方面,JDK 6提供了许多增强,例如NIO.2(非阻塞I/O),它扩展了...

    出现几率最高和覆盖范围最广的一套经典Java面试题.docx

    20. **EJB部署文件**:包含ejb-jar.xml和jboss.xml等,描述EJB的元数据,如bean的类型、接口、事务属性等。App Server根据部署文件管理EJB实例。 21. **设计模式**:如单例模式、工厂模式、观察者模式、策略模式、...

    JAVA上百实例源码以及开源项目源代码

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

    java面试宝典

    203、编程用JAVA解析XML的方式. 49 204、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? 51 205、EJB与JAVA BEAN的区别? 51 206、EJB的基本架构 51 207、MVC的各个部分都有那些技术来实现?如何实现? 52...

    Java面试宝典-经典

    给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP 126 21、STRUTS的工作流程! 126 22、spring 与EJB的区别!! 126 八. ...

    java面试题大全(2012版)

    给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP 126 21、STRUTS的工作流程! 126 22、spring 与EJB的区别!! 126 八. ...

    json工具jar包(java)

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,被广泛用于Web服务和应用程序之间的数据传输。在Java开发中,处理JSON数据是常见的任务,为此需要特定的库支持。"json工具jar包(java)"是针对Java...

    Java + SSM基于HTML的在线医疗系统(毕业设计、课程设计使用).rar

    【描述】提到的“可完全做为毕业设计、课程设计使用”,表明这个项目适合学生用于完成学业中的实践项目,其设计和功能已经相当成熟,能够满足基本的在线医疗系统需求。"界面美观、功能齐全"意味着该系统不仅在用户...

    企业java相关面试题,包含前端面试资料.zip

    在企业级Java相关的面试中,面试官通常会考察求职者的多方面能力,包括基础理论、实战经验、技术框架的理解和应用以及对前端和数据库的掌握程度。以下是对这些知识点的详细解析: 一、Java基础知识面试题 Java是...

    java面试题(整理)

    ### Java面试题详解 #### 一、Java基础知识 1. **您看过哪些Java方面的书籍...以上是对给定文件中的知识点进行了详细的解释和扩展,涵盖了Java基础知识、Web开发、JavaScript/Ajax、Struts以及Hibernate等多个方面。

    java软件开发简历模板.docx

    【Java软件开发简历模板】是IT领域中针对Java程序员求职时使用的一种标准格式,用于展示个人的专业技能、项目经验和教育背景。以下是对Java软件开发的关键知识点的详细解析: 1. **Java语言特性**: - **简单性**...

    最新Java面试宝典pdf版

    给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP 126 21、STRUTS的工作流程! 126 22、spring 与EJB的区别!! 126 八. ...

    java复习题库

    - Getter和Setter方法: 用于访问Bean的属性。 18. **JSP开发模式**: - JSP + JavaBean: 最简单的模式,适合小型项目。 - JSP + JavaBean + Servlet: 适用于中大型项目,提高了代码的重用性和维护性。 #### 二、...

    java知识点的总结

    8. **DOM编程**:理解和使用DOM解析XML文档,处理和操作XML数据。 9. **Servlet和JSP**:Servlet是Java Web开发的核心,用于处理HTTP请求,JSP则提供了更便捷的视图层开发方式。 10. **AJAX**:异步JavaScript和...

    java从入门到精通笔记

    - **发展方向**: 包括JAVASE(Java Standard Edition,标准版)、JAVAME(Java Micro Edition,小型版)和JAVAEE(Java Enterprise Edition,企业版)。 - **Java语言特点**: - **简单性**: Java简化了许多C++中的...

    java面试宝典2012

    给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 137 19、Jdo是什么? 137 20、什么是spring的IOC AOP 137 21、STRUTS的工作流程! 137 22、spring 与EJB的区别!! 137 八. ...

Global site tag (gtag.js) - Google Analytics