Flutter 基础知识总结

1、Flutter 介绍与环境安装

为什么选择 Dart:

  • 基于 JIT 快速开发周期:Flutter 在开发阶段采用 JIT 模式,避免每次改动都进行编译,极大的节省了开发时间
  • 基于 AOT 发布包:Flutter 在发布时可以通过 AOT 生成高效的 ARM 代码以保证应用性能
  • UI 帧率可达 120 FPS:为了快速流畅的用户体验需要能够在每个动画帧运行大量的代码,不能有周期性的停顿,否则会造成掉帧
  • 单线程:不需要锁,不存在数据竞争和变量状态同步,也没有线程上下文切换的性能损耗和锁导致的卡顿
  • 垃圾回收:多生代(参考了 JVM)无锁垃圾回收器,专门为 UI 框架中常见的大量 Widgets 对象创建和销毁优化

JIT(Just In Time)即时编译,在程序执行期间实时编译为本地机器码;AOT(Ahead Of Time)静态编译,程序运行前编译成本地机器码。在代码的执行效率上,JIT 不如 AOT。

2、Dart 基础语法

2024-5-17.Dart基础一

Dart 不用编译了,dart xxx.dart 直接就执行,不像 Java 需要先 javac 编译出 class 文件再 java xxx.class 执行。

2.1 变量

类型与声明

变量都是引用类型,未初始化的变量的值是 null。

声明变量的方式通常有三种:

  1. Object:与 Java 一样 Object 是所有类的基类,Object 声明的变量可以是任意类型。比如数字(包括 int 类型的数字)、方法和 null 都是对象
  2. var:声明的变量在赋值的那一刻,决定了它是什么类型
  3. dynamic:不是在编译时候确定实际类型的,而是在运行时。dynamic 声明的变量行为与 Object 一样,使用一样,关键在于运行时原理不同

示例代码:

void test1() {// 1.通过类型声明变量Object i = "Test";// 2.通过 var 声明变量var j = "Test";// 报错,声明时已经确定了变量类型,不可更改// j = 100;// 3.声明时没有具体指明是什么类型,那么就是默认的 Object 类型var k;// 可以为 k 赋值为 Object 的子类型k = "Test";k = 100;// 4.dynamic 动态类型可以赋值不同类型dynamic z = "Test";z = 100;
}

需要注意的地方:

  • 所有类型,没有初始化的变量自动获取一个默认值为 null
  • 声明变量时,可以选择加上具体类型,如int a = 1;,但对于局部变量,按照 Dart 代码风格,使用 var 而不是具体类型

final 与 const

final 声明运行时常量,const 声明编译器常量(相比于运行时常量可让代码运行更高效),二者都用于声明常量,可以替代任何类型,只能在声明时初始化,且不能改变:

void test2() {// 1.const 与 final 可以替代任何类型const a = 1;final b = 1;const int c = 1;final int d = 1;// 2.不能通过运行时常量构造编译时常量final m = 1;// 企图通过运行时常量构造编译时常量,导致 const 值无法确定// const n = m + 1;// 使用编译时能够确定的值构造 const 常量是可以的const x = 1;const y = x + 1;
}

类的变量可以是 final 但不能是 const。如果 const 变量在类中,需要定义为 static const 静态常量:

class T {static const i = 2; // 正确const j = 1; // 错误
}

2.2 内置类型

Dart 内置以下类型:

  • numbers
  • strings
  • booleans
  • lists(也被称之为 arrays)
  • maps
  • runes(用于在字符串中表示 Unicode 字符)
  • symbols

数值 num

num 是数字类型的父类,有两个子类 int 和 double。

int 的默认实现是 64 位,如果编译成 JavaScript,就是 32 位。在编码时,如果 int 长度超过 4 个字节,那么 Dart 会将其编译为类似 Java 的 long 类型,否则编译成 Java 中的 short 或 int。

也就是说,int 的长度是动态确定的,可以通过 int 的 bitLength() 确定存储该 int 变量所需要的最小的位数。

但实际上,不应该将 Dart 的 int 和 Java 的 int 做类比,因为前者是一个类,后者是一个基本类型的关键字。从本质上说,二者不是一个东西,没有可比性。

字符串 String

Dart 字符串是 UTF-16 编码的字符序列,使用方法如下:

  • 可以使用单引号或者双引号来创建字符串:

    var name = 'lance';
    // 如果插入一个简单的标识符,而后面没有紧跟更多的字母数字文本,那么 {} 应该被省略
    var a = "my name is $name!";
    var b = "my name is ${name.toUpperCase()}!";
    
  • 与 Java 一样可以使用 + 操作符来把拼接字符串,也可以把多个字符串放到一起来实现同样的功能:

    var a  = "my name is " "lance";
    
  • 使用三个单引号或者双引号可以创建多行字符串对象:

    var s1 = '''
    You can create
    multi-line strings like this one.
    ''';var s2 = """This is also a
    multi-line string.""";
    
  • 可以通过单引号嵌套双引号,或双引号嵌套单引号进行转义:

    print("'Test'"); // 'Test'
    print('"Test"'); // "Test"
    
  • 也可以使用 Java 的方式转义,或者使用 Dart 的 r 前缀创建一个原始字符串实现转义:

    // 两行输出结果均为 换行符 \n
    print("换行符 \\n");
    print(r"换行符 \n");
    

布尔类型 bool

Dart 的布尔类型 bool 有 true 和 false 两个对象。

列表 List

Dart 的数组是 List 对象,它有两种声明方式:

  1. 当作 List 对象声明:

    // new 可以省略
    var list = new List(1);
    
  2. 当作数组声明:

    var list = [1, 2, 3];
    

通过 for 循环遍历 List 也有两种方式:

for(var item in list) {print(item);
}for(var j = 0;j < list.length; ++j) {print(list[j]);
}

当数组与 const 相结合时,需要注意:

	List<int> list1 = const[1,2,3];// Unsupported operation: Cannot add to an unmodifiable list//list1.add(4);const List<int> list2 = [1,2];// Error: Can't assign to the const variable 'list2'.//list2 = list1;// Unsupported operation: Cannot add to an unmodifiable list//list2.add(4);

const 修是谁,谁就不可变:

  • list1 指向不可变的 [1,2,3],那么就不能修改数组,但是可以指向其他数组对象
  • list2 本身是一个常量引用,那么它就只能指向 [1,2],不能修改索引,也不能修改索引的内容

映射集合 Map

两种声明方式:

var companys = {'a': '阿里巴巴', 't': '腾讯', 'b': '百度'};
var companys2 = new Map();
// 添加元素
companys2['a'] = '阿里巴巴';
companys2['t'] = '腾讯';
companys2['b'] = '百度';// 获取与修改元素
var c = companys['c']; // 没有对应的 key 返回null
companys['a'] = 'alibaba'; 

const 与 Map 结合的情况与 List 样。

Runes

Runes 主要用于获取特殊字符的 Unicode 编码,或者需要将 32 位的 Unicode 编码转换为字符串。

Dart 表达 Unicode 代码点的常用方法是 \uXXXX,其中 XXXX 是 4 位十六进制值。要指定多于或少于 4 个十六进制数字,需要将值放在大括号中:

var clapping = '\u{1f44f}'; // 5 个 16 进制 需要使用 {}
print(clapping); //👏
// 获得 16 位代码单元
print(clapping.codeUnits); // [55357, 56399]
// 获得 Unicode 代码
print(clapping.runes.toList()); // [128079]// fromCharCode 根据字符码创建字符串
print(String.fromCharCode(128079));
print(String.fromCharCodes(clapping.runes));
print(String.fromCharCodes([55357, 56399]));
print(String.fromCharCode(0x1f44f));Runes input = new Runes('\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
print(String.fromCharCodes(input));

这里要清楚一个代码点和代码单元的概念:

代码点(Code Point)和代码单元(Code Unit)

代码单元与代码点

简言之,代码点就是字符集中每个字符的值,比如上面代码中👏符号在 Unicode32 中的值为 0x1f44f。

代码单元指编码集中具有最短比特组合的单元。对于 UTF-8 来说,代码单元是 8 比特长;对于 UTF-16 来说,代码单元是 16 比特长。换一种说法就是 UTF-8 的是以一个字节为最小单位的,UTF-16 是以两个字节为最小单位的。

我们在 Java 中常说 String.length() 是获取字符串长度,实际上是不严谨的,应该说是 UTF-16 编码表示下的代码单元数量,而不是字符个数。例如:

String a = "\uD83D\uDC4F";
printf(a); // 👏
printf(a.length()); // 2

你看打印输出的长度为代码单元个数 2,而不是 a 中字符的个数。charAt() 也是类似的情况。

Symbols

操作符标识符,可以看作C中的宏。表示编译时的一个常量:

var i = #A; // 常量
print(i.runtimeType); // Symbolmain() {print(i);switch(i) {case #A:print("A");break;case #B:print("B");break;}var b = new Symbol("b");print(#b == b); // true
}

2.3 操作符

主要看 Java 没有的操作符:

  1. 类型判定操作符:is!is 用于判断对象是否为某种类型,as 用于将对象转换为特定类型

  2. 赋值操作符:??= 用来指定值为 null 的变量的值,比如:

    // 如果 b 是 null,则 value 赋值给 b,否则 b 的值保持不变
    b ??= value;
    
  3. 条件表达式:

    • condition ? expr1 : expr2:如果 condition 为 true 则执行 expr1,否则执行 expr2
    • expr1 ?? expr2:如果 expr1 不为 null 则取 expr1,否则返回 expr2 的值
  4. 级联操作符:..可以在同一个对象上连续调用多个函数以及访问成员变量,这样可以避免创建临时变量,代码看起来也更加流畅:

    // StringBuffer write() 相当于 Java 的 append
    var sb = new StringBuffer();
    sb..write('foo')..write('bar');
    
  5. 安全操作符:?.左值如果为 null 则返回 null:

    String sb;
    // 报空指针异常
    print(sb.length);
    // 打印输出 null
    print(sb?.length);
    

3、方法

3.1 一等方法对象

Dart 是一个真正的面向对象语言,方法也是对象,类型为Function。 这意味着,方法可以赋值给变量,也可以当做其他方法的参数。可以把方法当做参数调用另外一个方法。

在 Java 中如果需要能够通知调用者或者其他地方方法执行过程的各种情况,可能需要指定一个接口,比如 View 的 OnClickListener。而在 Dart 中,我们可以直接指定一个回调方法给调用的方法,由调用的方法在合适的时机执行这个回调:

void setListener(Function listener) {listener("Success");
}// 或者
void setListener(void listener(String result)){listener("Success");
}// 两种方式,第一种调用者根本不确定回调函数的返回值、参数是些什么
// 第二种则需要写这么一大段,太麻烦// 第三种:类型定义,将返回值为 void,参数为一个 String 的方法定义为一个类型
typedef void Listener(String result)void setListener(Listener listener){listener("Success");
}

上面演示了方法作为参数的三种形式:

  1. 第一种使用 Function 表示一个方法,但是这种形式无法确定方法的参数以及返回值类型,因此不好
  2. 第二种直接将方法的原型写在方法参数中,写起来麻烦,看起来也不舒服,因此也 pass
  3. 第三种将方法定义为一个类型,使用该类型作为方法参数,推荐这种写法

3.2 可选命名参数

将方法的参数放到 {} 中就变成可选命名参数:

int add({int? i, int? j}) {if (i == null || j == null) {return 0;}return i + j;
}

调用方法时使用 key-value 形式指定参数:

void main() {print(add()); // 0print(add(i: 1, j: 2)); // 3
}

3.3 可选位置参数

将方法的参数放到 [] 中就变成可选位置参数,传值时按照参数位置顺序传递:

int add([int? i, int? j]) {if (i == null || j == null) {return 0;}return i + j;
}

调用时可以不传入全部的参数,参数按照参数声明的顺序赋值:

void main() {print(add()); // 0print(add(1)); // 0print(add(1, 2)); // 3
}

可选命名参数与可选位置参数的出现使得方法重载的实现更容易。在 Java 中,方法重载需要写出多个不同参数的方法,但是在 Dart 中通过将方法声明为可选命名参数或可选位置参数,写一个方法,在调用时传入所需参数即可。

3.4 默认参数值

定义方法时,可选参数可以使用 = 来定义可选参数默认值:

int add([int i = 1, int j = 2]) => i + j;
int add({int i = 1, int j = 2}) => i + j;

3.5 匿名方法

没有名字的方法,称之为匿名方法,也可以称之为 lambda 或者 closure 闭包。匿名方法的声明方式为:

([Type] param1,) { codeBlock; 
}; 

比如:

var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums'];
list.forEach((i) {print(i);
});

4、异常

Dart 的异常机制也像 Kotlin 一样非常灵活,不像 Java 那样强制你捕获异常。

所有的 Dart 异常是非检查异常,方法不一定声明了他们所抛出的异常, 并且不要求你捕获任何异常。

Dart 的异常类型有ExceptionError两种根类型还有若干个它们的子类型,在抛出异常时,可以抛出任何非 null 对象,不局限于ExceptionError以及它们的子类型:

throw new Exception('这是一个异常');
throw '这是一个异常';
throw 123;

Dart 虽然也支持 try-catch-finally 捕获异常,但是 catch 无法指定类型,需要结合 on 使用:

try {throw 123;
} on int catch(e) {// 使用 on 指定捕获 int 类型的异常对象,on TYPE catch(e)      
} catch(e,s) { // 两个参数的类型分别为 _Exception 和 _StackTracerethrow; // 使用 `rethrow` 关键字可以把捕获的异常给重新抛出
} finally {}

catch() 可以接收两个参数:

  • 第一个参数 e 是被抛出的异常对象,类型是 _Exception
  • 第二个参数 s 是堆栈信息对象,类型是 _StackTrace,通过 print(s) 可以输出异常堆栈信息

骚操作,抛出异常时抛出一个方法,catch 的时候可以通过捕获 Function 类型来执行该方法。

5、类

Dart 是面向对象的语言,所有类都继承自 Object。

命名风格:

  • 使用 lowercase_with_underscores 风格命名库和文件名
  • 使用 upperCamelCase 命名类型名称
  • 使用 lowerCamelCase 命名其他标识符
  • 推荐使用 lowerCamelCase 命名常量

每个实例变量会自动生成一个隐含的 getter 方法,非 final 实例变量还会自动生成一个 setter 方法:

class Point {// 公有变量num x = 0;// _开头的是私有变量num _y = 0;
}

Dart 在作用域上并没有 Java 那样 public、private 的关键字,作用域只有公有与私有之分,用 _ 开头表示私有变量或私有类,不以 _ 开头的就是公有的类或变量。

5.1 构造函数

常规构造函数

class User {// 初始值一定要给,否则编译不通过String name = "";int age = 0;User(String name, int age) {this.name = name;this.age = age;}
}

由于把构造函数的参数赋值给实例变量的场景太常见,因此 Dart 提供了语法糖来简化操作:

class User {String name = "";int age = 0;User(this.name, this.age);
}

也可以使用 {} 将构造函数的参数声明为可选位置参数,只不过此时不能用 this:

class User {// 成员变量要有初始值String name = "";int age = 0;// 使用可选命名参数,由于 name 和 age 都不可为 null,因此// 参数也需要设置默认值,防止没有为其传参时将成员变量赋值为 nullUser({String name = "", int age = 0}) {this.name = name;this.age = age;}
}void main() {var user0 = User(name: "User0"); // name = User0, age = 0var user1 = User(age: 30); // name = , age = 30var user2 = User(age: 22, name: "User2"); // name = User2, age = 22
}

命名构造函数

Dart 不允许任何函数的重载,不论是构造函数还是成员函数还是顶级函数。但有时我们确实有重载构造函数的需求,此时可以使用命名构造函数为一个类实现多个构造函数:

class User {String name = "";int age = 0;User(this.name, this.age);// 命名构造函数,在 . 后面随意取名,调用时也使用改名字进行构造即可User.fromJson(Map json) {name = json['name'];age = json['age'];}
}void main() {var map = {'name': 'User', 'age': 33};var user = User.fromJson(map);
}

好处是可以通过名字判断出构造函数的大致意图和内容,更加直观。比如 User.fromJson() 就能看出是通过 Json 数据构造 User 对象。

构造函数初始化列表

这一点跟 C++ 很像:

class User {String name = "";int age = 0;User(String name, int age): name = name,age = age;User.fromJson(Map json): name = json['name'],age = json['age'];
}

重定向构造函数

class View {View(int context, int attr);// 会调用上面的构造函数View.a(int context) : this(context, 0);
}

常量构造函数

这里的常量指的是编译器常量,首先需要使用 const 修饰构造函数:

class ImmutablePoint {final int x;final int y;// 常量构造函数要求成员必须是 final 的const ImmutablePoint(this.x, this.y);
}

然后在构造对象时,不使用 new,而是使用 const,并且要求构造不同对象时传入的参数必须是一样的:

void main() {var p1 = const ImmutablePoint(1, 1);var p2 = const ImmutablePoint(1, 1);var p3 = const ImmutablePoint(1, 2);var p4 = new ImmutablePoint(1, 1);print('''p1 == p2:${p1 == p2}
p1 == p3:${p1 == p3}
p1 == p4:${p1 == p4}''');
}

输出结果为:

p1 == p2:true
p1 == p3:false
p1 == p4:false

主要用于同一个对象被多次使用时,比如 UI 上显示三个相同的 ListItem,使用常量构造函数就可以创建出一个对象,而不是三个对象,节省了内存。

工厂构造函数

使用 factory 关键字修饰,必须返回一个本类或子类的实例对象:

class Person {// 返回本类对象factory Person.get() {return new Person();}// 返回子类对象factory Person.getStudent() {return new Student();}// 如果想要被,需要有一个常规构造函数Person();
}class Student extends Person {}

在 Dart 中使用单例模式时就可以用到 factory:

class Person {// 使用 _ 让静态对象私有化,并且类型后面加问号表示为可空// 类型,否则就要在声明 Person 对象时立即为其初始化static Person? _instance;// 定义工厂构造函数返回单例factory Person.getInstance() {// 如果 _instance 为 null 才创建对象_instance ??= Person._newInstance();// 返回 _instance,后接的感叹号表示非 null return _instance!;}// 创建一个私有的常规构造函数,这样默认的构造函数 Person() 就没有了 Person._newInstance();
}

这样在 Person 类所在的文件之外,就无法访问到私有的 _instance 和 _newInstance(),只能通过 getInstance() 获取到 Person 的单例:

var person = Person.getInstance();

5.2 getter & setter

Dart 中每一个实例属性都会有一个隐式的 getter,非 final 还有 setter。

首先来看一个错误示例:

class Point {int x = 0;int get x => x + 10;
}

在定义 x 的 getter 时编译器会报错,说 x 已经定义过。因此如果想自定义属性的 getter 或 setter 需要将属性声明为私有的:

class Point {int _x = 0;int _y = 0;int get x => _x + 10;int get y => _y + 20;
}

在一个需要注意,getter 与 setter 是方法,而不是属性,因此可以在方法名后面加上 {} 在里面写相关逻辑:

class Point {int _x = 0;int get x {return _x + 10;}// setter 需要有一个参数set x(int value) {_x = value;}
}

5.3 操作符重载

重载 + 运算符:

class Point {int x = 0;int y = 0;Point(this.x, this.y);// 用 operator 接上要重载的操作符Point operator +(Point other) => Point(x + other.x, y + other.y);
}

这样可以用 + 连接两个 Point 对象:

void main() {var point = Point(10, 20) + Point(30, 50);print("x = ${point.x}, y = ${point.y}"); // x = 40, y = 70
}

Dart 的操作符重载非常灵活,返回值的类型不受限制,比如上面重载 + 时返回一个 Point 是我们的常规操作,但是你也可以根据自己需要返回其他类型,比如 String、int 等等。

5.4 抽象类与接口

使用 abstract 定义抽象类,抽象类中允许出现无方法体的方法:

abstract class Parent {String name = "";// 抽象方法前面不能加 abstractvoid printName();
}

Dart 没有 interface 关键字,Dart 中的每个类都隐式定义了一个包含所有实例成员的接口:

class A {void a() {}
}class B implements A {void a() {}
}

5.5 其他语法

可调用的类

如果类中定义了 call 方法,可以通过该类实例对象后接 () 的形式快速调用 call:

void main() {var a = A();a();
}class A {void call() {print("invoke call method.");}
}

call 方法可以带参数。

混合 mixins

mixins 是一种在多类继承中重用一个类代码的方法,基本形式如下:

void main() {var c = C();c.a();c.b();c.c();
}mixin A {void a() {}
}mixin B {void b() {print("B");}
}class C with A, B {void c() {}void b() {print("C");}
}

注意:

  • 被混入的类需要用 mixin 声明,并且不能有构造函数,否则就无法作为被混入的类出现在 with 后面

  • 混合结果的 C 类中,可以重写,也可以重新定义 A、B 中的方法

  • 如果 A、B 内定义了同名方法,且 C 也定义了同名方法,那么 C 的实例在调用该方法时实际上调用的是 C 中的方法;如果 C 中没有定义同名方法,那么 C 调用的就是 B 中的方法(根据 with 后面的排序,优先取顺位靠后的)

  • 在 C 中可以通过 super 调用 A 或 B 中的方法,比如:

    mixin A {void a() {}
    }class C with A, B {void a() {super.a();}
    }
    
  • 上述几点能发现 mixin 与多继承的表现有很多相似之处

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

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

相关文章

Jenkins 持续集成部署

Jenkins的安装与部署 前言 当我们在实施一个项目时&#xff0c;从新代码中获得反馈的速度越快&#xff0c;问题越早得到解决&#xff0c;获得反馈的一种常见方法是在新代码之后运行测试&#xff0c;但这就导致了当代码正在编译并且正在运行测试时&#xff0c;开发人员无法在测…

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集BIM介绍基本原理算法流程 BIM代码实现BIM算法实现攻击效果 代码汇总bim.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对CIFAR10进行分类 Py…

OpenGL —— 2.6.1、绘制一个正方体并贴图渲染颜色(附源码,glfw+glad)

源码效果 C++源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version

ubuntu开机进入initramfs状态

虚拟机卡死成功起后进入了initramfs状态&#xff0c;可能是跟文件系统有问题或者检索不到根文件系统&#xff0c;或者是配置错误&#xff0c;系统磁盘等硬件问题导致 开机后进入如下图的界面&#xff0c; 文中有一条提示 要手动fsck 命令修复 /dev/sda1 命令如下 fsck /de…

java根据Word模板实现动态填充导出

最近项目中需要导出Word&#xff0c;根据不同的信息导出不同的内容&#xff0c;包含文本、列表、图片等&#xff0c;本文使用poi-tl实现在次做以记录。 添加依赖 <!-- word导出 --> <dependency><groupId>com.deepoove</groupId><artifactId>po…

Go框架比较:goframe、beego、iris和gin

由于工作需要&#xff0c;这些年来也接触了不少的开发框架&#xff0c;Golang的开发框架比较多&#xff0c;不过基本都是Web"框架"为主。这里稍微打了个引号&#xff0c;因为大部分"框架"从设计和功能定位上来讲&#xff0c;充其量都只能算是一个组件&…

OMG DDS 规范漫谈:分布式数据交互的演进之路

一、由来与起源脉络 OMG DDS&#xff08;Object Management Group Data Distribution Service&#xff09;的发展是计算机科学和技术进步的一个缩影&#xff0c;它反映了对高效、可靠的数据共享需求的响应。DDS 的概念萌生于20世纪90年代末&#xff0c;当时分布式计算已经从理…

Spring源码分析之AOP-@EnableAspectJAutoProxy

前言 这篇文章之前我们说了Springboot的启动流程,Bean对象怎么实现从无到有的一个过程还有一些接口的拓展的实现等等那么从这一篇文章开始的话我们就会开始说一说我们的常用的AOP它的底层实现原理所以大家一起加油加油&#xff01;&#xff01;&#xff01; AOP: 1.简介: AOP的…

Linux(Centos 7.6)基本信息查看

1.服务器硬件信息查看 1.1.服务器厂商、产品名称查看 dmidecode -s system-manufacturer&#xff1a;查看服务器厂商信息 dmidecode -s system-product-name&#xff1a;查看服务器产品名称信息 1.Windows使用VMware安装的Linux(Centos 7.6)后&#xff0c;服务器厂商、产品名…

小程序app封装公用顶部筛选区uv-drop-down

参考ui:DropDown 下拉筛选 | 我的资料管理-uv-ui 是全面兼容vue32、nvue、app、h5、小程序等多端的uni-app生态框架 样式示例&#xff1a; 封装公用文件代码 dropDownTemplete <template><!-- 顶部下拉筛选区封装公用组件 --><view><uv-drop-down ref&…

LeetCode:101. 对称二叉树

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输…

Docker-如何启动docker

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们在上一章&#xff0c;讲了虚拟化&#xff0c;虚拟化是把硬件虚拟化&#xff0c;然后创建出来的虚拟机完全隔离&#xff…

COMSOL with Matlab

文章目录 基本介绍COMSOL with MatlabCOMSOL主Matlab辅Matlab为主Comsol为辅 操作步骤常用指令mphopenmphgeommghmeshmphmeshstatsmphnavigatormphplot常用指令mphsavemphlaunchModelUtil.clear 实例教学自动另存新档**把语法套用到边界条件**把语法套用到另存新档 函数及其微分…

JVM系列(十二) -常用调优命令汇总

最近对 JVM 技术知识进行了重新整理&#xff0c;再次献上 JVM系列文章合集索引&#xff0c;感兴趣的小伙伴可以直接点击如下地址快速阅读。 JVM系列(一) -什么是虚拟机JVM系列(二) -类的加载过程JVM系列(三) -内存布局详解JVM系列(四) -对象的创建过程JVM系列(五) -对象的内存分…

bmp390l传感器的IIC命令通信(学习汇总)

参考链接&#xff1a; BMP390高精度压力传感器数据读取与处理&#xff08;基于STM32&#xff09;-CSDN博客 https://blog.csdn.net/qq_43862401/article/details/106502397 利用usb转iic模块测试bmp390l传感器采集当前环境的温度和气压数据&#xff0c;下图中reserved表示…

Windows11 家庭版安装配置 Docker

1. 安装WSL WSL 是什么&#xff1a; WSL 是一个在 Windows 上运行 Linux 环境的轻量级工具&#xff0c;它可以让用户在 Windows 系统中运行 Linux 工具和应用程序。Docker 为什么需要 WSL&#xff1a; Docker 依赖 Linux 内核功能&#xff0c;WSL 2 提供了一个高性能、轻量级的…

2025系统架构师(一考就过):案例题之一:嵌入式架构、大数据架构、ISA

一、嵌入式系统架构 软件脆弱性是软件中存在的弱点(或缺陷)&#xff0c;利用它可以危害系统安全策略&#xff0c;导致信息丢失、系统价值和可用性降低。嵌入式系统软件架构通常采用分层架构&#xff0c;它可以将问题分解为一系列相对独立的子问题&#xff0c;局部化在每一层中…

新手SEO指南如何快速入门与提升网站排名

内容概要 搜索引擎优化&#xff08;SEO&#xff09;是提高网站可见度和排名的重要手段&#xff0c;尤其对新手来说&#xff0c;掌握其基本概念和实用技巧至关重要。本文将针对新手提供一系列的指导&#xff0c;帮助你快速入门并逐步提升网站排名。 首先&#xff0c;了解SEO的…

Oracle下载安装(保姆级教学)

方法1 1. 官网下载安装包 对于 Oracle 软件的下载&#xff0c;建议通过官网免费下载&#xff0c;安全且有保证。 下载地址&#xff1a; https://www.oracle.com/database/technologies/oracle19c-windows-downloads.html 通过下载页面可以选择安装压缩包&#xff08; WIND…

第22天:信息收集-Web应用各语言框架安全组件联动系统数据特征人工分析识别项目

#知识点 1、信息收集-Web应用-开发框架-识别安全 2、信息收集-Web应用-安全组件-特征分析 一、ICO图标&#xff1a; 1、某个应用系统的标示&#xff0c;如若依系统有自己特点的图标&#xff1b;一旦该系统出问题&#xff0c;使用该系统的网站都会受到影响&#xff1b; 2、某个公…