Class 对象是反射的第一步,我们先从 Class 对象聊起,因为在反射中,只要你想在运行时使用类型信息,就必须先得到那个 Class 对象的引用,他是反射的核心,它代表了Java类的元数据信息,包含了类的结构、属性、方法和其他相关信息。通过Class对象,我们可以获取和操作类的成员,实现动态加载和操作类的能力。
publicstaticvoidmain(String[] args){ // do something if ("满足条件A") { // 查询权限 if ("是否具备权限A" && "是否具备权限B") { // 查询配置 if ("配置是否开启"){ // do something
}
}
} // do something
}
publicstaticvoidmain(String[] args){ // do something if (isMeetCondition()) { // 查询配置 // 此处查询配置的值需要在具体的任务中使用,所有并没抽离 if ("配置是否开启") { // do something
}
} // do something
}
// call echo.syn var ret=dsBridge.call("echo.syn",{msg:" I am echoSyn call", tag:1}) alert(JSON.stringify(ret)) // call echo.asyn
dsBridge.call("echo.asyn",{msg:" I am echoAsyn call",tag:2},function (ret) { alert(JSON.stringify(ret));
})
在ES6中,你可以使用Object.getOwnPropertyNames()方法来检查对象是否为空,但需要注意的是,该方法返回一个数组,其包含给定对象中所有自有属性(包括不可枚举属性,但不包括使用 symbol 值作为名称的属性)。 以下是使用Object.getOwnPropertyNames()方法来检查对象是否为空的示例代码:
const getDataFn = url => {
dispatch({
type: url,
payload: { id: query.id },
callback: res => {
if (res.ret === 1) {
let initFormVal = localStorage.getItem('initFormVal' + query?.id);
console.log('initFormVal', JSON.parse(initFormVal));
let cacheFormVal = {};
if (initFormVal) {
//initFormVal赋值给cacheFormVal,此处省略
}
setPricingInfo({
...cacheFormVal,
...res.data
});
}
发现有一个console.log(),JSON.parse('')会是什么?报错,果然,查异常上报日志的时候,也查到这个错误,真是一失足成千古恨,当时只是为了方便查看,打印了一下缓存数据,没想到是这个地方出现的问题 Uncaught SyntaxError: Unexpected end of JSON input
我继续忙着其他事情,3分钟后,我正要打开新的控制台页面,猛然发现控制台上的“ public = true”。我惊慌地查看磁盘快照状态,发现磁盘快照已经共享给了所有用户。任何用户都可以在自己的快照列表中看到这个快照,并用快照创建新的磁盘,这意味着这些快照数据已经泄露了。这可是公司重要客户的磁盘数据啊!!!!
其次,在合并代码时,我们要将四种分支模型(dev、test、uat、release)作为参照物,而不是把关注点放在自己的分支上。比如我们要在 dev 上调试,那就需要把自己的分支合并到 dev 分支上;如果我们需要提测,则把自己的分支合并到 test 分支上,以此类推。
即,我们要关注到,这四个环境的分支上,会有什么内容,会新增什么内容。切记不能反过来将这四个分支合并到自己的代码上!! 如果其他成员将自己的代码也提交到 dev 分支上,但是这个代码是没有通过验证的,此时你将 dev 往自己的分支上合,那之后的提测、上预发、生产则很大概率会出问题。所以一定要保持自己的分支是干净的!
接下来介绍合并代码的方式:
第一种:线上合并,也是推荐的规范操作
git push origin feat-0131-jie
先接着上面的提交步骤,将自己的分支推送到远程仓库。
然后在线上代码仓库中,申请将自己的分支合并到 xx 分支(具体是哪个分支就根据你当前的开发进度来,如 test),然后在线上解决冲突。如果有权限就自己通过了,如果没有就得找 mt 啥的
select s2.id,s2.name,s2.phone from encrypt_value_mapping s1 innerjoin`user` s2 on s1.ref_id=s2.id where s1.encrypt_value ='U2FsdGVkX19Se8cEpSLVGTkLw/yiNhcB' limit0,20;
但是... 微信小程序提供的元素依然太少了,根本没办法满足实际开发需要(比如根本没有表格元素)。于是微信小程序提供了一个 rich-text 元素,可用于渲染 HTML 元素。
但是这个 rich-text 就显得十分鸡肋,他不是通过 slot 传入 HTML 元素,而是通过 string 或者 object。这凭空增加了开发难度,导致我不得不这么写:
<rich-textnodes="{{nodes}}"></rich-text>
this.setData({ nodes: licenses.map(it => { return`
<div style="margin: 20px 10px;"><strong>${it.projectName}</strong>
is licensed under the <code>${it.licenseName}</code>:</div>
<pre style="overflow: auto; background-color:#F5F6FA;"><code>${it.fullLicense}</code></pre> ${it.sourceRepo?`<div style="margin: 20px 10px;"><span style="color:gray; font-size: 12px;">The source code can be found at: ${it.sourceRepo}</span></div>`:""}
<br/><br/>
`
}).join("")
})
classSolution { public Listpostorder(Node root) {
List ans = newArrayList<>();
Deque
C++ 代码:
classSolution { public: vector<int> postorder(Node* root){ vector<int> ans;
stackint, Node*>> st;
st.push({0, root}); while (!st.empty()) { auto [cnt, t] = st.top();
st.pop(); if (!t) continue; if (cnt == t->children.size()) ans.push_back(t->val); if (cnt < t->children.size()) {
st.push({cnt + 1, t});
st.push({0, t->children[cnt]});
}
} return ans;
}
};
Python 代码:
classSolution: defpostorder(self, root: 'Node') -> List[int]:
ans = []
stack = [(0, root)] while stack:
cnt, t = stack.pop() ifnot t: continue if cnt == len(t.children):
ans.append(t.val) if cnt < len(t.children):
stack.append((cnt + 1, t))
stack.append((0, t.children[cnt])) return ans
TypeScript 代码:
functionpostorder(root: Node | null): number[] { const ans = [], stack = [];
stack.push([0, root]); while (stack.length > 0) { const [cnt, t] = stack.pop()!; if (!t) continue; if (cnt === t.children.length) ans.push(t.val); if (cnt < t.children.length) {
stack.push([cnt + 1, t]);
stack.push([0, t.children[cnt]]);
}
} return ans;
};
时间复杂度:O(n)
空间复杂度:O(n)
通用「非递归」
另外一种「递归」转「迭代」的做法,是直接模拟系统执行「递归」的过程,这是一种更为通用的做法。
由于现代编译器已经做了很多关于递归的优化,现在这种技巧已经无须掌握。
在迭代过程中记录当前栈帧位置状态 loc,在每个状态流转节点做相应操作。
Java 代码:
classSolution { public Listpostorder(Node root) {
List ans = newArrayList<>();
Deque
C++ 代码:
classSolution { public: vector<int> postorder(Node* root){ vector<int> ans;
stackint, Node*>> st;
st.push({0, root}); while (!st.empty()) { int loc = st.top().first;
Node* t = st.top().second;
st.pop(); if (!t) continue; if (loc == 0) {
st.push({1, t}); for (int i = t->children.size() - 1; i >= 0; i--) {
st.push({0, t->children[i]});
}
} elseif (loc == 1) {
ans.push_back(t->val);
}
} return ans;
}
};
Python 代码:
classSolution: defpostorder(self, root: 'Node') -> List[int]:
ans = []
stack = [(0, root)] while stack:
loc, t = stack.pop() ifnot t: continue if loc == 0:
stack.append((1, t)) for child inreversed(t.children):
stack.append((0, child)) elif loc == 1:
ans.append(t.val) return ans
cat a.java 查看a.java文件的最后一页内容;
more a.java从 第一页开始查看a.java文件内容,按回车键一行一行进行查看,按空格键一页一页进行查看,q退出;
less a.java 从第一页开始查看a.java文件内容,按回车键一行一行的看,按空格键一页一页的看,支持使用PageDown和PageUp翻页,q退出。
总结下more和less的区别
less可以按键盘上下方向键显示上下内容,more不能通过上下方向键控制显示。
less不必读整个文件,加载速度会比more更快。
less退出后shell不会留下刚显示的内容,而more退出后会在shell上留下刚显示的内容。
实时查看文件后几行(实时查看日志)
tail -f a.java 查看a.java文件的后10行内容;
前后几行查看
head a.java:查看a.java文件的前10行内容;
tail -f a.java:查看a.java文件的后10行内容;
head -n 7 a.java:查看a.java文件的前7行内容;
tail -n 7 a.java:查看a.java文件的后7行内容;
文件内部搜索指定的内容
grep under 123.txt:在123.txt文件中搜索under字符串,大小写敏感,显示行;
grep -n under 123.txt:在123.txt文件中搜索under字符串,大小写敏感,显示行及行号;
grep -v under 123.txt:在123.txt文件中搜索under字符串,大小写敏感,显示没搜索到的行;
grep -i under 123.txt:在123.txt文件中搜索under字符串,大小写敏感,显示行;
grep -ni under 123.txt:在123.txt文件中搜索under字符串,大小写敏感,显示行及行号;
var pool = Executors.newSingleThreadExecutor() varout = DataOutputStream(xxxSocket.outputStream) var runnable = Runnable { try { out.writeInt(data.size) var offset = 0 while ((offset + 1024) <= data.size) { out.write(data, offset, 1024)
offset += 1024
} out.write(data, offset, data.size - offset) out.flush()
} catch (e: Throwable) {
Log.e("xxxx", "xxxx", e)
}
}
pool.execute(runnable)
读取
var input = DataInputStream(xxxSocket.inputStream) var runnable = Runnable { var outArray = ByteArrayOutputStream() while (true) {
outArray.reset() var length = input.readInt() if(length > 0) { var buffer = ByteArray(1024) var total = 0 while (total + 1024 <= length) { var count = input.read(buffer)
outArray.write(buffer, 0, count)
total += count
} var buffer2 = ByteArray(length - total)
input.read(buffer2)
outArray.write(buffer2) var result = outArray.toByteArray()
...
}
}
}
Thread(runnable).start()
bind: function (el, binding, vnode) { let resize = el let left = resize.previousElementSibling let right = resize.nextElementSibling let box = resize.parentElement }
let leftWidth = binding.value?.left || 300 let resizeWidth = binding.value?.resize || 10 let rightWidth = `calc(100% - ${leftWidth + 10}px - ${resizeWidth}px)`
if (binding.value?.left && Object.prototype.toString.call(binding.value?.left) !== '[object Number]') { console.error(`${binding.value.left} Must be Number`) } if (binding.value?.resize && Object.prototype.toString.call(binding.value?.resize) !== '[object Number]') { console.error(`${binding.value.left} Must be Number`) }
let resize = el let left = resize.previousElementSibling let right = resize.nextElementSibling let box = resize.parentElement