0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Lombok开发插件使用小技巧

电子工程师 来源:CSDN技术社区 作者:$码出未来 2021-06-12 18:07 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

0x01:Lombok简介

Lombok 是一款 Java开发插件,使得 Java 开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的 Java 模型对象(POJO)。在开发环境中使用 Lombok插件后,Java 开发人员可以节省出重复构建,诸如 hashCode 和 equals 这样的方法以及各种业务对象模型的 accessor 和 toString 等方法的大量时间。对于这些方法,Lombok 能够在编译源代码期间自动帮我们生成这些方法,但并不会像反射那样降低程序的性能。

0x02:Lombok安装

构建工具

Gradle

在 build.gradle 文件中添加 Lombok 依赖:

dependencies {

compileOnly ‘org.projectlombok1.18.10’

annotationProcessor ‘org.projectlombok1.18.10’

}

Maven

在 Maven 项目的 pom.xml 文件中添加 Lombok 依赖:

《dependency》

《groupId》org.projectlombok《/groupId》

《artifactId》lombok《/artifactId》

《version》1.18.10《/version》

《scope》provided《/scope》

《/dependency》

Ant

假设在 lib 目录中已经存在 lombok.jar,然后设置 javac 任务:

《javac srcdir=“src” destdir=“build” source=“1.8”》

《classpath location=“lib/lombok.jar” /》

《/javac》

IDE

由于 Lombok 仅在编译阶段生成代码,所以使用 Lombok 注解的源代码,在 IDE 中会被高亮显示错误,针对这个问题可以通过安装 IDE 对应的插件来解决。这里不详细展开,具体的安装方式可以参考:

https://www.baeldung.com/lombok-ide

0x03:Lombok 详解

注意:以下示例所使用的 Lombok 版本是 1.18.10

3.1 @Getter and @Setter

你可以使用 @Getter 或 @Setter 注释任何类或字段,Lombok 会自动生成默认的 getter/setter 方法。

@Getter 注解

@Target({ElementType.FIELD, ElementType.TYPE})

@Retention(RetentionPolicy.SOURCE)

public @interface Getter {

// 若getter方法非public的话,可以设置可访问级别

lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;

AnyAnnotation[] onMethod() default {};

// 是否启用延迟初始化

boolean lazy() default false;

}

@Setter

@Target({ElementType.FIELD, ElementType.TYPE})

@Retention(RetentionPolicy.SOURCE)

public @interface Setter {

// 若setter方法非public的话,可以设置可访问级别

lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;

AnyAnnotation[] onMethod() default {};

AnyAnnotation[] onParam() default {};

}

使用示例

@Getter

@Setter

public class GetterAndSetterDemo {

String firstName;

String lastName;

LocalDate dateOfBirth;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class GetterAndSetterDemo {

String firstName;

String lastName;

LocalDate dateOfBirth;

public GetterAndSetterDemo() {

}

// 省略其它setter和getter方法

public String getFirstName() {

return this.firstName;

}

public void setFirstName(String firstName) {

this.firstName = firstName;

}

}

Lazy Getter

@Getter 注解支持一个 lazy 属性,该属性默认为 false。当设置为 true 时,会启用延迟初始化,即当首次调用 getter 方法时才进行初始化。

示例

public class LazyGetterDemo {

public static void main(String[] args) {

LazyGetterDemo m = new LazyGetterDemo();

System.out.println(“Main instance is created”);

m.getLazy();

}

@Getter

private final String notLazy = createValue(“not lazy”);

@Getter(lazy = true)

private final String lazy = createValue(“lazy”);

private String createValue(String name) {

System.out.println(“createValue(” + name + “)”);

return null;

}

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class LazyGetterDemo {

private final String notLazy = this.createValue(“not lazy”);

private final AtomicReference《Object》 lazy = new AtomicReference();

// 已省略部分代码

public String getNotLazy() {

return this.notLazy;

}

public String getLazy() {

Object value = this.lazy.get();

if (value == null) {

synchronized(this.lazy) {

value = this.lazy.get();

if (value == null) {

String actualValue = this.createValue(“lazy”);

value = actualValue == null ? this.lazy : actualValue;

this.lazy.set(value);

}

}

}

return (String)((String)(value == this.lazy ? null : value));

}

}

通过以上代码可知,调用 getLazy 方法时,若发现 value 为 null,则会在同步代码块中执行初始化操作。

3.2 Constructor Annotations

@NoArgsConstructor

使用 @NoArgsConstructor 注解可以为指定类,生成默认的构造函数,@NoArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.SOURCE)

public @interface NoArgsConstructor {

// 若设置该属性,将会生成一个私有的构造函数且生成一个staticName指定的静态方法

String staticName() default “”;

AnyAnnotation[] onConstructor() default {};

// 设置生成构造函数的访问级别,默认是public

AccessLevel access() default lombok.AccessLevel.PUBLIC;

// 若设置为true,则初始化所有final的字段为0/null/false

boolean force() default false;

}

示例

@NoArgsConstructor(staticName = “getInstance”)

public class NoArgsConstructorDemo {

private long id;

private String name;

private int age;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class NoArgsConstructorDemo {

private long id;

private String name;

private int age;

private NoArgsConstructorDemo() {

}

public static NoArgsConstructorDemo getInstance() {

return new NoArgsConstructorDemo();

}

}

@AllArgsConstructor

使用 @AllArgsConstructor 注解可以为指定类,生成包含所有成员的构造函数,@AllArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.SOURCE)

public @interface AllArgsConstructor {

// 若设置该属性,将会生成一个私有的构造函数且生成一个staticName指定的静态方法

String staticName() default “”;

AnyAnnotation[] onConstructor() default {};

// 设置生成构造函数的访问级别,默认是public

AccessLevel access() default lombok.AccessLevel.PUBLIC;

}

示例

@AllArgsConstructor

public class AllArgsConstructorDemo {

private long id;

private String name;

private int age;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class AllArgsConstructorDemo {

private long id;

private String name;

private int age;

public AllArgsConstructorDemo(long id, String name, int age) {

this.id = id;

this.name = name;

this.age = age;

}

}

@RequiredArgsConstructor

使用 @RequiredArgsConstructor 注解可以为指定类必需初始化的成员变量,如 final 成员变量,生成对应的构造函数,@RequiredArgsConstructor 注解的定义如下:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.SOURCE)

public @interface RequiredArgsConstructor {

// 若设置该属性,将会生成一个私有的构造函数且生成一个staticName指定的静态方法

String staticName() default “”;

AnyAnnotation[] onConstructor() default {};

// 设置生成构造函数的访问级别,默认是public

AccessLevel access() default lombok.AccessLevel.PUBLIC;

}

示例

@RequiredArgsConstructor

public class RequiredArgsConstructorDemo {

private final long id;

private String name;

private int age;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class RequiredArgsConstructorDemo {

private final long id;

private String name;

private int age;

public RequiredArgsConstructorDemo(long id) {

this.id = id;

}

}

3.3 @EqualsAndHashCode

使用 @EqualsAndHashCode 注解可以为指定类生成 equals 和 hashCode 方法, @EqualsAndHashCode 注解的定义如下:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.SOURCE)

public @interface EqualsAndHashCode {

// 指定在生成的equals和hashCode方法中需要排除的字段列表

String[] exclude() default {};

// 显式列出用于identity的字段,一般情况下non-static,non-transient字段会被用于identity

String[] of() default {};

// 标识在执行字段计算前,是否调用父类的equals和hashCode方法

boolean callSuper() default false;

boolean doNotUseGetters() default false;

AnyAnnotation[] onParam() default {};

@Deprecated

@Retention(RetentionPolicy.SOURCE)

@Target({})

@interface AnyAnnotation {}

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.SOURCE)

public @interface Exclude {}

@Target({ElementType.FIELD, ElementType.METHOD})

@Retention(RetentionPolicy.SOURCE)

public @interface Include {

String replaces() default “”;

}

}

示例

@EqualsAndHashCode

public class EqualsAndHashCodeDemo {

String firstName;

String lastName;

LocalDate dateOfBirth;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class EqualsAndHashCodeDemo {

String firstName;

String lastName;

LocalDate dateOfBirth;

public EqualsAndHashCodeDemo() {

}

public boolean equals(Object o) {

if (o == this) {

return true;

} else if (!(o instanceof EqualsAndHashCodeDemo)) {

return false;

} else {

EqualsAndHashCodeDemo other = (EqualsAndHashCodeDemo)o;

if (!other.canEqual(this)) {

return false;

} else {

// 已省略大量代码

}

}

public int hashCode() {

int PRIME = true;

int result = 1;

Object $firstName = this.firstName;

int result = result * 59 + ($firstName == null ? 43 : $firstName.hashCode());

Object $lastName = this.lastName;

result = result * 59 + ($lastName == null ? 43 : $lastName.hashCode());

Object $dateOfBirth = this.dateOfBirth;

result = result * 59 + ($dateOfBirth == null ? 43 : $dateOfBirth.hashCode());

return result;

}

}

3.4 @ToString

使用 @ToString 注解可以为指定类生成 toString 方法, @ToString 注解的定义如下:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.SOURCE)

public @interface ToString {

// 打印输出时是否包含字段的名称

boolean includeFieldNames() default true;

// 列出打印输出时,需要排除的字段列表

String[] exclude() default {};

// 显式的列出需要打印输出的字段列表

String[] of() default {};

// 打印输出的结果中是否包含父类的toString方法的返回结果

boolean callSuper() default false;

boolean doNotUseGetters() default false;

boolean onlyExplicitlyIncluded() default false;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.SOURCE)

public @interface Exclude {}

@Target({ElementType.FIELD, ElementType.METHOD})

@Retention(RetentionPolicy.SOURCE)

public @interface Include {

int rank() default 0;

String name() default “”;

}

}

示例

@ToString(exclude = {“dateOfBirth”})

public class ToStringDemo {

String firstName;

String lastName;

LocalDate dateOfBirth;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class ToStringDemo {

String firstName;

String lastName;

LocalDate dateOfBirth;

public ToStringDemo() {

}

public String toString() {

return “ToStringDemo(firstName=” + this.firstName + “, lastName=” +

this.lastName + “)”;

}

}

3.5 @Data

@Data 注解与同时使用以下的注解的效果是一样的:

@ToString

@Getter

@Setter

@RequiredArgsConstructor

@EqualsAndHashCode

@Data 注解的定义如下:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.SOURCE)

public @interface Data {

String staticConstructor() default “”;

}

示例

@Data

public class DataDemo {

private Long id;

private String summary;

private String description;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class DataDemo {

private Long id;

private String summary;

private String description;

public DataDemo() {

}

// 省略summary和description成员属性的setter和getter方法

public Long getId() {

return this.id;

}

public void setId(Long id) {

this.id = id;

}

public boolean equals(Object o) {

if (o == this) {

return true;

} else if (!(o instanceof DataDemo)) {

return false;

} else {

DataDemo other = (DataDemo)o;

if (!other.canEqual(this)) {

return false;

} else {

// 已省略大量代码

}

}

}

protected boolean canEqual(Object other) {

return other instanceof DataDemo;

}

public int hashCode() {

int PRIME = true;

int result = 1;

Object $id = this.getId();

int result = result * 59 + ($id == null ? 43 : $id.hashCode());

Object $summary = this.getSummary();

result = result * 59 + ($summary == null ? 43 : $summary.hashCode());

Object $description = this.getDescription();

result = result * 59 + ($description == null ? 43 : $description.hashCode());

return result;

}

public String toString() {

return “DataDemo(id=” + this.getId() + “, summary=” + this.getSummary() + “, description=” + this.getDescription() + “)”;

}

}

3.6 @Log

若你将 @Log 的变体放在类上(适用于你所使用的日志记录系统的任何一种);之后,你将拥有一个静态的 final log 字段,然后你就可以使用该字段来输出日志。

@Log

private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());

@Log4j

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);

@Log4j2

private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);

@Slf4j

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);

@XSlf4j

private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

@CommonsLog

private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);

3.7 @Synchronized

@Synchronized 是同步方法修饰符的更安全的变体。与 synchronized 一样,该注解只能应用在静态和实例方法上。它的操作类似于 synchronized 关键字,但是它锁定在不同的对象上。synchronized 关键字应用在实例方法时,锁定的是 this 对象,而应用在静态方法上锁定的是类对象。对于 @Synchronized 注解声明的方法来说,它锁定的是 或lock。@Synchronized 注解的定义如下:

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public @interface Synchronized {

// 指定锁定的字段名称

String value() default “”;

}

示例

public class SynchronizedDemo {

private final Object readLock = new Object();

@Synchronized

public static void hello() {

System.out.println(“world”);

}

@Synchronized

public int answerToLife() {

return 42;

}

@Synchronized(“readLock”)

public void foo() {

System.out.println(“bar”);

}

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class SynchronizedDemo {

private static final Object $LOCK = new Object[0];

private final Object $lock = new Object[0];

private final Object readLock = new Object();

public SynchronizedDemo() {

}

public static void hello() {

synchronized($LOCK) {

System.out.println(“world”);

}

}

public int answerToLife() {

synchronized(this.$lock) {

return 42;

}

}

public void foo() {

synchronized(this.readLock) {

System.out.println(“bar”);

}

}

}

3.8 @Builder

使用 @Builder 注解可以为指定类实现建造者模式,该注解可以放在类、构造函数或方法上。@Builder 注解的定义如下:

@Target({TYPE, METHOD, CONSTRUCTOR})

@Retention(SOURCE)

public @interface Builder {

@Target(FIELD)

@Retention(SOURCE)

public @interface Default {}

// 创建新的builder实例的方法名称

String builderMethodName() default “builder”;

// 创建Builder注解类对应实例的方法名称

String buildMethodName() default “build”;

// builder类的名称

String builderClassName() default “”;

boolean toBuilder() default false;

AccessLevel access() default lombok.AccessLevel.PUBLIC;

@Target({FIELD, PARAMETER})

@Retention(SOURCE)

public @interface ObtainVia {

String field() default “”;

String method() default “”;

boolean isStatic() default false;

}

}

示例

@Builder

public class BuilderDemo {

private final String firstname;

private final String lastname;

private final String email;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class BuilderDemo {

private final String firstname;

private final String lastname;

private final String email;

BuilderDemo(String firstname, String lastname, String email) {

this.firstname = firstname;

this.lastname = lastname;

this.email = email;

}

public static BuilderDemo.BuilderDemoBuilder builder() {

return new BuilderDemo.BuilderDemoBuilder();

}

public static class BuilderDemoBuilder {

private String firstname;

private String lastname;

private String email;

BuilderDemoBuilder() {

}

public BuilderDemo.BuilderDemoBuilder firstname(String firstname) {

this.firstname = firstname;

return this;

}

public BuilderDemo.BuilderDemoBuilder lastname(String lastname) {

this.lastname = lastname;

return this;

}

public BuilderDemo.BuilderDemoBuilder email(String email) {

this.email = email;

return this;

}

public BuilderDemo build() {

return new BuilderDemo(this.firstname, this.lastname, this.email);

}

public String toString() {

return “BuilderDemo.BuilderDemoBuilder(firstname=” + this.firstname + “, lastname=” + this.lastname + “, email=” + this.email + “)”;

}

}

}

3.9 @SneakyThrows

@SneakyThrows 注解用于自动抛出已检查的异常,而无需在方法中使用 throw 语句显式抛出。@SneakyThrows 注解的定义如下:

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})

@Retention(RetentionPolicy.SOURCE)

public @interface SneakyThrows {

// 设置你希望向上抛的异常类

Class《? extends Throwable》[] value() default java.lang.Throwable.class;

}

示例

public class SneakyThrowsDemo {

@SneakyThrows

@Override

protected Object clone() {

return super.clone();

}

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class SneakyThrowsDemo {

public SneakyThrowsDemo() {

}

protected Object clone() {

try {

return super.clone();

} catch (Throwable var2) {

throw var2;

}

}

}

3.10 @NonNull

你可以在方法或构造函数的参数上使用 @NonNull 注解,它将会为你自动生成非空校验语句。@NonNull 注解的定义如下:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})

@Retention(RetentionPolicy.CLASS)

@Documented

public @interface NonNull {

}

示例

public class NonNullDemo {

@Getter

@Setter

@NonNull

private String name;

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class NonNullDemo {

@NonNull

private String name;

public NonNullDemo() {

}

@NonNull

public String getName() {

return this.name;

}

public void setName(@NonNull String name) {

if (name == null) {

throw new NullPointerException(“name is marked non-null but is null”);

} else {

this.name = name;

}

}

}

3.11 @Clean

@Clean 注解用于自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成 try-finally 这样的代码来关闭流。

@Target(ElementType.LOCAL_VARIABLE)

@Retention(RetentionPolicy.SOURCE)

public @interface Cleanup {

// 设置用于执行资源清理/回收的方法名称,对应方法不能包含任何参数,默认名称为close。

String value() default “close”;

}

示例

public class CleanupDemo {

public static void main(String[] args) throws IOException {

@Cleanup InputStream in = new FileInputStream(args[0]);

@Cleanup OutputStream out = new FileOutputStream(args[1]);

byte[] b = new byte[10000];

while (true) {

int r = in.read(b);

if (r == -1) break;

out.write(b, 0, r);

}

}

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class CleanupDemo {

public CleanupDemo() {

}

public static void main(String[] args) throws IOException {

FileInputStream in = new FileInputStream(args[0]);

try {

FileOutputStream out = new FileOutputStream(args[1]);

try {

byte[] b = new byte[10000];

while(true) {

int r = in.read(b);

if (r == -1) {

return;

}

out.write(b, 0, r);

}

} finally {

if (Collections.singletonList(out).get(0) != null) {

out.close();

}

}

} finally {

if (Collections.singletonList(in).get(0) != null) {

in.close();

}

}

}

}

3.11 @With

在类的字段上应用 @With 注解之后,将会自动生成一个 withFieldName(newValue) 的方法,该方法会基于 newValue 调用相应构造函数,创建一个当前类对应的实例。@With 注解的定义如下:

@Target({ElementType.FIELD, ElementType.TYPE})

@Retention(RetentionPolicy.SOURCE)

public @interface With {

AccessLevel value() default AccessLevel.PUBLIC;

With.AnyAnnotation[] onMethod() default {};

With.AnyAnnotation[] onParam() default {};

@Deprecated

@Retention(RetentionPolicy.SOURCE)

@Target({})

public @interface AnyAnnotation {

}

}

示例

public class WithDemo {

@With(AccessLevel.PROTECTED)

@NonNull

private final String name;

@With

private final int age;

public WithDemo(String name, int age) {

if (name == null) throw new NullPointerException();

this.name = name;

this.age = age;

}

}

以上代码经过 Lombok 编译后,会生成如下代码:

public class WithDemo {

@NonNull

private final String name;

private final int age;

public WithDemo(String name, int age) {

if (name == null) {

throw new NullPointerException();

} else {

this.name = name;

this.age = age;

}

}

protected WithDemo withName(@NonNull String name) {

if (name == null) {

throw new NullPointerException(“name is marked non-null but is null”);

} else {

return this.name == name ? this : new WithDemo(name, this.age);

}

}

public WithDemo withAge(int age) {

return this.age == age ? this : new WithDemo(this.name, age);

}

}

3.12 其它特性

val

val 用在局部变量前面,相当于将变量声明为 final,此外 Lombok 在编译时还会自动进行类型推断。val 的使用示例:

public class ValExample {

public String example() {

val example = new ArrayList《String》();

example.add(“Hello, World!”);

val foo = example.get(0);

return foo.toLowerCase();

}

public void example2() {

val map = new HashMap《Integer, String》();

map.put(0, “zero”);

map.put(5, “five”);

for (val entry : map.entrySet()) {

System.out.printf(“%d: %s

”, entry.getKey(), entry.getValue());

}

}

}

以上代码等价于:

public class ValExample {

public String example() {

final ArrayList《String》 example = new ArrayList《String》();

example.add(“Hello, World!”);

final String foo = example.get(0);

return foo.toLowerCase();

}

public void example2() {

final HashMap《Integer, String》 map = new HashMap《Integer, String》();

map.put(0, “zero”);

map.put(5, “five”);

for (final Map.Entry《Integer, String》 entry : map.entrySet()) {

System.out.printf(“%d: %s

”, entry.getKey(), entry.getValue());

}

}

}

至此功能强大的 Lombok 工具就介绍完毕了。

source:https://www.yuque.com/fengzheng-fly67/zln9pu/hgu2wb

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    20

    文章

    2997

    浏览量

    115709
  • IDE
    IDE
    +关注

    关注

    0

    文章

    363

    浏览量

    48747
  • Code
    +关注

    关注

    0

    文章

    71

    浏览量

    16160
  • 代码
    +关注

    关注

    30

    文章

    4942

    浏览量

    73167

原文标题:Lombok 使用指南

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    vscode的rtthread micropython插件没有创建工程的图标,为什么?

    我想用micropython开发ESP32,请问我的vscode已经安装了RT-Thread micropython插件,为什么在下方没有创建micropython的“+”图标呢?
    发表于 09-28 13:13

    所见即所得——Luban-Lite VS Code插件开发实现“命令行自由”

    NEWS所见即所得!Luban-LiteVSCode插件指南亲爱的开发者朋友们,你是否还在为嵌入式开发中频繁切换命令行而抓狂?配置环境参数如“走迷宫”,编译烧录还需切换AiBurn?今天,匠芯创为您
    的头像 发表于 08-07 15:38 832次阅读
    所见即所得——Luban-Lite VS Code<b class='flag-5'>插件</b>让<b class='flag-5'>开发</b>实现“命令行自由”

    用 VSCode 编写自己的 KiCad 插件(下)

    “  很多小伙伴都想自己开发 KiCad 插件,但不知从何入手。本文由华秋电子的另一位 KiCad 开发者波波同学撰写,分享了如何快速搭建环境,并开发一个简单的
    的头像 发表于 06-19 11:44 2479次阅读
    用 VSCode 编写自己的 KiCad <b class='flag-5'>插件</b>(下)

    用VSCode编写自己的KiCad插件(上)详细步骤教程

    “  很多小伙伴都想自己开发 KiCad 插件,但不知从何入手。本文由华秋电子的另一位 KiCad 开发者波波同学撰写,分享了如何快速搭建环境,并开发一个简单的
    的头像 发表于 06-17 11:10 2739次阅读
    用VSCode编写自己的KiCad<b class='flag-5'>插件</b>(上)详细步骤教程

    使用DevEcoStudio 开发、编译鸿蒙 NEXT_APP 以及使用中文插件

    # 使用DevEcoStudio 开发、编译鸿蒙 NEXT_APP 以及使用中文插件 #鸿蒙开发工具 #DevEco Studio ## 1. 概述 DevEco Studio 是华为提供
    发表于 06-11 17:18

    [迅为]Linux开发小技巧:Remote - SSH插件

    [迅为]Linux开发小技巧:Remote - SSH插件
    的头像 发表于 04-01 15:46 957次阅读
    [迅为]Linux<b class='flag-5'>开发</b>小技巧:Remote - SSH<b class='flag-5'>插件</b>

    纳雷科技推出Milestone VMS插件

    为解决安防雷达集成开发难、主流平台不适配等问题,纳雷开发Milestone VMS平台插件,与Milestone XProtect大型、中小型、精简版系列产品无缝对接,可助力客户一键完成平台部署。
    的头像 发表于 03-21 11:41 1051次阅读

    edge浏览器识别 latex语法插件

    默认的浏览器是没有latex识别功能的,容易显示为乱码或者源码,无法正常识别。本插件需要在浏览器的扩展程序菜单下安装,能在edge下完美运行。本插件是免费插件
    发表于 03-17 18:03 1次下载

    PREEvision插件使用场景介绍

    PREEvision插件中心(Add-in House)是Vector中国PREEvision团队针对中国用户开发插件网站。用户可以在这里找到各种场景的扩展插件,包括以太网与SOA设
    的头像 发表于 03-14 13:50 1011次阅读
    PREEvision<b class='flag-5'>插件</b>使用场景介绍

    彻底移除Calico网络插件

    0.前言 参考文档:https://github.com/containernetworking/cni Pod网络插件,为了实现Pod网络而需要的插件、组件。由于Kubernetes通过开放
    的头像 发表于 01-23 17:26 1823次阅读
    彻底移除Calico网络<b class='flag-5'>插件</b>

    JetBrains IDE上架开发微信小程序的官方插件

    一直以来,小程序开发者必须安装第三方插件,才能在 JetBrains IDE 中进行小程序开发。在 JetBrains Marketplace 上,有关插件已有约 50 万下载量。 对
    的头像 发表于 01-16 17:15 1082次阅读
    JetBrains IDE上架<b class='flag-5'>开发</b>微信小程序的官方<b class='flag-5'>插件</b>

    环球仪器Omni插件机的优势

    由于传统插件机引脚歪斜,导致抛料率高,减低插件成功率,提高了拋料率。环球仪器的Omni 插件机,则采用两项技术,提高插件成功率,减低拋料率。
    的头像 发表于 01-07 09:12 1454次阅读
    环球仪器Omni<b class='flag-5'>插件</b>机的优势

    使用MCUXpresso for VS Code插件开发Zephyr的hello world

    本期来到Zephyr实战经验演练,小编带着大家一起使用MCUXpresso for VS Code插件开发一个属于Zephyr的hello world。
    的头像 发表于 01-03 09:21 1793次阅读
    使用MCUXpresso for VS Code<b class='flag-5'>插件</b><b class='flag-5'>开发</b>Zephyr的hello world

    Kubernetes的CNI网络插件之flannel

    Kubernetes设计了网络模型,但却将它的实现讲给了网络插件,CNI网络插件最重要的功能就是实现Pod资源能够跨主机通信。
    的头像 发表于 01-02 09:43 1207次阅读

    激光焊锡应用:插件孔的大小对PCB电路板的影响

    在印刷电路板(PCB)设计中,插件孔(也称为通孔或过孔)的尺寸是一个关键参数,它不仅影响到元件的安装,还涉及到电气性能、可靠性以及制造成本等多个方面。插件孔通常用于连接多层PCB上的导电层,或是为
    的头像 发表于 12-31 10:31 1594次阅读
    激光焊锡应用:<b class='flag-5'>插件</b>孔的大小对PCB电路板的影响