util 工具模块
util 工具模块
util 是一组偏底层、偏通用的小工具,主要解决 4 类事情:
- 把值格式化成更适合日志看的字符串
- 判断一个值到底是不是数组、函数、数字、对象
- 做简单对象扩展
- 在 Java 对象、Java 数组、JS 对象之间来回桥接
它不是“必须先学会才能写脚本”的模块,但一旦你开始写复杂一点的调试脚本、桥接脚本、通用库脚本,这组 API 会很顺手。
先记住这 10 条
util.format()是最像 Node.jsutil.format()的这一组。util.inspect()很适合打印复杂对象,比直接String(obj)有用得多。util.extend(target, source)既支持普通对象合并,也支持构造函数原型继承那套写法。util.isNull()和util.isUndefined()是两回事,别混。util.isNullOrUndefined()不传参数时也会返回true。util.java.instanceOf(obj, clazz)适合判断“这是不是某个 Java 类的实例”。util.java.array(type, length)会创建 Java 数组,不是 JS 数组。util.java.toJsArray(...)只能吃 Java 数组、JavaIterable、Kotlin 集合,普通对象不行。util.java.objectToMap(obj)是把 JS 可枚举属性转成 JavaMap,不是把任意 Java 对象字段全量反射出来。util.java.mapToObject(map)是把 JavaMap转成普通 JS 对象。
util.format(...args)
作用
按格式串拼接文本。
返回值
string
支持的占位符
| 占位符 | 作用 | 说明 |
|---|---|---|
%s | 字符串 | 取 toString() 结果 |
%d | 整数 | 转数字后按整数输出 |
%i | 整数 | 和 %d 类似 |
%f | 浮点数 | 转数字后按浮点输出 |
%j | JSON | 会尝试做 JSON 序列化,失败时返回 [Circular] |
%o | 对象 | 用较深层级做 inspect |
%O | 对象 | 用默认较浅层级做 inspect |
%% | 百分号 | 输出一个 % |
真实规则
- 如果第一个参数不是字符串格式串,就会退化成“把所有参数按空格拼起来”。
- 多余的参数不会丢掉,会追加到结尾。
- 占位符不够时,剩余值会按普通文本拼接。
示例
log(util.format("uid=%d name=%s", 1001, "demo"));
log(util.format("payload=%j", { a: 1, b: true }));
log(util.format("obj=%o", {
user: { id: 1, name: "demo" },
enabled: true
}));
%o 和 %O 的区别
当前实现里:
%o:inspect深度大约按4%O:inspect深度大约按2
所以 %o 更适合看深一点的结构。
util.inspect(value, options?)
作用
把复杂值格式化成更适合调试阅读的字符串。
返回值
string
options 写法一:对象
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
showHidden | boolean | false | 是否尽量包含更多属性 id |
depth | number | null | 2 | 递归层级;传 null 表示不限制 |
colors | boolean | false | 是否输出 ANSI 颜色转义码 |
customInspect | boolean | true | 当前实现里会被记录,但没有再扩展出单独的自定义 inspect 钩子 |
options 写法二:兼容参数位
也支持下面这种老式写法:
util.inspect(obj, showHidden, depth, colors);
对应顺序是:
showHiddendepthcolors
示例
const value = {
user: {
id: 1,
profile: {
name: "demo",
tags: ["a", "b", "c"]
}
}
};
log(util.inspect(value));
log(util.inspect(value, { depth: 4 }));
depth 怎么理解
| 取值 | 效果 |
|---|---|
0 | 只看当前层 |
1 | 再展开一层 |
2 | 默认值 |
| 更大数字 | 展开更多层 |
null | 不限制层级 |
colors 要不要开
如果你只是把结果打到普通日志里,colors: true 输出的是 ANSI 颜色码文本,不一定每个显示环境都真能渲染颜色,所以通常:
- 普通脚本日志:
false - 明确知道接收端支持 ANSI:再开
true
util.extend(target, source)
作用
扩展目标对象,或者做构造函数继承桥接。
返回值
通常返回 target 本身。
用法一:普通对象合并
const base = { a: 1 };
const extra = { b: 2, c: 3 };
util.extend(base, extra);
log(JSON.stringify(base)); // {"a":1,"b":2,"c":3}
用法二:构造函数继承
如果你传的是两个函数 / 构造器:
function Parent() {}
Parent.prototype.say = function () {
return "hello";
};
function Child() {}
util.extend(Child, Parent);
const c = new Child();
log(c.say());
当前实现会做这几件事:
- 拿到
Parent.prototype - 让
Child.prototype继承它 - 把
constructor指回Child - 挂一个
Child.super_ = Parent
什么时候别滥用
它不是深拷贝,也不是复杂合并器,所以:
- 适合简单属性扩展
- 不适合拿来做复杂配置合并
类型判断组
下面这些方法的返回值全都是 boolean。
util.isArray(value)
会判定为 true 的情况
- JS 数组
- Java 数组
- Kotlin / Java 传进来的真正数组对象
- JS 里的
List包装成的数组结构
示例
log(util.isArray([1, 2, 3]));
log(util.isArray(util.java.array("int", 3)));
util.isBoolean(value)
作用
判断是否为布尔值。
示例
log(util.isBoolean(true));
log(util.isBoolean(false));
log(util.isBoolean("true")); // false
util.isDate(value)
作用
判断是否为日期类值。
当前会覆盖的常见类型
java.util.Datejava.util.Calendarjava.time.*里实现Temporal的类型- JS 侧 className 为
Date的对象
示例
const DateClass = importClass("java.util.Date");
log(util.isDate(new DateClass()));
util.isError(value)
作用
判断是否为错误对象。
当前会判定为 true 的情况
- Java / Kotlin 异常对象
- JS className 为
Error的对象
示例
try {
throw new Error("demo");
} catch (err) {
log(util.isError(err));
}
util.isFunction(value)
作用
判断是否为函数。
说明
它既认普通 JS function,也认 Rhino / BaseFunction 包装出来的函数对象。
示例
log(util.isFunction(function () {}));
log(util.isFunction(console.log));
util.isNull(value)
作用
只判断“是不是 null”,不包含 undefined。
示例
log(util.isNull(null)); // true
log(util.isNull(undefined)); // false
util.isNullOrUndefined(value)
作用
判断是不是 null 或 undefined。
特别规则
如果你一个参数都不传,它也会返回 true。
示例
log(util.isNullOrUndefined(null));
log(util.isNullOrUndefined(undefined));
log(util.isNullOrUndefined());
util.isNumber(value)
作用
判断是否为数字。
示例
log(util.isNumber(123));
log(util.isNumber(1.25));
log(util.isNumber("123")); // false
util.isObject(value)
作用
判断是不是“对象型值”。
当前排除的类型
- 函数
- 字符串
- 数字
- 布尔值
CharSequence
所以它更接近“非原始值对象”。
示例
log(util.isObject({ a: 1 }));
log(util.isObject(new java.util.HashMap()));
util.isPrimitive(value)
作用
判断是不是原始值。
当前大致会算作 primitive 的情况
undefinednull- 字符串
- 数字
- 布尔值
示例
log(util.isPrimitive("abc"));
log(util.isPrimitive(123));
log(util.isPrimitive({})); // false
util.isRegExp(value)
作用
判断是否为正则。
示例
log(util.isRegExp(/abc/));
util.isString(value)
作用
判断是否为字符串。
当前会覆盖的情况
- JS 字符串
- Java
String CharSequence
示例
log(util.isString("demo"));
util.isUndefined(value)
作用
判断是否为 undefined。
特别规则
如果你不传参数,它也会返回 true。
示例
log(util.isUndefined(undefined));
log(util.isUndefined());
util.java
这是 util 下面专门处理 Java 互操作的一组子 API。
util.java.instanceOf(obj, clazz)
作用
判断某个对象是不是某个 Java 类的实例。
参数
| 参数 | 类型 | 说明 |
|---|---|---|
obj | any | 要判断的对象 |
clazz | Class | 类代理 | 字符串类名 | 目标 Java 类型 |
返回值
boolean
示例
const ArrayList = importClass("java.util.ArrayList");
const list = new ArrayList();
log(util.java.instanceOf(list, "java.util.List"));
log(util.java.instanceOf(list, ArrayList));
util.java.array(type, length?)
作用
创建 Java 数组。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
type | Class | 类代理 | 字符串类型名 | 无 | 必填 |
length | number | 0 | 小于 0 会按 0 处理 |
返回值
Java 数组对象,不是 JS 数组。
说明
- 如果你传的是数组类型,内部会取组件类型再创建。
- 如果类型解析失败,会直接抛错。
常见写法
const intArray = util.java.array("int", 3);
const stringArray = util.java.array("java.lang.String", 2);
失败行为
类型无效时会抛:
util.java.array requires a Java type
util.java.toJsArray(value, nullListToEmptyArray?)
作用
把 Java 数组 / Java Iterable / Kotlin 集合转成 JS 数组。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | Java 数组 / Iterable / 集合 | 无 | 普通对象不行 |
nullListToEmptyArray | boolean | false | 为 true 时,null 输入会返回空数组 |
返回值
Array 或 null
返回规则
| 输入 | nullListToEmptyArray=false | nullListToEmptyArray=true |
|---|---|---|
null | null | [] |
| Java 数组 | JS 数组 | JS 数组 |
| Java / Kotlin 集合 | JS 数组 | JS 数组 |
示例
const arr = util.java.array("java.lang.String", 2);
arr[0] = "a";
arr[1] = "b";
const jsArr = util.java.toJsArray(arr);
log(JSON.stringify(jsArr));
失败行为
如果不是 Java 数组也不是可迭代对象,会抛:
util.java.toJsArray requires a Java array or iterable
util.java.objectToMap(obj)
作用
把 JS 对象的可枚举属性转成 Java LinkedHashMap。
返回值
Java Map<String, Any?>
说明
- 只会遍历脚本对象当前能枚举到的属性。
- 每个值会再做一层脚本值到普通 Kotlin / HTTP 兼容值的转换。
- 它不是“反射 Java 对象的所有字段”。
示例
const map = util.java.objectToMap({
name: "demo",
count: 3,
enabled: true
});
log(String(map));
util.java.mapToObject(map)
作用
把 Java Map 转成普通 JS 对象。
返回值
JS Object;如果传入不是 Map,返回 null。
示例
const HashMap = importClass("java.util.HashMap");
const map = new HashMap();
map.put("name", "demo");
map.put("count", 3);
const obj = util.java.mapToObject(map);
log(obj.name);
log(obj.count);
util.api
util.api 是 util 自己的别名引用,常见用途只是拿来确认模块对象本身或统一风格:
log(util === util.api);
log(util.java === util.java.api);
util.java.api
同理,util.java.api 是 util.java 这个子对象本身。
