2019独角兽企业重金招聘Python工程师标准>>>

在日常的开发中,偶尔会遇到运行字符串表达式的情况,通常这样的需求会对需求进行进一步分析,然后进行进一步 “特殊化”,最后直接写到硬代码中,这样做的话,就不太好扩展了;也有另外的处理方式是采用 Java 内置的 JavaScript 引擎等运行字符串表达式,但是内置引擎也有弊端,比如频繁运行片段式的字符串的效率非常低,并且与 Java 之间的数据交互比较麻烦,于是,便产生了写一个“字符串表达式计算引擎”的想法...

写的过程其实没想象中那么麻烦,最初版大概在今年 5 月底写好,但是结构比较混乱,写的时候基本上是一边写一边修,最后 if...else...这样的条件以及嵌套太多,以至于自己也无法完全理解,好在逻辑基本完善,运行也没出现意料之外的情况(也许出现了,只是没发现),并且是自己用,所以就没太在意。

前两个星期,又抽空重新整理了一遍,重新梳理了一下结构,扩展了一些功能,重新定义了一下各种符号的 “语义边界”,尽可能保证运算符与 Java 本身运算符一致,逻辑结构也更清晰,不会产生意外情况等。

RunnerUtil 在语法上很大程度参考了 JavaScript 的语法,比如用花括号表示一个键值对“对象”(实际上会被解析成 HashMap),键名不必用单引号或双引号包裹,单引号双引号均表示普通字符串,通过点号(.)和方括号链式取值等。这对于从事 JavaWeb 开发的同学来说,书写起来也比较方便。现在已经实现了绝大部分功能,已实现的功能也经过一定测试,确保能“符合期望”的运行,如果有想法和建议也希望多多的提一下哈。

  • 项目地址: github.com/xua74453185…

基本用法介绍

字符串表达式通过一个叫 RunnerUtil 的静态类运行,可以直接运行得到表达式结果,也可以解析一个表达式后在需要的时候运行,RunnerUtil 主要有以下几个方法:

  • RunnerUtil.run(/* expression */); 直接运行表达式并得到结果;
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run("1 + 1"); // 2
RunnerUtil.run(" 'Hello' + ' ' + 'World!' "); // "Hello World!"
复制代码</pre>
  • RunnerUtil.run(/* expression */, / * data */); 运行含有变量的表达式,后面的 data 是变量将要指向的“值”;
  • RunnerUtil.parseRun(/* expression */); 直接运行“另一种”表达式,并得到结果,如:
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.parseRun("Hello {{   'World!'   }}"); // "Hello World!"
复制代码</pre>

可见 #parseRun 是运行包含“插值语法”的表达式,被包裹的内容被作为一个表达式单独运行;

字符串中可以包含多个插值语法表达式,但不能嵌套和交叉,也可以运行含有变量的表达式。

  • Runner runner = RunnerUtil.parse(/* expression */);

解析一个字符串表达式,得到一个“字符串表达式运行器” —— Runner,然后调用其 run(/ * data */) 方法运行并得到结果。

语法及运算详细介绍

作为一个具有一定“语言特点”的东西,它定义了一些自己的语法、数据类型、运算类型等,但大部分都与 Java 和 JavaScript 兼容,相同符号具有相同或相似的语言意义。

数据类型:

  1. null:这是一个关键字,但因为它符合和变量的定义规则,所以需要注意一下,同样被定义为关键字的还有 true 和 false。
  2. boolean:true 和 false
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" null   "); // null
RunnerUtil.run("   true "); // true
RunnerUtil.run("false"); // false
// 表达式中多余的空格自动忽略
复制代码</pre>
  1. 数字:这里面的数字统一采用 Java 里的 int 和 double 型数据,直接参与运算的也只有是这两种类型,区别就是有没有小数点。
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" 12  "); // 12
RunnerUtil.run(" 12.5 "); // 12.5
// 表示数字必须是连续,中间不能有空格的
// 否则将抛出异常,如
RunnerUtil.run(" 12\. 5"); // 异常
RunnerUtil.run(" 1 2 "); // 异常
复制代码</pre>

表示数字的字符之间应该是连续的,如:25、36.9 等;如果是不连续的会抛出异常,如:2 5、36 .9 等;

  1. 字符串:Java 里的字符串用双引号包裹,在这里还将表示字符的单引号“征用”,双引号单引号包裹的都表示普通字符串的直接值,这样做也是为了书写方便(与 JavaScript 相似),同时也就没有了 char 类型数据啦啦啦……
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" 'abcdef'  "); // "abcdef"
RunnerUtil.run(" \"abcdef\"  "); // "abcdef"
RunnerUtil.run(" 'abc   def'  "); // "abc   def"
复制代码</pre>
  1. List:实际上是 ArrayList,对应 JavaScript 里面的数组。Java 的数组也对应 JavaScript 数组。
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" { } ");
// 总是返回一个空ArrayList

RunnerUtil.run(" {1,2,,4, } ");
// 总是返回一个包含:1、2、null、4 这几项的 ArrayList

// 可以看出最后一个逗号之后如果是结束符号会自动忽略
// 中间的逗号与逗号之间若没有其他非空白符号会插入一个 null 值
复制代码</pre>

  1. Map:实际上是 HashMap,对应 JavaScript 里的对象。同样对应 JavaScript 对象的还有普通 POJO。

Map 对应的是 JavaScript 里的对象,但是在这里 Map 的键可以是这些数据类型:

null、true / false、数字(int / double)、字符串,不能再是其他 Java 对象了

<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" {:} "); // 总是返回一个空 HashMap,
// 注意与空 List 的异同,都是用花括号表示
// 但空 Map 里面需要有一个冒号,否则就是 ListRunnerUtil.run(" {key: 'value'}");
// 总是返回包含一个键值对的 HashMap
// 可以看出,对象的键名是字符串的话可以不用引号包裹
// 但是值必须被包裹
RunnerUtil.run(" {true: 'value'}"); // 键是 true
/** 这里的 true 不是字符串,而是 boolean。* 同样,未被引号包裹的 null、false、数字都是对应类型的数据,而不是字符串* 其他符合变量命名规则的键都是普通字符串,被单引号或双引号包裹的也是*/
RunnerUtil.run(" {'true': 'value', 25: false, 'name': \"张三\"}");
复制代码</pre>

运算支持的类型:

  1. 普通四则混合运算:+、-、*、/、%、()
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" 1 + 1 "); // 2
RunnerUtil.run(" 1 + (3 * 4)) "); // 13
RunnerUtil.run(" 'Hello ' + \"World!\" ");  // "Hello World!"
RunnerUtil.run(" true + false "); // "truefalse"
/** true+false 在 Java 中是不允许的* 但如果是“+”运算的话,这里均作为普通字符串;* 相当于调用了 toString 方法*/
复制代码</pre>
  1. 位运算:&、|、^、<<、>>
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" 1 ^ 1 ");
RunnerUtil.run(" 1 & 1 ");
RunnerUtil.run(" 1 | 1 ");
RunnerUtil.run(" 1 << 1 ");
RunnerUtil.run(" 1 >> 1 ");
复制代码</pre>
  1. 比较运算:>、>=、==、<=、<
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" 1 + 1 == 2 "); // true
RunnerUtil.run(" 1 + 1 < 2 "); // false
复制代码</pre>
  1. 逻辑运算:&&、||、!
<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run("1+1==2 && 5 > 4"); // true
复制代码</pre>
  1. 变量:命名规则与 Java 变量命名规则相同,同时 null、true、false 不能作为变量

表达式中包含变量就代表这个表达式在运行得到结果时需要从外部获取数据,如果不能正确的从数据源读取到数据,运行就会抛出异常;在此我向大家推荐一个架构学习交流裙。交流学习裙号:687810532,里面会分享一些资深架构师录制的视频录像

<pre class="prettyprint hljs kotlin" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run(" 'Hello, ' + name "); // 抛出异常Map data = new HashMap();
data.put("name", "Li Lei!");RunnerUtil.run(" 'Hello, ' + name ", data); // "Hello, Li Lei!"
复制代码</pre>
  1. 链式取值:链式语法与 JavaScript 很相似
<pre class="prettyprint hljs thrift" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">HashMap data = new HashMap(); ArrayList list = new ArrayList();
list.add(true);
list.add(false);
list.add(25);
list.add('隔壁老王'); HashMap map = new HashMap();
map.put("name", "小四");
map.put("index", 2);
map.put(true, "true 是 Boolean 类型作为键"); data.put("list", list);
data.put("map", map); RunnerUtil.run("map.name", data); // "小四"RunnerUtil.run("map['name']", data);
// "小四" (也可以这样取值)RunnerUtil.run("list[ 2 ]", data);
// 25 (索引取值需要用方括号包裹) RunnerUtil.run("list[3]", data);
// "隔壁老王" (索引取值需要用方括号包裹) RunnerUtil.run("list[map.index]", data); // 25
// (这是高级点的用法,方括号包含另一个表达式
// 返回值是一个索引,然后返回索引指向的值)RunnerUtil.run("[true]", data); // "true 是 Boolean 类型作为键"
// 如果不用方括号包括,true 就是一个直接值,返回 true
// 那么问题来了:
// 如果传入的数据不是 Map 或 POJO,而是 List 或数组怎么办呢?
RunnerUtil.run(" [1] ", list); // false
// 啊……唐宗宋祖,略显风骚!// 这种链式语法与 JavaScript 很相似
复制代码</pre>
  1. 运行方法:目前只能运行无参和一个参数的方法,变长参数的方法支持不完善,慎用。
<pre class="prettyprint hljs kotlin" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">这里的数据 data 继续用上一条的 data,具体数据不写了RunnerUtil.run("map.size()", data); // 3
RunnerUtil.run("map.get('name')", data); // "小四"
RunnerUtil.run("map.get('name').length()", data); // 2
RunnerUtil.run("map.name.length()", data); // 2
RunnerUtil.run(" [3].length() ", list); // 4
// 唐宗宋祖,又显风骚!
复制代码</pre>
  1. 运行静态方法: @ ;运行静态方法需要用到“@”符号作为标记。目前也不支持多参数方法调用。

当你打开源码会发现这是一整个独立的工具库,很多方法和 commons-lang 包内容相似(个人认为不是重复造轮子,也有很多不同的和不如的)...,运行静态方法也可以运行这个工具库内的所有工具方法,暂时未将 RunnerUtil 剥离出来,也还不支持自定义的静态方法调用,不过这个工具库所提供的功能

<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">RunnerUtil.run("@System.currentTimeMillis() ");
// 15.....(一个毫秒数)
RunnerUtil.run("@Objects.toString(25) "); // "25"
复制代码</pre>

综上,就是这个工具库所支持的字符串表达式运算了,以上所列举的运算可以嵌套、连接、但是不能交叉的进行运算。接下来要做的是加入的功能是多参数方法调用,希望对大家的日常开发有所帮助,也希望大家给点意见,如出现 BUG 一定在最快的时间内修改,谢谢大家啦啦啦!!

转载于:https://my.oschina.net/u/3972077/blog/2962653

分享Java 中如何运行字符串表达式?相关推荐

  1. JAVA中用于处理字符串的 三兄弟

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! JAVA ...

  2. 如何在Java中转义JSON字符串-Eclipse IDE技巧

    在Java应用程序中工作或进行JSON解析时,通常很常见的做法是从某些资源(例如RESTful Web服务)中复制粘贴JSON字符串,然后使用Jackson库解析JSON. 这是测试和学习Java中解 ...

  3. Java中怎么定义字符串?Java基础

    字符串是 Java 中特殊的类,使用方法像一般的基本数据类型,被广泛应用在 Java 编程中.Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个 String 类来创建和操作字符串 ...

  4. Java中普通字符串转json,老司机帮您java中如何将字符串转成json

    电脑现已成为我们工作.生活和娱乐必不可少的工具了,在使用电脑的过程中,可能会遇到java中如何将字符串转成json的问题,如果我们遇到了java中如何将字符串转成json的情况,该怎么处理怎么才能解决 ...

  5. Java中如何将字符串反转

    目录 一.Java中如何将字符串反转 1.利用 StringBuffer 或 StringBuilder 的 reverse() 成员方法 代码演示: 运行结果: 2.利用 String 的 toCh ...

  6. Java中如何组装字符串

    1.Java中如何组装字符串? 相信很多做Java开发的同学**,第一反应肯定是拼接字符串**.是呀,Java中拼接字符串太容易了 直接用+拼接就行了. 比如 String name = " ...

  7. 在java中如何把字符串转换成时间格式?

    在java中如何把字符串转换成时间格式? 检举 | 2007-11-28 17:26 提问者:baixiao429 | 悬赏分:20 | 浏览次数:6645次 有这样一个字符串:"20070 ...

  8. 在 Java 中检查空字符串或空白字符串

    1. 简介 在本教程中,我们将讨论一些在 Java 中检查空字符串或空白字符串的方法.有一些母语方法,以及几个库. 2. 空与空白 当然,知道字符串何时为空或空白是很常见的,但让我们确保我们的定义在同 ...

  9. java中把一个字符串中大写字母转换为小写,小写字母转换为大写

    java中把一个字符串中大写字母转换为小写,小写字母转换为大写 观看提示: 这里提供2中思维,但是第一种是正确的,第二种是错误的:第二种的思维可以了解了解,但是需要注意的是如果某个字符串定义为Stri ...

最新文章

  1. Python实例介绍正则化贪心森林算法(附代码)
  2. 将客户端图片保存到数据库中的方法
  3. 数据链路层、交换机内容整合
  4. 【今晚9点】:对话袁荣喜——一名C程序员的打怪之路
  5. 操作系统内存管理问题集锦
  6. 关于云原生需要了解什么
  7. 商标45类分类表明细表_2019版注册商标分类表,商标注册45类范围明细
  8. TensorFlow GPU配置
  9. 【Qt教程】2.3 - Qt5 控件 - 按钮组(QPushButton、QToolButton、QRadioButton、QCheckBox)资源编辑器导入资源
  10. aes256 php,如何在PHP中进行AES256解密?
  11. 3款电脑必备的常用运行库合集,你值得拥有
  12. synaptics触摸板_使用Dell Synaptics触摸板修复Firefox滚动问题
  13. 入门Struts1第一讲——Struts1入门就这么简单
  14. Python修改图片格式
  15. ET1100和PHY的总结
  16. Docker基础之containerd的shim
  17. 银行排队信息预测系统数学建模
  18. GBase 8d证书查看
  19. 记录一次学习通接口分析
  20. 一个团队从无到有再到高效的管理方式

热门文章

  1. Centos 7 密码重置
  2. iOS 分组索引和索引分区
  3. 每日一题_JavaScript.利用Js操作frameset框架集对象实现购物车?
  4. (1)-使用json所要用到的jar包下载
  5. 汇编实现时钟设置代码理解
  6. 3款强大的BootStrap的可视化制作工具推荐
  7. http://longshuai2007.blog.163.com/blog/static/1420
  8. CocoaChina2013开发者大会演讲稿-主会场-陈昊芝
  9. OSPF基本概念单与区域配置
  10. JavaScript权威指南笔记 - 1