百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

SpringBoot Lombok使用详解:从入门到精通(注解最全)

liuian 2025-07-14 18:27 117 浏览

一、Lombok概述与基础使用

1.1 Lombok是什么

Lombok是一个Java库,它通过注解的方式自动生成Java代码(如getter、setter、toString等),从而减少样板代码的编写,提高开发效率。根据我的项目经验,Lombok可以显著减少约30%-50%的JavaBean代码量。

Lombok的核心原理是在编译时通过注解处理器(Annotation Processor)动态修改抽象语法树(AST),生成对应的字节码。这意味着使用Lombok不会增加运行时负担,因为它只在编译阶段工作。

1.2 Lombok的优势与劣势

下表对比了使用Lombok与传统Java开发的差异:

对比维度

传统Java开发

使用Lombok开发

代码量

需要手动编写大量样板代码

自动生成,代码简洁

可读性

业务逻辑被样板代码淹没

聚焦业务逻辑,更清晰

维护性

修改字段需同步修改多个方法

修改字段自动同步

学习曲线

无需额外学习

需要学习注解含义

团队协作

无需特殊配置

需要统一开发环境配置

调试难度

直接查看完整代码

需IDE插件支持查看生成代码

第三方依赖

需要引入Lombok依赖

1.3 环境准备与基础配置

1.3.1 引入Lombok依赖

在Spring Boot项目中引入Lombok非常简单,只需在pom.xml中添加以下依赖:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version> <!-- 使用最新稳定版本 -->
    <scope>provided</scope>
</dependency>

1.3.2 IDE插件安装

由于Lombok在编译时生成代码,为了让IDE能正确识别这些生成的代码,需要安装对应的插件:

  • IntelliJ IDEA: 通过File -> Settings -> Plugins搜索"Lombok Plugin"安装
  • Eclipse: 下载lombok.jar并双击运行安装

1.3.3 基础注解使用

让我们从一个最简单的JavaBean开始,展示Lombok如何简化代码:

传统JavaBean写法:

public class User {
    private Long id;
    private String username;
    private String password;
    
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    // 其他getter/setter...
    
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
    
    @Override
    public boolean equals(Object o) {
        // 冗长的equals实现...
    }
    
    @Override
    public int hashCode() {
        // hashCode实现...
    }
}

使用Lombok后的写法:

import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String password;
}

这个简单的例子展示了Lombok的强大之处 - 一个@Data注解就替代了数十行代码。@Data是一个复合注解,它包含了以下功能:

  • 所有字段的getter(final字段除外)
  • 所有非final字段的setter
  • toString()方法
  • equals()和hashCode()方法
  • 必要的构造函数

二、Lombok核心注解详解

2.1 常用基础注解

2.1.1 @Getter/@Setter

@Getter@Setter是最基础的注解,用于生成getter和setter方法。

public class User {
    @Getter @Setter private Long id;
    
    @Getter(
        value = AccessLevel.PROTECTED // 设置访问级别为protected
    ) 
    @Setter(
        value = AccessLevel.PRIVATE, // 设置访问级别为private
        onMethod_ = @Deprecated // 在生成的方法上添加@Deprecated注解
    )
    private String password;
}

生成的代码相当于:

public class User {
    private Long id;
    private String password;
    
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    protected String getPassword() { return password; }
    @Deprecated
    private void setPassword(String password) { this.password = password; }
}

2.1.2 @ToString

@ToString注解自动生成toString()方法,默认包含所有非静态字段。

@ToString(
    exclude = {"password"}, // 排除password字段
    includeFieldNames = false, // 不包含字段名
    callSuper = true // 包含父类的toString结果
)
public class User extends BaseEntity {
    private Long id;
    private String username;
    private String password;
}

生成的toString()方法输出类似:

User(super=BaseEntity(createdAt=2023-01-01), id=1, username=admin)

2.1.3 @EqualsAndHashCode

@EqualsAndHashCode生成equals()和hashCode()方法实现。

@EqualsAndHashCode(
    exclude = {"createdAt"}, // 排除createdAt字段
    callSuper = true // 包含父类的equals和hashCode
)
public class User extends BaseEntity {
    private Long id;
    private String username;
    private Date createdAt;
}

2.1.4 @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor

Lombok提供了三种构造器生成方式:

@NoArgsConstructor // 无参构造器
@RequiredArgsConstructor // 为所有final或@NonNull字段生成构造器
@AllArgsConstructor // 全参构造器
public class User {
    private Long id;
    @NonNull private String username;
    private final String role = "USER";
}

2.2 实用注解

2.2.1 @Data

@Data是一个复合注解,相当于:

  • @Getter
  • @Setter
  • @ToString
  • @EqualsAndHashCode
  • @RequiredArgsConstructor
@Data
public class Product {
    private Long id;
    private String name;
    private BigDecimal price;
}

2.2.2 @Builder

@Builder实现了建造者模式,提供了一种更优雅的对象创建方式。

@Builder
public class Order {
    private Long id;
    private String orderNo;
    private BigDecimal amount;
}

// 使用方式
Order order = Order.builder()
    .id(1L)
    .orderNo("20230101123456")
    .amount(new BigDecimal("100.00"))
    .build();

2.2.3 @Slf4j

@Slf4j自动生成日志对象,避免了手动创建Logger的繁琐。

@Slf4j
public class OrderService {
    public void createOrder() {
        log.info("Creating order...");
        try {
            // 业务逻辑
            log.debug("Order created successfully");
        } catch (Exception e) {
            log.error("Failed to create order", e);
        }
    }
}

2.3 高级注解

2.3.1 @Value

@Value是不变类(immutable class)的快捷方式,相当于:

  • final字段
  • 只有getter
  • 全参构造器
  • toString/equals/hashCode
@Value
public class ImmutableUser {
    Long id;
    String username;
    String role;
}

2.3.2 @SneakyThrows

@SneakyThrows可以偷偷抛出受检异常而不在方法签名中声明。

public class FileUtil {
    @SneakyThrows
    public static String readFile(String path) {
        return Files.readString(Paths.get(path));
    }
}

2.3.3 @Cleanup

@Cleanup自动管理资源,确保资源使用后被正确关闭。

public class FileUtil {
    @SneakyThrows
    public static void copyFile(String src, String dest) {
        @Cleanup InputStream in = new FileInputStream(src);
        @Cleanup OutputStream out = new FileOutputStream(dest);
        in.transferTo(out);
    }
}

三、Lombok在Spring Boot中的实战应用

3.1 实体类(Entity)开发

在Spring Data JPA中,实体类通常需要大量样板代码,Lombok可以极大简化这一过程。

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, length = 100)
    private String name;
    
    @Column(precision = 10, scale = 2)
    private BigDecimal price;
    
    @Column(updatable = false)
    private LocalDateTime createdAt;
    
    @Version
    private Integer version;
    
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
    }
}

3.2 DTO/VO对象开发

数据传输对象(DTO)和值对象(VO)通常只包含数据和简单逻辑,非常适合使用Lombok。

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
    private Long id;
    private String username;
    private String email;
    private String phone;
    
    @Data
    public static class Address {
        private String province;
        private String city;
        private String detail;
    }
}

3.3 控制器(Controller)开发

在Controller中,我们经常需要记录日志,@Slf4j可以简化这一过程。

@RestController
@RequestMapping("/api/users")
@Slf4j
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    
    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        log.debug("Fetching user with id: {}", id);
        return ResponseEntity.ok(userService.getUserById(id));
    }
    
    @PostMapping
    public ResponseEntity<Void> createUser(@Valid @RequestBody UserDTO userDTO) {
        log.info("Creating new user: {}", userDTO.getUsername());
        userService.createUser(userDTO);
        return ResponseEntity.created(URI.create("/api/users")).build();
    }
}

3.4 服务层(Service)开发

服务层通常需要事务管理和日志记录,Lombok也能提供帮助。

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional
public class OrderServiceImpl implements OrderService {
    private final OrderRepository orderRepository;
    private final ProductRepository productRepository;
    
    @Override
    public OrderDTO createOrder(OrderCreateDTO createDTO) {
        log.info("Creating order for user: {}", createDTO.getUserId());
        
        Product product = productRepository.findById(createDTO.getProductId())
            .orElseThrow(() -> {
                log.error("Product not found: {}", createDTO.getProductId());
                return new ResourceNotFoundException("Product not found");
            });
        
        Order order = Order.builder()
            .userId(createDTO.getUserId())
            .productId(product.getId())
            .amount(product.getPrice())
            .status(OrderStatus.CREATED)
            .build();
        
        return convertToDTO(orderRepository.save(order));
    }
    
    private OrderDTO convertToDTO(Order order) {
        // 转换逻辑
    }
}

四、Lombok高级特性与最佳实践

4.1 自定义Lombok配置

在项目根目录下创建lombok.config文件,可以自定义Lombok行为:

# 将生成的构造器设为protected
lombok.anyConstructor.suppressConstructorProperties = true

# 禁止使用@EqualsAndHashCode的callSuper=true警告
config.stopBubbling = true
lombok.equalsAndHashCode.callSuper = warn

# 全局配置@ToString不包含字段名
lombok.toString.includeFieldNames = false

4.2 与MapStruct集成

MapStruct是一个代码生成器,用于Java Bean之间的映射,与Lombok配合使用效果极佳。

@Mapper(componentModel = "spring")
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    
    @Mapping(source = "username", target = "name")
    UserDTO toDTO(User user);
    
    @Mapping(source = "name", target = "username")
    User toEntity(UserDTO userDTO);
}

@Data
public class User {
    private Long id;
    private String username;
    private String password;
}

@Data
public class UserDTO {
    private Long id;
    private String name;
    private String email;
}

4.3 与Jackson集成

Lombok与Jackson JSON库可以很好地配合使用,但需要注意一些细节。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL) // 只包含非null字段
public class ApiResponse<T> {
    private Integer code;
    private String message;
    private T data;
    
    @JsonIgnore // 忽略这个getter
    public boolean isSuccess() {
        return code == 200;
    }
}

4.4 常见问题与解决方案

4.4.1 与JPA的兼容性问题

当使用JPA的懒加载(Lazy Loading)时,直接调用toString()可能导致异常。解决方案:

@Entity
@Data
@ToString(exclude = {"orders"}) // 排除关联集合
public class User {
    @Id
    @GeneratedValue
    private Long id;
    
    private String name;
    
    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    private List<Order> orders;
}

4.4.2 与继承体系的问题

在继承体系中,正确配置callSuper非常重要:

@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AdminUser extends User {
    private String privilege;
}

4.4.3 性能考虑

虽然Lombok在编译时生成代码,但某些复杂注解(如@Builder)生成的代码量较大,在性能敏感的场景需要权衡使用。

五、Lombok原理深入解析

5.1 Lombok工作原理

Lombok的工作流程可以用以下序列图表示:

Java CompilerLombok Annotation ProcessorIDEDeveloperJava CompilerLombok Annotation ProcessorIDEDeveloper编写带有Lombok注解的Java文件请求解析AST修改AST返回修改后的AST提供增强的代码视图显示增强后的代码效果编译代码再次处理AST生成最终字节码

5.2 注解处理流程

Lombok的注解处理发生在编译期的以下阶段:

  1. 解析阶段:Java编译器解析源代码生成AST
  2. 注解处理阶段:Lombok的注解处理器修改AST
  3. 分析生成阶段:基于修改后的AST生成字节码

5.3 与IDE的集成原理

IDE通过Lombok插件实现以下功能:

  • 在编辑器中显示生成的代码
  • 提供代码补全建议
  • 支持导航到"虚拟"的生成方法

六、Lombok替代方案与对比

6.1 手动编写代码

优点:

  • 完全控制代码细节
  • 无需额外依赖
  • 更好的可调试性

缺点:

  • 代码冗长
  • 维护成本高
  • 容易出错

6.2 IDE代码生成

优点:

  • 可视化的生成过程
  • 可以选择性生成

缺点:

  • 生成的代码仍需保留在源文件中
  • 字段变更时需要重新生成
  • 不同IDE生成风格可能不一致

6.3 其他代码生成工具

工具

特点

适用场景

Lombok

注解驱动,编译时生成,无运行时依赖

日常JavaBean开发

AutoValue

专注于生成不可变类

需要不可变对象的场景

Immutables

类似AutoValue但功能更丰富

复杂不可变对象需求

Kotlin

语言层面支持数据类(data class)

使用Kotlin的项目

Record类(Java14+)

Java语言内置的简化数据载体定义

Java 14+的简单数据传输对象

七、Lombok在企业项目中的实践建议

7.1 项目规范制定

  1. 注解使用规范
  2. 实体类:使用@Data+@Builder+@NoArgsConstructor+@AllArgsConstructor
  3. DTO:使用@Value@Data+@Builder
  4. 工具类:使用@UtilityClass
  5. 代码风格统一
  6. 统一配置lombok.config
  7. 规定toString的格式
  8. 统一equals/hashCode的实现方式

7.2 团队协作注意事项

  1. 新成员培训
  2. 基础注解的含义
  3. IDE插件的安装配置
  4. 常见问题的解决方法
  5. 代码审查要点
  6. 检查是否过度使用Lombok
  7. 验证callSuper的正确设置
  8. 确认排除字段的合理性

7.3 性能优化建议

  1. 避免在性能关键路径使用复杂注解
  2. @ToString在大对象上可能影响性能
  3. @EqualsAndHashCode在大型集合比较时注意
  4. 合理选择注解组合
  5. 只使用需要的注解,而不是简单的@Data
  6. 考虑使用@Value替代@Data创建不可变对象

八、完整实战案例

8.1 电商系统用户模块

// 实体类
@Entity
@Table(name = "users")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString(exclude = {"password", "orders"})
@EqualsAndHashCode(callSuper = true, exclude = {"orders"})
public class User extends BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true, length = 50)
    private String username;
    
    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false, unique = true)
    private String email;
    
    @Column(name = "phone_number", length = 20)
    private String phoneNumber;
    
    @Enumerated(EnumType.STRING)
    private UserStatus status;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    @Builder.Default
    private List<Order> orders = new ArrayList<>();
    
    @Embedded
    private Address address;
    
    @Version
    private Integer version;
}

// DTO类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserDTO {
    private Long id;
    private String username;
    private String email;
    private String phoneNumber;
    private UserStatus status;
    private AddressDTO address;
    
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class AddressDTO {
        private String province;
        private String city;
        private String street;
        private String zipCode;
    }
}

// 服务类
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final UserMapper userMapper;
    
    @Override
    public UserDTO getUserById(Long id) {
        log.debug("Fetching user with id: {}", id);
        return userRepository.findById(id)
            .map(userMapper::toDTO)
            .orElseThrow(() -> new ResourceNotFoundException("User not found"));
    }
    
    @Override
    @Transactional
    public UserDTO createUser(UserCreateDTO createDTO) {
        log.info("Creating new user: {}", createDTO.getUsername());
        
        if (userRepository.existsByUsername(createDTO.getUsername())) {
            throw new BusinessException("Username already exists");
        }
        
        User user = User.builder()
            .username(createDTO.getUsername())
            .password(passwordEncoder.encode(createDTO.getPassword()))
            .email(createDTO.getEmail())
            .phoneNumber(createDTO.getPhoneNumber())
            .status(UserStatus.ACTIVE)
            .address(convertAddress(createDTO.getAddress()))
            .build();
        
        return userMapper.toDTO(userRepository.save(user));
    }
    
    private Address convertAddress(UserDTO.AddressDTO addressDTO) {
        // 转换逻辑
    }
}

8.2 RESTful API响应封装

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiResult<T> {
    private long timestamp;
    private String status;
    private String code;
    private String message;
    private T data;
    private String path;
    
    public static <T> ApiResult<T> success() {
        return success(null);
    }
    
    public static <T> ApiResult<T> success(T data) {
        return ApiResult.<T>builder()
            .timestamp(System.currentTimeMillis())
            .status("success")
            .code("200")
            .data(data)
            .build();
    }
    
    public static ApiResult<?> error(String code, String message) {
        return error(code, message, null);
    }
    
    public static ApiResult<?> error(String code, String message, String path) {
        return ApiResult.builder()
            .timestamp(System.currentTimeMillis())
            .status("error")
            .code(code)
            .message(message)
            .path(path)
            .build();
    }
}

// 使用示例
@RestController
@RequestMapping("/api/users")
@Slf4j
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    
    @GetMapping("/{id}")
    public ApiResult<UserDTO> getUser(@PathVariable Long id) {
        return ApiResult.success(userService.getUserById(id));
    }
    
    @ExceptionHandler(BusinessException.class)
    public ApiResult<?> handleBusinessException(BusinessException e, 
                                             HttpServletRequest request) {
        log.error("Business exception: {}", e.getMessage(), e);
        return ApiResult.error("400", e.getMessage(), 
                             request.getRequestURI());
    }
}

九、Lombok的未来与发展

9.1 Java Record类与Lombok

Java 14引入的Record类在某些场景下可以替代Lombok:

// 使用Record
public record UserRecord(Long id, String username, String email) {}

// 使用Lombok
@Data
@AllArgsConstructor
public class UserLombok {
    private Long id;
    private String username;
    private String email;
}

比较:

  • Record更简洁,但功能有限(不可变,有限的自定义能力)
  • Lombok更灵活,支持可变对象和各种自定义

9.2 Lombok的未来发展方向

  1. 更好的Java新版本兼容性
  2. 更智能的代码生成策略
  3. 增强与其他工具链的集成
  4. 可能的元注解支持

9.3 何时选择/不选择Lombok

适合使用Lombok的场景

  • 大量的POJO/DTO/VO类
  • 需要快速原型开发
  • 团队统一规范并接受Lombok

不适合使用Lombok的场景

  • 对字节码有严格要求的场景
  • 需要精细控制生成的代码
  • 项目成员不熟悉Lombok且学习成本高

十、总结与个人建议

经过多年的Java开发和Lombok使用经验,我认为:

  1. 适度使用:Lombok是很好的生产力工具,但不要滥用。在简单DTO/实体类上使用,在复杂业务类上谨慎使用。
  2. 团队共识:确保团队成员都理解并接受Lombok,统一配置和风格。
  3. 了解原理:理解Lombok的工作原理有助于解决遇到的问题。
  4. 结合其他工具:与MapStruct、Jackson等工具配合使用效果更佳。
  5. 关注替代方案:随着Java语言发展(如Record类),评估是否可以用语言特性替代Lombok。

Lombok不是银弹,但在正确使用的场景下,它能显著提高开发效率,减少样板代码,让我们更专注于业务逻辑的实现。希望这篇全面的指南能帮助你在Spring Boot项目中更好地利用Lombok。

关注我?别别别,我怕你笑出腹肌找我赔钱。


头条对markdown的文章显示不太友好,想了解更多的可以关注微信公众号:“Eric的技术杂货库”,有更多的干货以及资料下载。

相关推荐

万能bt搜索引擎网站(bt万能搜索破解版)

最好用最全面的的磁力搜索引擎是磁力熊,因为它是一个内容丰富、还是功能最为强大的一个磁力搜索网站,通过它不仅仅可以搜索磁力熊磁力熊,是一个内容丰富、功能最为强大的一个磁力搜索网站,通过它不仅仅可以搜索...

苹果id注册官网登录(appleid官网注册账号)

浏览器访问申请AppleID官网注册  1、在浏览器地址栏上面输入:“https://appleid.apple.com/cn”,进入申请AppleID官网界面,点击下面的“创建AppleID...

苹果笔记本怎么下载windows系统

方法一:使用BootCamp方法二:使用虚拟机方法三:使用Wine简介BootCamp是苹果电脑自带的一个软件,可以帮助用户在Mac上安装Windows操作系统。虚拟机则是运行在Mac上的一个软件...

华硕电脑激活码(华硕电脑windows激活码在哪里)

你所说的应该是系统激活密钥吧华硕OEM密钥就行!HomePremium(家庭高级版):27GBM-Y4QQC-JKHXW-D9W83-FJQKDUltimate(旗舰版):6K2KY-BF...

wifi如何防止别人蹭网(wifi如何防止别人蹭网呢)

防止WIFI被蹭网的方法1、家庭的wifi信号,一般是通过设置无线路由器发射出来。在设置无线路由器时,一定要注意设置无线密码的安全强度。最好含有大小写字母加数字的组合,不要设置连续数字,比如“1234...

无线ap安装示意图(无线ap如何安装方法)

商用无线ap安装完成后连接ap应用添加wifi网络信号将无线网卡插入电脑USBWindows7/8系统下,网卡安装成功后直接进行软件安装...2.继续安装类型,推荐保持默认选择,点击“下一步”继续安装...

miui官网开发版下载(小米miui开发版下载)

你好,miui12开发版下载方式如下1打开浏览器,登录小米Rom官网,2进去之后搜索自己的手机型号,3点击进入就可以看到所有发布过的miui版本4点击想要的12版本下载即可。现在的MIUI开发版需要申...

惠普台式机进入bios设置u盘启动
惠普台式机进入bios设置u盘启动

设置u盘启动的步骤如下:1、首先,将u盘插入hp台式机的USB接口处。2、开机快速断续的按F10键进入BIOS设置界面。3、将光标移到【BootDevicePriority】选项按回车键进入。4、选择【HDDGroupBootPr...

2026-01-15 00:37 liuian

云手机免费版无限挂机怎么用

1、登陆后,如果需要挂网页游戏,点击服务器的左下角,找到IE浏览器,然后打开网页游戏,登陆你的账号就行了,不要关闭IE浏览器,你的网页游戏就会24小时挂在云服务器上面。2、如果想要挂机,打开IE浏览器...

上海最近3天疫情情况(上海近几天的新冠疫情情况)

根据国家卫健委的每天疫情通报及上海市的疫情通报,上海没有一个区属中高风险地区,所以从上海任何一个区返乡都不需要隔离14天。上海这么大的城市,每天人来人往的Ill流不息,能继续做到区级地区没有中高级风险...

windows media player怎么下载

方法如下:在安装WMP11时只是把C:\DocumentsandSettings\AllUsers\ApplicationData\WindowsGenuineAdvantage\data...

during(during用法)

during用来表示一段时间,其意义大致相当于in的用法。一般来说,凡是能用in的地方,也可以用during.例如:Hecametoseemeduringmyabsence.Don’t...

深圳电脑城在哪里(深圳电脑卖场)

龙岗:世纪电脑城,平湖电脑城,京科电脑城坪山新区:坪山电脑城龙华:观澜电脑城,大浪电脑城,宏华电脑城,龙华电子城宝安区:赛格电子城,宝安电子城,丰明电脑城,沙井电子城龙岗中心区那边有两个电子城,...

电脑上怎么清理c盘垃圾(电脑里怎么清理c盘的东西)

C:\ProgramFiles\WindowsApps(隐藏文件夹)。打开“此电脑”,点击“查看”,勾选“隐藏的项目”,即可查看隐藏文件。为保证文件安全,此文件夹需要获取权限才能操作。获取方式...

手机哪个杀毒软件最好用

杀毒软件我有用过好几种用过之觉得体验感及安全性来说人喜欢推荐腾讯手机管家功能比较全面监控流量、查杀病毒、保护隐私等等界面也比较漂亮重点还要定期扫描同时也要轻易点开别人发链接之类软件有提示危险绝对要点开...