最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot自定義注解從入門到實(shí)戰(zhàn)指南

 更新時(shí)間:2025年12月27日 11:55:40   作者:海南java第二人  
本文介紹了SpringBoot中自定義注解的設(shè)計(jì)、實(shí)現(xiàn)與應(yīng)用技巧,涵蓋了注解基礎(chǔ)、創(chuàng)建自定義注解、注解處理器實(shí)現(xiàn)方案、高級(jí)注解特性、性能優(yōu)化與最佳實(shí)踐、實(shí)戰(zhàn)案例、測試策略、常見問題與解決方案以及總結(jié)與最佳實(shí)踐,感興趣的朋友跟隨小編一起看看吧

引言:為什么需要自定義注解?

在現(xiàn)代化Spring Boot應(yīng)用開發(fā)中,注解已經(jīng)成為不可或缺的編程元素。自定義注解不僅僅是語法糖,更是實(shí)現(xiàn)代碼解耦、增強(qiáng)可讀性、統(tǒng)一業(yè)務(wù)規(guī)范實(shí)現(xiàn)AOP編程的利器。通過本文,您將全面掌握Spring Boot自定義注解的設(shè)計(jì)、實(shí)現(xiàn)與應(yīng)用技巧。

一、注解基礎(chǔ):元注解深度剖析

1.1 什么是元注解?

元注解(Meta-Annotation)是用于定義其他注解的注解。Java提供了5個(gè)標(biāo)準(zhǔn)元注解,它們是構(gòu)建自定義注解的基石。

1.2 核心元注解詳解

@Target:定義注解使用范圍

@Target(ElementType.METHOD)  // 僅可用于方法
@Target({ElementType.TYPE, ElementType.METHOD})  // 可用于類和方法

常用ElementType值:

  • TYPE:類、接口、枚舉
  • FIELD:字段
  • METHOD:方法
  • PARAMETER:參數(shù)
  • CONSTRUCTOR:構(gòu)造器

@Retention:定義注解生命周期

@Retention(RetentionPolicy.RUNTIME)  // 運(yùn)行時(shí)保留,可通過反射獲取

三種保留策略對(duì)比:

策略編譯時(shí)類文件運(yùn)行時(shí)典型用途
SOURCE???Lombok注解
CLASS???字節(jié)碼增強(qiáng)
RUNTIME???Spring注解

@Documented:包含在JavaDoc中

@Inherited:允許子類繼承

@Repeatable:可重復(fù)使用

二、創(chuàng)建自定義注解:從簡單到復(fù)雜

2.1 基礎(chǔ)注解創(chuàng)建

/**
 * 簡單日志注解示例
 * 用于標(biāo)記需要記錄日志的方法
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Loggable {
    // 無參數(shù)注解
}

2.2 帶參數(shù)的注解

/**
 * 緩存注解
 * 用于方法結(jié)果緩存
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {
    // 必填參數(shù)
    String key();
    // 可選參數(shù)(帶默認(rèn)值)
    long expire() default 300L;
    // 枚舉類型參數(shù)
    CacheType type() default CacheType.LOCAL;
    // 數(shù)組類型參數(shù)
    String[] excludeParams() default {};
    // 注解支持的數(shù)據(jù)類型:
    // 1. 基本類型(int, long, double, boolean等)
    // 2. String
    // 3. Class
    // 4. Enum
    // 5. Annotation
    // 6. 以上類型的數(shù)組
}

2.3 實(shí)戰(zhàn):創(chuàng)建業(yè)務(wù)注解

/**
 * 數(shù)據(jù)權(quán)限注解
 * 用于控制數(shù)據(jù)訪問權(quán)限
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataPermission {
    /**
     * 權(quán)限類型
     */
    DataScope scope() default DataScope.ALL;
    /**
     * 權(quán)限字段(數(shù)據(jù)庫字段名)
     */
    String field() default "create_user_id";
    /**
     * 自定義過濾條件(SpEL表達(dá)式)
     */
    String condition() default "";
    /**
     * 數(shù)據(jù)權(quán)限范圍枚舉
     */
    enum DataScope {
        ALL,        // 全部數(shù)據(jù)
        DEPARTMENT, // 本部門數(shù)據(jù)
        SELF,       // 本人數(shù)據(jù)
        CUSTOM      // 自定義
    }
}

三、注解處理器實(shí)現(xiàn)方案

3.1 AOP切面處理(最常用)

/**
 * 日志注解切面處理器
 */
@Aspect
@Component
@Slf4j
public class LogAspect {
    /**
     * 環(huán)繞通知:處理@Loggable注解
     */
    @Around("@annotation(com.example.annotation.Loggable)")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().getName();
        log.info("方法 {} 開始執(zhí)行,參數(shù): {}", methodName, joinPoint.getArgs());
        try {
            Object result = joinPoint.proceed();
            long endTime = System.currentTimeMillis();
            log.info("方法 {} 執(zhí)行成功,耗時(shí): {}ms, 結(jié)果: {}", 
                    methodName, endTime - startTime, result);
            return result;
        } catch (Exception e) {
            log.error("方法 {} 執(zhí)行異常: {}", methodName, e.getMessage());
            throw e;
        }
    }
}

3.2 攔截器處理

/**
 * 權(quán)限注解攔截器
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 檢查方法上的@RequirePermission注解
        RequirePermission annotation = method.getAnnotation(RequirePermission.class);
        if (annotation != null) {
            return checkPermission(annotation.value(), request);
        }
        return true;
    }
}

3.3 BeanPostProcessor處理

/**
 * 字段驗(yàn)證處理器
 * 使用BeanPostProcessor處理字段級(jí)注解
 */
@Component
public class ValidationBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Class<?> clazz = bean.getClass();
        // 處理字段注解
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            processFieldAnnotations(field, bean);
        }
        // 處理方法注解
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            processMethodAnnotations(method, bean);
        }
        return bean;
    }
}

四、高級(jí)注解特性

4.1 組合注解(注解的注解)

/**
 * RESTful GET接口組合注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value = "查詢接口")
@Loggable
public @interface RestGet {
    String value() default "";
    boolean requireAuth() default true;
}
// 使用示例
@RestGet("/users/{id}")
public User getUser(@PathVariable Long id) {
    // 方法自動(dòng)擁有所有組合注解的功能
}

4.2 條件注解

/**
 * 環(huán)境條件注解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnEnvironmentCondition.class)
public @interface ConditionalOnEnvironment {
    String[] profiles();
    Logical logical() default Logical.OR;
}
/**
 * 條件判斷實(shí)現(xiàn)
 */
public class OnEnvironmentCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        // 實(shí)現(xiàn)環(huán)境條件判斷邏輯
        return true;
    }
}

4.3 SpEL表達(dá)式支持

/**
 * 支持SpEL表達(dá)式的注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Lockable {
    /**
     * 鎖的key,支持SpEL表達(dá)式
     * 示例: #user.id, #args[0], #p0
     */
    String key();
    /**
     * 鎖的過期時(shí)間(秒)
     */
    long expire() default 30L;
}
/**
 * SpEL解析器工具類
 */
@Component
public class SpELParser {
    private final ExpressionParser parser = new SpelExpressionParser();
    public String parse(String expression, Method method, Object[] args) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        // 設(shè)置參數(shù)
        String[] paramNames = getParameterNames(method);
        for (int i = 0; i < paramNames.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        // 設(shè)置特殊變量
        context.setVariable("args", args);
        return parser.parseExpression(expression)
                    .getValue(context, String.class);
    }
}

五、性能優(yōu)化與最佳實(shí)踐

5.1 反射性能優(yōu)化

/**
 * 注解緩存管理器
 * 避免重復(fù)反射調(diào)用,提升性能
 */
@Component
public class AnnotationCacheManager {
    private final Map<Method, Map<Class<?>, Annotation>> methodCache = 
            new ConcurrentHashMap<>();
    private final Map<Class<?>, Map<Class<?>, Annotation>> classCache = 
            new ConcurrentHashMap<>();
    /**
     * 獲取方法注解(帶緩存)
     */
    @SuppressWarnings("unchecked")
    public <T extends Annotation> T getMethodAnnotation(Method method, 
                                                       Class<T> annotationClass) {
        return (T) methodCache
                .computeIfAbsent(method, k -> new ConcurrentHashMap<>())
                .computeIfAbsent(annotationClass, 
                               k -> method.getAnnotation(annotationClass));
    }
    /**
     * 批量獲取注解信息
     */
    public AnnotationInfo getAnnotationInfo(Method method) {
        return AnnotationInfo.builder()
                .method(method)
                .annotations(Arrays.asList(method.getAnnotations()))
                .build();
    }
}

5.2 線程安全設(shè)計(jì)

/**
 * 線程安全的注解處理器
 */
@Component
public class ThreadSafeAnnotationProcessor {
    private final ThreadLocal<AnnotationContext> contextHolder = 
            new ThreadLocal<>();
    public void processWithContext(Runnable task, AnnotationContext context) {
        AnnotationContext oldContext = contextHolder.get();
        contextHolder.set(context);
        try {
            task.run();
        } finally {
            contextHolder.set(oldContext);
        }
    }
    /**
     * 注解上下文
     */
    @Data
    public static class AnnotationContext {
        private String currentUser;
        private Map<String, Object> attributes = new HashMap<>();
    }
}

5.3 錯(cuò)誤處理與回退

/**
 * 容錯(cuò)的注解處理器
 */
@Component
public class FaultTolerantAnnotationProcessor {
    @Slf4j
    public Object processWithFallback(ProceedingJoinPoint joinPoint, 
                                     Annotation annotation) {
        try {
            return processAnnotation(joinPoint, annotation);
        } catch (AnnotationProcessingException e) {
            log.warn("注解處理失敗,使用默認(rèn)處理: {}", e.getMessage());
            return fallbackProcess(joinPoint);
        } catch (Exception e) {
            log.error("注解處理發(fā)生未知異常", e);
            throw e;
        }
    }
    private Object fallbackProcess(ProceedingJoinPoint joinPoint) 
            throws Throwable {
        // 默認(rèn)處理邏輯
        return joinPoint.proceed();
    }
}

六、實(shí)戰(zhàn)案例:完整的權(quán)限控制注解系統(tǒng)

6.1 定義權(quán)限注解

/**
 * 權(quán)限控制注解體系
 */
// 角色要求注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireRole {
    String[] value();
    Logical logical() default Logical.AND;
}
// 權(quán)限要求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
    String value();
    String[] actions() default {"read", "write"};
}
// 數(shù)據(jù)權(quán)限注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataAuth {
    String type();
    String field() default "owner_id";
}

6.2 實(shí)現(xiàn)權(quán)限注解處理器

/**
 * 權(quán)限注解統(tǒng)一處理器
 */
@Aspect
@Component
@Order(1)  // 高優(yōu)先級(jí)
public class SecurityAspect {
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private DataAuthService dataAuthService;
    /**
     * 權(quán)限檢查切入點(diǎn)
     */
    @Pointcut("@annotation(com.example.annotation.RequireRole) || " +
              "@annotation(com.example.annotation.RequirePermission)")
    public void securityPointcut() {}
    /**
     * 數(shù)據(jù)權(quán)限切入點(diǎn)
     */
    @Pointcut("@annotation(com.example.annotation.DataAuth)")
    public void dataAuthPointcut() {}
    /**
     * 權(quán)限前置檢查
     */
    @Before("securityPointcut()")
    public void checkSecurity(JoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        // 檢查角色權(quán)限
        checkRolePermission(method);
        // 檢查操作權(quán)限
        checkOperationPermission(method);
    }
    /**
     * 數(shù)據(jù)權(quán)限環(huán)繞處理
     */
    @Around("dataAuthPointcut()")
    public Object handleDataAuth(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        DataAuth dataAuth = method.getAnnotation(DataAuth.class);
        // 設(shè)置數(shù)據(jù)權(quán)限上下文
        DataAuthContext context = DataAuthContext.builder()
                .type(dataAuth.type())
                .field(dataAuth.field())
                .build();
        DataAuthHolder.setContext(context);
        try {
            return joinPoint.proceed();
        } finally {
            DataAuthHolder.clear();
        }
    }
}

6.3 使用示例

@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    @RequireRole({"ADMIN", "MANAGER"})
    @RequirePermission("user:read")
    @DataAuth(type = "user", field = "id")
    public User getUser(@PathVariable Long id) {
        // 方法會(huì)自動(dòng)受到權(quán)限控制
        return userService.getUserById(id);
    }
    @PostMapping
    @RequireRole("ADMIN")
    @RequirePermission(value = "user:write", actions = {"create"})
    @Loggable
    public User createUser(@RequestBody UserDTO userDTO) {
        // 同時(shí)具有日志和權(quán)限控制
        return userService.createUser(userDTO);
    }
}

七、測試策略

7.1 單元測試

@SpringBootTest
public class AnnotationTest {
    @Test
    public void testAnnotationPresence() {
        Method method = UserController.class.getMethod("getUser", Long.class);
        assertTrue(method.isAnnotationPresent(RequireRole.class));
        assertTrue(method.isAnnotationPresent(RequirePermission.class));
        RequireRole roleAnnotation = method.getAnnotation(RequireRole.class);
        assertArrayEquals(new String[]{"ADMIN", "MANAGER"}, roleAnnotation.value());
    }
    @Test
    public void testAnnotationProcessing() {
        // 測試注解處理邏輯
        UserController controller = new UserController();
        // 模擬AOP處理
        SecurityAspect aspect = new SecurityAspect();
        // ... 測試注解處理邏輯
    }
}

7.2 集成測試

@WebMvcTest(UserController.class)
@AutoConfigureMockMvc
public class AnnotationIntegrationTest {
    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private UserService userService;
    @Test
    @WithMockUser(roles = "ADMIN")
    public void testAuthorizedAccess() throws Exception {
        when(userService.getUserById(1L)).thenReturn(new User());
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isOk());
    }
    @Test
    @WithMockUser(roles = "USER")  // 權(quán)限不足
    public void testUnauthorizedAccess() throws Exception {
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isForbidden());
    }
}

八、常見問題與解決方案

8.1 注解繼承問題

問題:默認(rèn)情況下,注解不會(huì)被繼承

解決方案

// 方案1:使用@Inherited元注解
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotation {
    String value();
}
// 方案2:手動(dòng)檢查繼承鏈
public static <A extends Annotation> A findAnnotationRecursively(
        Class<?> clazz, Class<A> annotationType) {
    // 檢查當(dāng)前類
    A annotation = clazz.getAnnotation(annotationType);
    if (annotation != null) return annotation;
    // 檢查接口
    for (Class<?> ifc : clazz.getInterfaces()) {
        annotation = findAnnotationRecursively(ifc, annotationType);
        if (annotation != null) return annotation;
    }
    // 檢查父類
    Class<?> superClass = clazz.getSuperclass();
    if (superClass != null && superClass != Object.class) {
        return findAnnotationRecursively(superClass, annotationType);
    }
    return null;
}

8.2 注解參數(shù)驗(yàn)證

/**
 * 帶參數(shù)驗(yàn)證的注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RangeValidator.class)
public @interface ValidRange {
    String message() default "值超出有效范圍";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    double min() default 0;
    double max() default Double.MAX_VALUE;
}
/**
 * 驗(yàn)證器實(shí)現(xiàn)
 */
public class RangeValidator implements ConstraintValidator<ValidRange, Number> {
    private double min;
    private double max;
    @Override
    public void initialize(ValidRange constraintAnnotation) {
        this.min = constraintAnnotation.min();
        this.max = constraintAnnotation.max();
    }
    @Override
    public boolean isValid(Number value, ConstraintValidatorContext context) {
        if (value == null) return true;
        double doubleValue = value.doubleValue();
        return doubleValue >= min && doubleValue <= max;
    }
}

九、總結(jié)與最佳實(shí)踐

9.1 設(shè)計(jì)原則

  1. 單一職責(zé):每個(gè)注解應(yīng)只負(fù)責(zé)一個(gè)明確的功能
  2. 合理命名:注解名稱應(yīng)清晰表達(dá)其用途(名詞或形容詞)
  3. 完整文檔:使用JavaDoc詳細(xì)說明每個(gè)參數(shù)的含義
  4. 向后兼容:已發(fā)布的注解應(yīng)保持兼容性
  5. 適度使用:避免過度使用注解導(dǎo)致代碼難以理解

9.2 性能建議

  1. 緩存反射結(jié)果:避免重復(fù)的反射調(diào)用
  2. 懶加載:延遲初始化昂貴的資源
  3. 使用索引:Spring的類路徑索引加速注解掃描
  4. 異步處理:耗時(shí)操作使用異步處理

9.3 擴(kuò)展建議

  1. 與Spring生態(tài)集成:充分利用Spring的擴(kuò)展點(diǎn)
  2. 支持SpEL:提供靈活的配置能力
  3. 提供工具類:簡化注解的使用和測試
  4. 監(jiān)控與統(tǒng)計(jì):記錄注解的使用情況

結(jié)語

Spring Boot自定義注解是框架強(qiáng)大擴(kuò)展能力的體現(xiàn)。通過合理設(shè)計(jì)和實(shí)現(xiàn)自定義注解,可以顯著提升代碼質(zhì)量、降低維護(hù)成本、統(tǒng)一技術(shù)規(guī)范。本文從基礎(chǔ)到高級(jí),從理論到實(shí)踐,全面介紹了自定義注解的各個(gè)方面,希望能為您的Spring Boot開發(fā)之旅提供有力支持。

記住,注解不是目的,而是手段。始終關(guān)注業(yè)務(wù)價(jià)值,合理運(yùn)用技術(shù)手段,才是優(yōu)秀工程師的追求。

如需獲取更多關(guān)于Spring IoC容器深度解析、Bean生命周期管理、循環(huán)依賴解決方案、條件化配置等內(nèi)容,請(qǐng)持續(xù)關(guān)注本專欄《Spring核心技術(shù)深度剖析》系列文章。

到此這篇關(guān)于Spring Boot自定義注解從入門到實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Boot自定義注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java經(jīng)典面試題最全匯總208道(三)

    Java經(jīng)典面試題最全匯總208道(三)

    這篇文章主要介紹了Java經(jīng)典面試題最全匯總208道(三),本文章內(nèi)容詳細(xì),該模塊分為了六個(gè)部分,本次為第三部分,需要的朋友可以參考下
    2023-01-01
  • SpringBoot監(jiān)控所有線程池的四種解決方案及代碼案例

    SpringBoot監(jiān)控所有線程池的四種解決方案及代碼案例

    這篇文章介紹了四種監(jiān)控Spring Boot中所有線程池的解決方案,并提供了代碼案例,推薦使用自動(dòng)發(fā)現(xiàn)機(jī)制來監(jiān)控所有線程池,需要的朋友可以參考下
    2025-12-12
  • Java設(shè)計(jì)模式之命令模式

    Java設(shè)計(jì)模式之命令模式

    這篇文章介紹了Java設(shè)計(jì)模式之命令模式,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Java解析XML文件開源庫DOM4J

    Java解析XML文件開源庫DOM4J

    dom4j是一個(gè)Java的XML API,是jdom的升級(jí)品,用來讀寫XML文件的。dom4j是一個(gè)十分優(yōu)秀的JavaXML API,具有性能優(yōu)異、功能強(qiáng)大和極其易使用的特點(diǎn),它的性能超過sun公司官方的dom技術(shù),同時(shí)它也是一個(gè)開放源代碼的軟件
    2023-01-01
  • Java利用反射自動(dòng)封裝成實(shí)體對(duì)象的方法

    Java利用反射自動(dòng)封裝成實(shí)體對(duì)象的方法

    這篇文章主要介紹了Java利用反射自動(dòng)封裝成實(shí)體對(duì)象的方法,可實(shí)現(xiàn)自動(dòng)封裝成bean對(duì)象功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • Redis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法

    Redis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猂edis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-06-06
  • 使用Idea簡單快速搭建springcloud項(xiàng)目的圖文教程

    使用Idea簡單快速搭建springcloud項(xiàng)目的圖文教程

    這篇文章主要介紹了使用Idea簡單快速搭建springcloud項(xiàng)目,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Spring boot整合Springfox生成restful的在線api文檔

    Spring boot整合Springfox生成restful的在線api文檔

    這篇文章主要為大家介紹了Spring boot整合Springfox生成restful在線api文檔,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • Java 1.8使用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列

    Java 1.8使用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列

    這篇文章主要為大家詳細(xì)介紹了Java 1.8使用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • 總結(jié)一下Java回調(diào)機(jī)制的相關(guān)知識(shí)

    總結(jié)一下Java回調(diào)機(jī)制的相關(guān)知識(shí)

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著Java回調(diào)機(jī)制展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評(píng)論

新龙县| 玉溪市| 故城县| 莒南县| 成武县| 浏阳市| 巴林右旗| 永和县| 芒康县| 仪征市| 马尔康县| 静安区| 兴仁县| 莎车县| 沂源县| 平和县| 玉环县| 苍南县| 青阳县| 营口市| 阳信县| 曲靖市| 峨眉山市| 屏边| 宾阳县| 南平市| 巴里| 土默特左旗| 文山县| 景德镇市| 康平县| 遂宁市| 潢川县| 大洼县| 三台县| 齐河县| 民勤县| 嵊州市| 监利县| 江孜县| 长治市|