鸿蒙Harmony角落里的知识:从ECMA规范到ArkTS接口(二)

news2024/11/23 7:25:44

上篇介绍了typedArray.slice方法,鸿蒙Harmony角落里的知识:从ECMA规范到ArkTS接口(一)本文介绍一个返回结果和参数和slice非常类似的函数:TypedArray.prototype.subarray。


ECMA对TypedArray.prototype.subarray接口的定义:

按照ECMA的规范,TypedArray.prototype.subarray(begin, end) 方法定义如下:

  • begin: 起始索引,表示新视图的起始点。
  • end: 结束索引,代表新视图的终点(但不包括该索引本身)。

如果 end 参数省略,subarray 将默认包含从 begin 开始到原数组结尾的所有元素。如果 begin 或 end 是负值,则它们表示从数组末尾开始的倒数索引。方法返回一个新的 TypedArray 实例,它表示原始 TypedArray 的一个连续子集。

我们可以直接查看ECMA规范中对该函数的描述:

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )
	This method returns a new TypedArray whose element type is the element type of this TypedArray and whose ArrayBuffer is the ArrayBuffer of this TypedArray, referencing the elements in the interval from start (inclusive) to end (exclusive). If either start or end is negative, it refers to an index from the end of the array, as opposed to from the beginning.

It performs the following steps when called:

1. Let O be the this value.
2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
4. Let buffer be O.[[ViewedArrayBuffer]].
5. Let srcRecord be MakeTypedArrayWithBufferWitnessRecord(O, SEQ-CST).
6. If IsTypedArrayOutOfBounds(srcRecord) is true, then
	a. Let srcLength be 0.
7. Else,
	a. Let srcLength be TypedArrayLength(srcRecord).
8. Let relativeStart be ? ToIntegerOrInfinity(start).
9. If relativeStart = -∞, let startIndex be 0.
10. Else if relativeStart < 0, let startIndex be max(srcLength + relativeStart, 0).
11. Else, let startIndex be min(relativeStart, srcLength).
12. Let elementSize be TypedArrayElementSize(O).
13. Let srcByteOffset be O.[[ByteOffset]].
14. Let beginByteOffset be srcByteOffset + (startIndex × elementSize).
15. If O.[[ArrayLength]] is AUTO and end is undefined, then
	a. Let argumentsList be « buffer, 𝔽(beginByteOffset) ».
16. Else,
	a. If end is undefined, let relativeEnd be srcLength; else let relativeEnd be ? ToIntegerOrInfinity(end).
	b. If relativeEnd = -∞, let endIndex be 0.
	c. Else if relativeEnd < 0, let endIndex be max(srcLength + relativeEnd, 0).
	d. Else, let endIndex be min(relativeEnd, srcLength).
	e. Let newLength be max(endIndex - startIndex, 0).
	f. Let argumentsList be « buffer, 𝔽(beginByteOffset), 𝔽(newLength) ».
17. Return ? TypedArraySpeciesCreate(O, argumentsList).
This method is not generic. The this value must be an object with a [[TypedArrayName]] internal slot.

TypedArray.prototype.subarray与TypedArray.prototype.slice对比:

TypedArray.prototype.subarray 和 TypedArray.prototype.slice 是两个不同的 TypedArray 方法,用于生成原数组某部分的新数组,但他们在处理方式和结果的内存分配上存在差异。

首先,subarray 方法返回的新 TypedArray 对象,并不创建原 ArrayBuffer 的副本,而是创建了一个新的 TypedArray 视图,这个视图引用的是原 ArrayBuffer 中的相同内存区域。这意味着 subarray 方法生成的数组与原数组共享相同的数据存储,因此对新数组的修改会影响到原数组中相应的部分。这个方法的执行效率较高,因为它避免了复制操作,只是创建了一个指向相同内存区域的新视图。

另一方面,slice 方法会创建一个新的 ArrayBuffer,并将选定的元素从原 TypedArray 对象复制到新数组中。这意味着 slice 方法生成的新数组拥有自己的数据存储,对这个新数组的任何修改都不会影响原数组。由于涉及到内存中数据的复制操作,slice 方法在执行时的效率略低于 subarray

下面是这两个方法的对比分析:

  1. 内存共享与否
    • subarray:返回一个新 TypedArray,共享同一个 ArrayBuffer
    • slice:返回一个新 TypedArray,有自己独立的 ArrayBuffer
  2. 性能
    • subarray:性能较高,因为没有进行元素的复制,仅仅是创建了一个新的视图。
    • slice:性能较低,因为需要复制元素到新的 ArrayBuffer
  3. 修改影响
    • subarray:由于共享 ArrayBuffer,对生成的 TypedArray 的修改会影响到原数组。
    • slice:由于使用了新的 ArrayBuffer,对生成的 TypedArray 的修改不会影响到原数组。
  4. 参数处理
    • subarray 和 slice 方法对于 start 和 end 参数的处理是相同的。如果 start 或 end 是负数,它们会被解释为从数组末尾开始的索引。如果 end 是 undefined,则操作会处理直到原数组的末尾。
  5. 返回值类型
    • 无论是 subarray 还是 slice,返回的新数组类型都与原数组相同。
  6. 错误处理
    • slice 方法在复制过程中有更严格的错误检查。例如,如果源 TypedArray 越界,它会抛出 TypeError

总的来说,选择 subarray 还是 slice 取决于你是否需要一个独立的数组副本,以及是否关心性能和内存使用。如果你只是想要一个指向相同数据的快速视图,并且不介意对这个视图的修改会影响原数据,那么 subarray 是一个好选择。而如果你需要一个完全独立的复制,不会影响原数据的副本,那么应该选择 slice 方法。

ArkTS对subarray的接口描述:

我们继续以\static_core\plugins\ets\stdlib\escompat\TypedUArrays.ets的Uint8Array定义为例:

/**
     * Creates a Uint8Array with the same underlying Buffer
     *
     * @param begin start index, inclusive
     *
     * @param end last index, exclusive
     *
     * @returns new Uint8Array with the same underlying Buffer
     */
    public subarray(begin?: number, end?: number): Uint8Array {
        return this.subarray(asIntOrDefault(begin, 0 as int), asIntOrDefault(end, this.lengthInt))
    }

    /**
     * Creates a Uint8Array with the same underlying Buffer
     *
     * @param begin start index, inclusive
     *
     * @param end last index, exclusive
     *
     * @returns new Uint8Array with the same underlying Buffer
     */
    public subarray(begin: number, end: number): Uint8Array {
        return this.subarray(begin as int, end as int)
    }

    /**
     * Creates a Uint8Array with the same underlying Buffer
     *
     * @param begin start index, inclusive
     *
     * @param end last index, exclusive
     *
     * @returns new Uint8Array with the same underlying Buffer
     */
    public subarray(begin: number, end: int): Uint8Array {
        return this.subarray(begin as int, end as int)
    }

    /**
     * Creates a Uint8Array with the same underlying Buffer
     *
     * @param begin start index, inclusive
     *
     * @param end last index, exclusive
     *
     * @returns new Uint8Array with the same underlying Buffer
     */
    public subarray(begin: int, end: number): Uint8Array {
        return this.subarray(begin as int, end as int)
    }

    /**
     * Creates a Uint8Array with the same underlying Buffer
     *
     * @param begin start index, inclusive
     *
     * @param end last index, exclusive
     *
     * @returns new Uint8Array with the same underlying Buffer
     */
    public subarray(begin: int, end: int): Uint8Array {
        const len: int = this.length as int
        const relStart = normalizeIndex(begin, len)
        const relEnd = normalizeIndex(end, len)
        let count = relEnd - relStart
        if (count < 0) {
            count = 0
        }
        return new Uint8Array(this.buffer, relStart * Uint8Array.BYTES_PER_ELEMENT as int, count)
    }

    /**
     * Creates a Uint8Array with the same Buffer
     *
     * @param begin start index, inclusive
     *
     * @returns new Uint8Array with the same Buffer
     */
    public subarray(begin: number): Uint8Array {
        return this.subarray(begin as int, this.lengthInt)
    }

    /**
     * Creates a Uint8Array with the same Buffer
     *
     * @param begin start index, inclusive
     *
     * @returns new Uint8Array with the same Buffer
     */
    public subarray(begin: int): Uint8Array {
        return this.subarray(begin, this.lengthInt)
    }

ArkTS对subarray的接口定义如上,可以看到基本覆盖了ECMA的规范的方方面面。此外,我们还可以看到,subarray提供了对int类型参数的支持,而TS是仅仅只支持number类型的参数的。

测试用例:

要验证我们的 subarray 方法实现是否正确,我们可以编写单元测试用例。这里我们使用了ArkTS和Jest测试框架,来确保我们的实现与ECMA规范一致。

const success = 0;
const fail = 1;
function testSubarrayWithOutParam(): int {
  let source: number[] = [10, 20, 30, 40, 50, 60];
  let ss = new ArrayBuffer(source.length as int * 1);

  let origin: Uint8Array;

  try {
    origin = new Uint8Array(ss);
    origin.set(source);
  } catch(e) {
    console.log(e);
    return fail;
  }

  let target: Uint8Array;

  try {
    target = origin.subarray();
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != origin.length as int) {
    console.log("Array length mismatch on slice");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = 0; i< origin.length as int; i++) {
    let tv = target[i] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  origin= new Uint8Array(0);
  if (origin.length as int != 0){
    return fail;
  }

  try {
    target = origin.subarray();
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != 0){
    return fail;
  }
  return success;
}

function testSubarrayOneParam(): int {
  let source: number[] = [10, 20, 30, 40, 50, 60];
  let ss = new ArrayBuffer(source.length as int * 1);

  let origin: Uint8Array;

  try {
    origin = new Uint8Array(ss);
    origin.set(source);
  } catch(e) {
    console.log(e);
    return fail;
  }

  let subarrayStart: int = 1;
  let subarrayEnd: int = origin.length as int;

  let target: Uint8Array;

  try {
    target = origin.subarray(subarrayStart);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != origin.length as int - subarrayStart) {
    console.log("Array length mismatch on subarray One Params" + target.length);
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  subarrayStart = 0;
  try {
    target = origin.subarray(undefined);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != origin.length as int) {
    console.log("Array length mismatch on subarray One Params" + target.length);
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  //The subarray method returns a view of the original array, so modifications made to the subarray will affect the original array, and vice versa.
  target[subarrayStart] = 1;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  origin[subarrayStart] = 2;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  return success;
}

function testSubarrayTwoParams(): int {
  let source: number[] = [10, 20, 30, 40, 50, 60, 70, 80];
  let ss = new ArrayBuffer(source.length as int * 1);

  let origin: Uint8Array;

  try {
    origin = new Uint8Array(ss);
    origin.set(source);
  } catch(e) {
    console.log(e);
    return fail;
  }

  let subarrayStart: int = 2;
  let subarrayEnd: int = 4;

  let target: Uint8Array;

  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != subarrayEnd - subarrayStart) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  subarrayStart = 0;
  subarrayEnd = origin.length as int;
  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != subarrayEnd - subarrayStart) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  try {
    target = origin.subarray(new Number(subarrayStart), undefined);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != subarrayEnd - subarrayStart) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  try {
    target = origin.subarray(undefined, undefined);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != subarrayEnd - subarrayStart) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  try {
    target = origin.subarray(undefined, new Number(subarrayEnd));
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != subarrayEnd - subarrayStart) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = subarrayStart; i< subarrayEnd; i++) {
    let tv = target[i - subarrayStart] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  try {
    target = origin.subarray(0, 0);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != 0) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  return success;
}

function testSubarrayTwoParamsWithOtherNumber(): int {
  let source: number[] = [10, 20, 30, 40, 50, 60, 70, 80];
  let ss = new ArrayBuffer(source.length as int * 1);

  let origin: Uint8Array;

  try {
    origin = new Uint8Array(ss);
    origin.set(source);
  } catch(e) {
    console.log(e);
    return fail;
  }

  let subarrayStart: int = 4;
  let subarrayEnd: int = 2;

  let target: Uint8Array;

  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    return fail;
  }

  if (target.length as int != 0) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  subarrayStart = -1;
  subarrayEnd = origin.length as int;
  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    return fail;
  }

  if (target.length as int != subarrayEnd - (origin.length + subarrayStart)) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  //Check all the data copied;
  for (let i: int = (origin.length + subarrayStart) as int; i< subarrayEnd; i++) {
    let tv = target[i - (origin.length + subarrayStart)] as number;
    let ov = origin[i] as number;
    console.log(source[i] + "->" + tv + "->" + ov);
    if (tv != ov) {
      console.log("Array data mismatch");
      return fail;
    }
  }

  subarrayStart = 0;
  subarrayEnd = -origin.length as int;
  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    console.log(e);
    return fail;
  }

  if (target.length as int != (origin.length + subarrayEnd) - subarrayStart) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  return success;
}

function testSubarrayOneLengthTwoParams(): int {
  let source: number[] = [10];
  let ss = new ArrayBuffer(source.length as int * 1);

  let origin: Uint8Array;

  try {
    origin = new Uint8Array(ss);
    origin.set(source);
  } catch(e) {
    console.log(e);
    return fail;
  }
  
  let subarrayStart: int = 4;
  let subarrayEnd: int = 2;

  let target: Uint8Array;

  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    return fail;
  }

  if (target.length as int != 0) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  subarrayStart = 2;
  subarrayEnd = 4;
  try {
    target = origin.subarray(subarrayStart, subarrayEnd);
  } catch(e) {
    return fail;
  }

  if (target.length as int != 0) {
    console.log("Array length mismatch on subarray2");
    return fail;
  }

  return success;
}


这些测试用例检查了 subarray 方法在正常条件下和非正常条件下的行为,对比slice函数的测试用例,我们使用通过修改源数组影响目标数组数值的方式验证内存共享的功能。

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习

点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

一、鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

二、HarmonyOS Next 最新全套视频教程

三、《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

四、大厂面试必问面试题

五、鸿蒙南向开发技术

六、鸿蒙APP开发必备

七、鸿蒙生态应用开发白皮书V2.0PDF


完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

                        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1846654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【启明智显产品介绍】Model3C工业级HMI芯片详解专题(三)通信接口

Model3C 是一款基于 RISC-V 的高性能、国产自主、工业级高清显示与智能控制 MCU, 集成了内置以太网控制器&#xff0c;配备2路CAN、4路UART、5组GPIO、2路SPI等多种通信接口&#xff0c;能够轻松与各种显示设备连接&#xff0c;实现快速数据传输和稳定通信&#xff0c;可以与各…

Matplotlib绘制一个X轴2个Y轴的图表

import matplotlib matplotlib.use(Agg) # 使用Agg后端&#xff0c;这个后端适用于生成图像文件但不显示它们 import matplotlib.pyplot as plt fig plt.figure(figsize(15, 8))# 字体使用楷体 matplotlib.rc("font", family"Microsoft YaHei") ax1 fig…

【大数据】—二手车用户数据可视化分析案例

项目背景 在当今的大数据时代&#xff0c;数据可视化扮演着至关重要的角色。随着信息的爆炸式增长&#xff0c;我们面临着前所未有的数据挑战。这些数据可能来自社交媒体、商业交易、科学研究、医疗记录等各个领域&#xff0c;它们庞大而复杂&#xff0c;难以通过传统的数据处…

ISCC2024 WriteUpReverse 迷失之门

Reverse 迷失之门 迷失之门 writeup解题思路 打开题目是一个压缩包解压后是一个.exe程序 按照做题顺序第一步查壳发现并没有壳将其拖入ida中进行查看 使用shiftF12进行字符串查看 发现flag字符了我们双击它 将光标移动到yes哪里右击空白地方打开交叉索引并按F5进行反汇编发现…

Ci2451和Ci2454:2.4GHz无线MCU的芯片对比数据资料分析

一、2.4GHz无线MCU芯片的背景介绍 1、开头我们先聊聊&#xff0c;关于南京中科微2.4GHz无线MCU芯片&#xff08;Ci2451、Ci2454、CSM2433)是建立在现有的2.4GHz射频芯片基础上面&#xff0c;它的内部是集成了8位RISC内核&#xff0c;且集成丰富的MCU资源、更小的尺寸可以来满足…

stable diffusion webui电商基础模型

电商生成模型的产生主要有两个路子,1.训练微调;2.模型融合。 下面这些是借鉴,帮助思考如何构建电商模型。 电商必备的10款Stable diffusion WebUI 模型 - 知乎一、WFProduct 电商场景这是一个专门为电商摄影场景训练的 lora 模型,可以生成各种极具设计感的场景图,效果逼真…

2024年高处安装、维护、拆除证考试题库及高处安装、维护、拆除试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年高处安装、维护、拆除证考试题库及高处安装、维护、拆除试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上…

【设计模式深度剖析】【10】【行为型】【状态模式】

&#x1f448;️上一篇:访问者模式 | 下一篇:解释器模式&#x1f449;️ 设计模式-专栏&#x1f448;️ 文章目录 状态模式定义英文定义直译如何理解呢&#xff1f; 状态模式的角色Context&#xff08;环境类&#xff09;State&#xff08;抽象状态类&#xff09;Concret…

实战!如何从零搭建10万级 QPS 大流量、高并发优惠券系统--图文解析

实战&#xff01;如何从零搭建10万级 QPS 大流量、高并发优惠券系统–图文解析 原文链接&#xff1a;https://juejin.cn/post/7087824893831544845 原文作者&#xff1a;字节跳动技术团队 需求背景 需要设计、开发一个能够支持十万级 QPS 的优惠券系统 什么是QPS? Queri…

课程标准包括哪些内容?

老师们常常会思考&#xff1a;课程标准究竟包含哪些要素&#xff1f;课程标准不仅仅是一系列冷冰冰的条条框框&#xff0c;而是活生生的指导原则&#xff0c;引领教学实践&#xff0c;激发学生的潜能。 课程标准&#xff0c;简而言之&#xff0c;是对学习成果的期望和要求的明确…

观测云「可观测性解决方案」荣耀登入华为云官网

继成功上架华为云云商店联营商品后&#xff0c;「观测未来可观测性解决方案」已进一步正式登陆华为云官网&#xff0c;标志着双方合作的深化与拓展。这一全新上架的解决方案是观测云技术实力的集大成之作&#xff0c;为企业提供了一个全面升级的数字化监控观测服务。 观测云&am…

AI大模型“行业数据集-场景应用创新计划”启动征集

数据决定了大模型的“智力”边界。当前&#xff0c;在通用领域&#xff0c;大模型初步呈现了一定的场景应用能力&#xff0c;然而&#xff0c;在医疗健康、教育等垂直领域&#xff0c;大模型所展现的能力尚不足以支持专业应用&#xff0c;其主要原因在于模型训练缺乏高质量可用…

深入探索Java开发世界:MySQL~类型分析大揭秘

文章目录 深入探索Java开发世界&#xff1a;MySQL~类型分析大揭秘一、数据结构类型二、函数类型三、事物类型四、事物隔离级别类型五、数据一致性问题类型 深入探索Java开发世界&#xff1a;MySQL~类型分析大揭秘 MySQL数据库基础知识&#xff0c;类型知识点梳理~ 一、数据结构…

基于EXCEL数据表格创建省份专题地图

1 数据源 随着西藏于5月1日发布2022年一季度经济运行情况&#xff0c;31省份一季度GDP数据已全部出炉。 总量方面&#xff0c;粤苏鲁稳居前三&#xff1b;增速方面&#xff0c;23省份高于“全国线”&#xff0c;新疆表现最佳&#xff0c;增速达到7.0%。 表格表现数据不够直观…

MATLAB神经网络---lstmLayer(LSTM 长短期记忆神经网络)

前言 描述LSTM就要先描述一下循环神经网络 循环神经网络 循环神经网络通过使用带自反馈的神经元&#xff0c;使得网络的输出不仅和当前的输入有关&#xff0c;还和上一时刻的输出相关&#xff0c;于是在处理任意长度的时序数据时&#xff0c;就具有短期记忆能力。 如下是一个…

【前端vue3】TypeScrip-interface(接口)和对象类型

对象类型 定义对象需要用到interface&#xff08;接口&#xff09;&#xff0c;主要用来约束数据的类型满足格式 定义方式如下&#xff1a; interface Person {name: string;age: number; }如对象中与接口中的属性不一致会报错&#xff0c;必须保持一致 例如如下&#xff1a…

web中间件漏洞-Tomcat漏洞-密码爆破、war包上传

web中间件漏洞-Tomcat漏洞-密码爆破、war包上传 密码爆破 步骤: 抓登陆包、对字典进行base64编码&#xff0c;爆破得到账号密码tomcat/tomcat,登陆即可 tomcat/tomcat登陆成功 服务器 查看 tomcat-users.xml里的账号密码 war包上传 步骤 上传war包、访问即可

低成本创业新篇章:上门回收小程序的崛起与挑战

在当今这个快速变化的时代&#xff0c;低成本创业项目成为了许多创业者的首选。其中&#xff0c;上门回收小程序以其独特的商业模式和市场需求&#xff0c;成为了创业市场中的一股新势力。本文将深入探讨上门回收小程序作为低成本创业项目的崛起之路以及面临的挑战。 一、上门回…

振弦式渗压计在土木工程安全监测中的重要性解析

在土木工程领域中&#xff0c;特别是涉及到坝体、隧道、路基等复杂结构的监测与安全管理时&#xff0c;渗压计作为一种关键的测量工具&#xff0c;发挥着举足轻重的作用。其中&#xff0c;振弦式渗压计以其独特的优点&#xff0c;得到了广泛的应用和认可。本文将对振弦式渗压计…

关于OS中逻辑地址与物理地址转换

首先将逻辑地址134D从十六进制转为2进制 0001 0011 0100 1101 1&#xff09;1K的时候对应2的10次方 页面大小占10位 从后往前数 0001 00 || 11 0100 1101 前面的转为十进制为4 对应页号4内容1A转为2进制01 1010将这个替换原来的前六位数字 即0110 1011 0100 1101 再转换为…