论坛首页 Java企业应用论坛

被Groovy震的第一下

浏览 20990 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (7)
作者 正文
   发表时间:2009-03-20   最后修改:2009-03-20
Groovy比Python和Ruby更吸引我的地方全部来自于它的语法风格。
0 请登录后投票
   发表时间:2009-03-20  
看下面的代码:
class Module {
    static def abc = {return "打印测试"}
    static def hij = {person->return person.name}
}
class Person {String name;}

def d = new Person(name:"123");
d.metaClass.abc = {->
   Module.abc()
}
d.metaClass.hij = {person->
   Module.hij(person)
}
println d.abc()
println d.hij(d)

0 请登录后投票
   发表时间:2009-03-20  
就算是动态语言也应该有一套严格的语法。
就如前几楼说的URL获取内容一样。
过于灵活会让人觉得无所适从。
Php中有 fopen,file_get_contents,curl等可以用来获取远程内容。
但各有特点,适用于不同情况。
如果像Js那样偶尔再蹦出几个hack那就太令人抓狂了。
0 请登录后投票
   发表时间:2009-03-20  
Bernard 写道
就算是动态语言也应该有一套严格的语法。
就如前几楼说的URL获取内容一样。
过于灵活会让人觉得无所适从。
Php中有 fopen,file_get_contents,curl等可以用来获取远程内容。
但各有特点,适用于不同情况。
如果像Js那样偶尔再蹦出几个hack那就太令人抓狂了。


groovy保持java的样子,模仿动态语言语法,同时也包装了一些java hack……
虽说编译成静态,但是动态语法大量使用反射泛型和动态代理和动态装载,速度比正常java慢很多,与解释执行相比也体现不出编译的效率优势。

看看《java解惑》,java里令人抓狂的陷阱也不少。

日常说话聊天比动态语言灵活多了,也无所适从么?
0 请登录后投票
   发表时间:2009-03-20  
manyinjin 写道
JohnnyJian 写道

这还不是最简单的,试试:
Java代码 println new URL("http://manyinjin.iteye.com").text  println new URL("http://manyinjin.iteye.com").text


呵呵,试了一下,真的很cool 
像这个,
new File( 'd:\\tmp\\test.log' ).eachLine{ line ->
    if(line =~ ".*127.0.0.1.*") println line;
}

真的很简单。



perl
python里面基本都是这样吧

为啥痴迷语法呢
0 请登录后投票
   发表时间:2009-03-20  
package com.lab.eqpt.web.admin;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springside.core.web.StrutsEntityAction;

import com.common.UC2GB;
import com.common.UtilDao;
import com.common.Utils;
import com.lab.eqpt.service.EqptBookManager;
import com.lab.eqpt.service.EqptBookTaskManager;
import com.lab.model.CodeBookStep;
import com.lab.model.EqptBook;
import com.lab.model.EqptBookApproveTime;
import com.lab.model.EqptBookBookTime;
import com.lab.model.EqptBookFinalTime;
import com.lab.model.EqptBookTime;
import com.lab.model.EqptUseRecord;
import com.lab.model.InfoGuideFile;
import com.lab.model.ScLoginUser;

public class EqptBookInfoStatisticsAction extends StrutsEntityAction<EqptBook, EqptBookManager>{
	private EqptBookManager eqptBookManager;
	private EqptBookTaskManager eqptBookTaskManager;
	public void setEqptBookTaskManager(EqptBookTaskManager eqptBookTaskManager){
		this.eqptBookTaskManager = eqptBookTaskManager;
	}
	public void setEqptBookManager(EqptBookManager eqptBookManager) {
		this.eqptBookManager = eqptBookManager;
	}
	protected void onInitForm(ActionForm form,
            HttpServletRequest request,EqptBook  eqptBook)
	{
		String bookMan = request.getParameter("bookMan");
		String taskFlag = request.getParameter("taskFlag");
		if (Utils.isNotEmpty(bookMan))request.setAttribute("bookMan",bookMan);
		if (eqptBook.getEqptBookBookTimes() != null)
		{
			Iterator it = eqptBook.getEqptBookBookTimes().iterator();
			if(it.hasNext())
			{
				EqptBookBookTime eqptBookBookTime = (EqptBookBookTime)it.next();
				request.setAttribute("eqptBookBookTimes", eqptBookBookTime);
			}
		}
		EqptBookApproveTime eqptBookApproveTime = null;
		EqptBookFinalTime eqptBookFinalTime = null;   
     	if(eqptBook.getEqptBookFinalTimes()!=null)
		{
     		//向页面传值
			List bookTimes = new ArrayList();
			for(Iterator iter = eqptBook.getEqptBookFinalTimes().iterator(); iter.hasNext();) 
			{
				EqptBookFinalTime bookFinalTime = (EqptBookFinalTime)iter.next();
				String startTime = Utils.getFmtDate(bookFinalTime.getStartTime(), "yyyy-MM-dd HH:mm");
				String endTime = Utils.getFmtDate(bookFinalTime.getEndTime(), "yyyy-MM-dd HH:mm");
				
				EqptBookTime eqptBookTime = new EqptBookTime();
				eqptBookTime.setFinFlag(bookFinalTime.getFinFlag());
				eqptBookTime.setDate(startTime.substring(0,11));
				eqptBookTime.setStartHour(startTime.substring(11,13));
				eqptBookTime.setStartMinute(startTime.substring(startTime.length()-2));
				eqptBookTime.setEndHour(endTime.substring(11,13));
				eqptBookTime.setEndMinute(endTime.substring(startTime.length()-2));
				
				bookTimes.add(eqptBookTime);
			}
			request.setAttribute("bookTimes", bookTimes);    			
		}
     	//多时间段取值
     	List eqptBookFinalTimes = new ArrayList();
     	if(eqptBookFinalTime==null&&eqptBook.getEqptBookApproveTimes() != null)
     	{	
     		for(Iterator iter1=eqptBook.getEqptBookApproveTimes().iterator(); iter1.hasNext();) {
     			eqptBookApproveTime = (EqptBookApproveTime)iter1.next();
     			eqptBookFinalTime = new EqptBookFinalTime();
     			eqptBookFinalTime.setStartTime(eqptBookApproveTime.getStartTime());
     			eqptBookFinalTime.setEndTime(eqptBookApproveTime.getEndTime());     
     			eqptBookFinalTimes.add(eqptBookFinalTime);
     		}
     	}
     	String[] fileNames = null;
     	String[] fileUrls = null;
     	ArrayList<InfoGuideFile> reportGuideFiles = new  ArrayList<InfoGuideFile>();
     	EqptUseRecord eqptUseRecord = null;
		if(eqptBook.getEqptUseRecords()!=null)
		{
			//向页面传值
			List bookTimes = new ArrayList();
			for(Iterator iter = eqptBook.getEqptBookFinalTimes().iterator(); iter.hasNext();) 
			{
				EqptBookFinalTime bookFinalTime = (EqptBookFinalTime)iter.next();
				String startTime = Utils.getFmtDate(bookFinalTime.getStartTime(), "yyyy-MM-dd HH:mm");
				String endTime = Utils.getFmtDate(bookFinalTime.getEndTime(), "yyyy-MM-dd HH:mm");
				
				EqptBookTime eqptBookTime = new EqptBookTime();
				eqptBookTime.setFinFlag(bookFinalTime.getFinFlag());
				eqptBookTime.setDate(startTime.substring(0,11));
				eqptBookTime.setStartHour(startTime.substring(11,13));
				eqptBookTime.setStartMinute(startTime.substring(startTime.length()-2));
				eqptBookTime.setEndHour(endTime.substring(11,13));
				eqptBookTime.setEndMinute(endTime.substring(startTime.length()-2));
				
				bookTimes.add(eqptBookTime);
			}
			request.setAttribute("bookTimes", bookTimes);
			
			Iterator i = eqptBook.getEqptUseRecords().iterator();
			if(i.hasNext())
			{
				eqptUseRecord = (EqptUseRecord)i.next();
				Date enterDate = eqptUseRecord.getEnterDate();
				Date today = new Date();
				if(((today.getTime() - enterDate.getTime())/(60L*60L*24L*1000L)) > 15) 
				{
					request.setAttribute("expired", 1);
				}
				request.setAttribute("eqptUseRecordForm", eqptUseRecord);
				if(Utils.isNotEmpty(eqptUseRecord.getReport())&&Utils.isNotEmpty(eqptUseRecord.getReporturl()))
				{
				  fileNames = eqptUseRecord.getReport().split(",");
				  fileUrls = eqptUseRecord.getReporturl().split(",");
				  for(int j = 0;j < fileNames.length;j++)
				  {
					  InfoGuideFile reportGuideFile = new InfoGuideFile();
					  reportGuideFile.setFileName(fileNames[j]);
					  reportGuideFile.setFileUrl(fileUrls[j]);
					  reportGuideFiles.add(reportGuideFile);
				  }
				}
			}
		}
		if(eqptUseRecord==null)
		{
			//向页面传值
			List bookTimes = new ArrayList();
			for(Iterator iter = eqptBookFinalTimes.iterator(); iter.hasNext();) 
			{
				EqptBookFinalTime bookFinalTime = (EqptBookFinalTime)iter.next();
				
				String startTime = Utils.getFmtDate(bookFinalTime.getStartTime(), "yyyy-MM-dd HH:mm");
				String endTime = Utils.getFmtDate(bookFinalTime.getEndTime(), "yyyy-MM-dd HH:mm");
				
				EqptBookTime eqptBookTime = new EqptBookTime();
				eqptBookTime.setFinFlag(bookFinalTime.getFinFlag());
				eqptBookTime.setDate(startTime.substring(0,11));
				eqptBookTime.setStartHour(startTime.substring(11,13));
				eqptBookTime.setStartMinute(startTime.substring(startTime.length()-2));
				eqptBookTime.setEndHour(endTime.substring(11,13));
				eqptBookTime.setEndMinute(endTime.substring(startTime.length()-2));
				
				bookTimes.add(eqptBookTime);
			}
			request.setAttribute("bookTimes", bookTimes);
			eqptUseRecord = new EqptUseRecord();
			eqptUseRecord.setSelfFee(new Double(0));
			eqptUseRecord.setExtFee(new Double(0));
			request.setAttribute("eqptUseRecordForm", eqptUseRecord);
		}
		request.setAttribute("taskFlag", taskFlag);
		request.setAttribute("reportGuideFiles", reportGuideFiles);
	}
    @SuppressWarnings("unchecked")
	public ActionForward saveEqptBook(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
	{
    	ScLoginUser scLoginUser = (ScLoginUser)request.getSession().getAttribute("loginUser");
    	String bookId = request.getParameter("bookId");
    	String step = request.getParameter("step");
     	UtilDao utilDao = (UtilDao) WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext()).getBean("utilDao");
    	utilDao.deleteRecord("eqpt_book_final_time", "book_id",bookId);
    	EqptBook eqptBook = eqptBookManager.get(EqptBook.class,bookId);
    	//处理完成登记
    	Enumeration enu = request.getParameterNames();
		int temp=0, len=0;
		while(enu.hasMoreElements()) {
			String condition = String.valueOf(enu.nextElement());
			if(condition.startsWith("t_")) {
				temp = Integer.parseInt(condition.substring(condition.length()-1));
			}
			if(temp > len) {
				len = temp;
			}
		}
		String recordId = request.getParameter("t_recordId1");
		String testUserName = "";
		String enterName = "";
		for(int i=1; i<=len; i++) {
			String startDate = request.getParameter("t_startDate"+i);
			String endDate = request.getParameter("t_endDate"+i);
			String startHour = request.getParameter("t_startHour"+i);
			String startMinute = request.getParameter("t_startMinute"+i);
			String endHour = request.getParameter("t_endHour"+i);
			String endMinute = request.getParameter("t_endMinute"+i);
			Date startTime = Utils.getDate(startDate,startHour,startMinute);
			Date endTime = Utils.getDate(startDate, endHour, endMinute);
			testUserName += request.getParameter("t_testUserName"+i) + ",";
			
			if(startTime != null && endTime !=null) {
				EqptBookFinalTime eqptBookFinalTime = new EqptBookFinalTime();
				if(step.equals("3")) eqptBookFinalTime.setFinFlag(Long.valueOf(1));
				eqptBookFinalTime.setEndTime(endTime);
				eqptBookFinalTime.setStartTime(startTime);
				eqptBookFinalTime.setEqptBook(eqptBook);
				eqptBook.getEqptBookFinalTimes().add(eqptBookFinalTime);
			}
			enterName = request.getParameter("t_enterName"+i);
	    }
    	
    	//添加使用记录
		EqptUseRecord eqptUseRecord = new EqptUseRecord();
	    if(Utils.isNotEmpty(recordId))
	    {
	    	eqptUseRecord = this.eqptBookManager.get(EqptUseRecord.class, recordId);
	    }
	    eqptUseRecord.setTestUserName(testUserName);
	    ////文件上传处理
        String[] del_id = request.getParameterValues("del_id");
	    deleteFile(eqptUseRecord,del_id, request.getRealPath(""));// 1.首先删除磁盘文件
	    String path = "/uploads/report/";
	    String fileNames = eqptUseRecord.getReport();
	    String fileUrls = eqptUseRecord.getReporturl();
		String file_num = request.getParameter("file_num");
		if (file_num != null) 
		{
			if(Utils.isEmpty(fileNames))
			{
				fileNames = "";
			}
			if(Utils.isEmpty(fileUrls))
			{
				fileUrls = "";
			}
			for (int i = 1; i <= Integer.parseInt(file_num); i++) 
			{
			    String reportFile[] = uploadFile(form, request, "attachfile" + i,path);
				if (reportFile != null) 
				{
					fileNames += reportFile[0]+",";
					fileUrls += path + reportFile[1]+",";
				}
            }
		}
		eqptUseRecord.setReport(fileNames);
		eqptUseRecord.setReporturl(fileUrls);
		 
		///////////////////////////////////////////////////////////////////////
	    String memo = request.getParameter("memo");
	    eqptUseRecord.setMemo(memo);
	    String selfFeeStr = request.getParameter("selfFee");
	    if(!Utils.isNotEmpty(selfFeeStr))
	    {
	    	selfFeeStr = "0";
	    }
	    String extFeeStr = request.getParameter("extFee");
	    if(!Utils.isNotEmpty(extFeeStr))
	    {
	    	extFeeStr = "0";
        }
	    String resultMessage = "";
	    String url ="";
        //在这里需要处理从当年的基金当中扣除该补贴金额
	    double oldExtFee = 0;
	    double oldSelfFee = 0;
	    if(Utils.isNotEmpty(recordId))
	    {
	    	oldExtFee = eqptUseRecord.getExtFee().doubleValue();
	    	oldSelfFee = eqptUseRecord.getSelfFee().doubleValue();
	    }
	    resultMessage = this.eqptBookManager.extFeeProcess(new Date(),Double.valueOf(selfFeeStr).doubleValue(),
	    		Double.valueOf(extFeeStr).doubleValue(),oldSelfFee,oldExtFee);
	    if(Utils.isNotEmpty(resultMessage))
	    {
	    	url = "admin.eqptBookInfoStatistics.do?method=edit&bookId="+bookId;
	    }
	    else
	    {
		    eqptUseRecord.setSelfFee(new Double(selfFeeStr));
		    eqptUseRecord.setExtFee(new Double(extFeeStr));
	    }
	    if(Utils.isEmpty(recordId))
	    {
          eqptUseRecord.setEnterDate(new Date());
	    }
	    eqptUseRecord.setScLoginUserByEnterUser(scLoginUser);
	    eqptUseRecord.setEqptBook(eqptBook);
	    eqptBook.getEqptUseRecords().add(eqptUseRecord);
	    //接着修改预约记录的状态
	    if(!"bookWarn".equals(request.getParameter("operator"))&&!"stop".equals(request.getParameter("operator"))){
    	    eqptBook.setCodeBookStep(eqptBookManager.get(CodeBookStep.class,step));
	    }
    	//utilDao.deleteRecord("eqpt_use_record", "book_id", eqptBook.getBookId());
		if("bookWarn".equals(request.getParameter("operator"))){
			eqptBook.getScLoginUserByLoginId().setWarnFlag(eqptBook.getScLoginUserByLoginId().getWarnFlag()+1);
			eqptBook.getScLoginUserByLoginId().setWarnStatus("000");
			eqptBook.setReleaseFlag("1");
			eqptBook.setCodeBookStep(eqptBookManager.get(CodeBookStep.class,"5"));
		}
		if("stop".equals(request.getParameter("operator"))) {
			eqptBook.setReleaseFlag("1");
			eqptBook.setCodeBookStep(eqptBookManager.get(CodeBookStep.class,"6"));
		}
    	if(Utils.isEmpty(resultMessage))
    	{
    		resultMessage = "用户使用记录操作成功!";
    		url = "admin.eqptBookInfo.do?method=list";
    		if(Utils.isEmpty(recordId))
    		{
    			this.eqptBookTaskManager.statisticsEqptBookTask(scLoginUser, eqptBook);
    		}
    	}
    	eqptBookManager.save(eqptBook);
     	request.setAttribute("resultMessage", resultMessage);
		String taskFlag = request.getParameter("taskFlag");
		if (Utils.isNotEmpty(taskFlag)) url = "show.eqptBookTask.do?taskFlg=0";     	
     	request.setAttribute("url", url);
     	
		return mapping.findForward("success");
	}
    /*
	 * 下载文件
	 * 
	 */
	public ActionForward downFile(ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) {
		 String error="";
		 String fileUrl=request.getParameter("fileUrl");
	     String fileName = request.getParameter("fileName");
         try{ 
        	 File file=new File(request.getRealPath("")+fileUrl);        	 
        	 if(file.exists()){//文件存在时
        		 response.setContentType ("application/OCTET-STREAM;charset=GBK");	
        		 String downName=UC2GB.toUni(fileName);
        		 response.setHeader ("Content-Disposition", "attachment;filename=\""+downName+"\"");
        		
        		 FileInputStream in = new FileInputStream(file); 
	             OutputStream outstream=response.getOutputStream(); 
	             
	             byte[] bytes=new byte[1024];
	             int len=0;
	             while((len=in.read(bytes))!=-1){
	                   outstream.write(bytes,0,len);
	                  } 
	             in.close(); 
	             outstream.close();          
        	 }else{//文件不存在时
        		 error="文件【"+fileName+"】不存在";
        		 request.setAttribute("error",error);
                 return mapping.findForward("downFile");
        	 }
         }catch(IOException e){ 
        	 error="文件下载出现错误,请重新下载!";
             request.setAttribute("error",error);
             return mapping.findForward("downFile");
         } 

          return null;
    }
	/**
	 * 文件上传的处理.
	 */
	private String[] uploadFile(ActionForm form, HttpServletRequest request,
			String inputName, String path) {

		if (!(form instanceof DynaBean))
			return null;

		Object imgObj = ((DynaBean) form).get(inputName);
		if (!(imgObj instanceof FormFile))
			return null;

		FormFile file = (FormFile) imgObj;		
		if (StringUtils.isBlank(file.getFileName()))
			return null;

		try {

			InputStream in = file.getInputStream();
			String filename=file.getFileName();//上传文件名
			String filePath = request.getSession().getServletContext()
					.getRealPath("/");
			OutputStream out = new FileOutputStream(filePath + path
					+ file.getFileName());

			int bytesRead;
			byte[] buffer = new byte[8192];
			while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {
				out.write(buffer, 0, bytesRead);
			}
			out.close();
			in.close();
			//修改文件名
			int index=filename.lastIndexOf(".");
			String name=filename.substring(0,index);//原文件名
			String suffix=filename.substring(index+1,filename.length());//后缀
			//目标文件名
			String destFileName = name+"_"+DateFormatUtils.format(new Date(), "yyyyMMdd")+ 
			org.apache.commons.lang.StringUtils.leftPad(Math.round(Math.random() * 1000)+ "", 4, '0')+"."+suffix;
			
			String sourceFileName=filePath+"/"+path+"/"+filename;
			String destinationFileName = request.getSession()
					.getServletContext().getRealPath(
							"/" + path + "/" + destFileName);			
	        File sourceFile=new File(sourceFileName);
	        File destFile=new File(destinationFileName);
	        sourceFile.renameTo(destFile);
	        String[] array={filename,destFileName};
	         
			return array;

		} catch (Exception e) {
			log.error("文件上传处理出错", e);
			return null;
		}
	}

	// 删除磁盘文件
	public void deleteFile(EqptUseRecord eqptUseRecord,String[] delFileUrls, String path) {
     	if (delFileUrls != null && delFileUrls.length > 0) 
     	{
     		for (int i = 0; i < delFileUrls.length; i++) 
     		{
				File file = new File(path + delFileUrls[i]);
				if (file.exists())
					file.delete();
			}
			if(Utils.isNotEmpty(eqptUseRecord.getReport())&&Utils.isNotEmpty(eqptUseRecord.getReporturl()))
			{
				String[] fileNames = eqptUseRecord.getReport().split(",");
				String[] fileUrls = eqptUseRecord.getReporturl().split(",");
				String report = "";
				String reportUrl = "";
				for(int i = 0;i<fileUrls.length;i++)
				{
					if(!this.hasFileUrl(fileUrls[i], delFileUrls))
					{
						report += fileNames[i]+",";
						reportUrl += fileUrls[i]+",";
					}
				}
				eqptUseRecord.setReport(report);
				eqptUseRecord.setReporturl(reportUrl);
			}
        }
	}
	private boolean hasFileUrl(String fileUrl,String[] delFileUrls)
	{
		boolean result = false;
		if(delFileUrls!=null)
		{
			for(String delFileUrl:delFileUrls)
			{
				if(delFileUrl.equals(fileUrl))
				{
					result = true;
					break;
				}
			}
		}
		return result;
	}
}
0 请登录后投票
   发表时间:2009-03-21  
night_stalker 写道
Bernard 写道
就算是动态语言也应该有一套严格的语法。
就如前几楼说的URL获取内容一样。
过于灵活会让人觉得无所适从。
Php中有 fopen,file_get_contents,curl等可以用来获取远程内容。
但各有特点,适用于不同情况。
如果像Js那样偶尔再蹦出几个hack那就太令人抓狂了。


groovy保持java的样子,模仿动态语言语法,同时也包装了一些java hack……
虽说编译成静态,但是动态语法大量使用反射泛型和动态代理和动态装载,速度比正常java慢很多,与解释执行相比也体现不出编译的效率优势。

看看《java解惑》,java里令人抓狂的陷阱也不少。

日常说话聊天比动态语言灵活多了,也无所适从么?


你的日常用语很好么,怎么让人觉得这么反感。
0 请登录后投票
   发表时间:2009-03-21  
xmpp 写道
看下面的代码:
class Module {
    static def abc = {return "打印测试"}
    static def hij = {person->return person.name}
}
class Person {String name;}

def d = new Person(name:"123");
d.metaClass.abc = {->
   Module.abc()
}
d.metaClass.hij = {person->
   Module.hij(person)
}
println d.abc()
println d.hij(d)


Groovy 1.6支持更简单的mixin:
class Person { String name }

@Category(Person)
class Module {
    def abc() { 'abc' }
    def hij() { name }
}

def p = new Person(name: '123')
p.metaClass.mixin Module
println p.abc()
println p.hij()
0 请登录后投票
   发表时间:2009-03-21  
看Perl代码会更让你震
0 请登录后投票
   发表时间:2009-03-22  
语法嘛,一切皆表象啊~~~~

看看有那么多牛人发明各种动态语言,特别这两年跟爆炸似的,然而有几个“实现良好"的互联网大型应用,或者企业级应用是跑在这些语言上面的呢?

看看每年的程序语言排行就明白了!这些排行直接说明使用各种语言人数的多少,间接说明企业招聘岗位的多少,从而也能看出在各个行业中,这些语言使用情况的多少。

发明这些语言的人不可谓不聪明,其中的原因值得思考!!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics