Java ”框架 = 注解 + 反射 + 设计模式“ 之 注解详解

news2024/11/28 18:36:33

Java ”框架 = 注解 + 反射 + 设计模式“ 之 注解详解

在这里插入图片描述

每博一文案

刹那间我真想令时光停住,好让我回顾自己,回顾失去的年华,缅怀哪个穿一身短小的连衣裙
和瘦窄的短衫的小女孩。让我追悔少年时代,我心灵的愚钝无知,它轻易地错过了我一生中本来
可以获得欢乐和幸福。
                             —————— 《平凡的世界》
                             
真的,如果痛苦不能改变生存,那还不如平静地将自己毁灭,毁灭,一切都毁灭了,
只有生命还在苟延残喘,这样的生命还有有什么存在的价值。
                            —————— 《平凡的世界》
                     

文章目录

  • Java ”框架 = 注解 + 反射 + 设计模式“ 之 注解详解
    • 每博一文案
    • 1. 注解的概念
    • 2. 注解的作用
    • 3. 文档注释中的注解
    • 4. 自定义注解
      • 4.1 注解中的属性
      • 4.2 注解中属性为:数组的赋值
    • 5. JDK 内置的三个基本注解
      • 5.1 @Override: 限定重写父类方法, 该注解只能用于方法
      • 5.2 @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。
      • 5.3 @SuppressWarnings: 抑制编译器警告
    • 6. 元注解
      • 6.1 @Target
      • 6.2 @Retention
      • 6.3 @Documented
      • 6.4 @Inherited
    • 7. 通过反射获取到注解信息
    • 8. 总结:
    • 9. 最后:

1. 注解的概念

注解,一种元数据形式提供了一个不属于程序本身的程序的数据。注解对他们注解的代码的操作没有直接的影响。

注解有很多用途,其中:

  • 编译器的信息 - 编译器可以使用注解来检测错误或抑制警告。
  • 编译和部署时处理 - 软件工具可以处理注解信息以生成代码,XML 文件等。
  • 运行时处理 - 一些注解可以在运行时检查

JDK5.0 开始,Java增加了对元数据**(MetaData)** 的支持,也就是 Annotation 注解。

  • 注解: 其实就是代码里的 特殊标记 ,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用 注解,

程序员可以在不改变原有的逻辑的情况下,在源文件种嵌入一些补充的信息。代码分析工具,开发工具和部署工具可以通过这些补充信息进行验证或进行部署。

  • 注解: 可以像修饰符一样被使用,可以用于 修饰:包,类,构造器,方法,成员变量,参数,局部变量的声明 。这些信息被保存在 注解 Annotaion 的“ name = value” 键值对中。

  • JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如

    用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗 代码和XML配置等。

  • 未来的开发模式都是基于注解的,JPA 是基于注解的,Spring2.5 以上都是基于注解的,Hibernate3.x 以后也是基于注解的,

现在Struts2 有一部分也是基于注解的了。注解是一种趋势,一定程度上可以说:框架 = 注解 + 反射 + 设计模式

2. 注解的作用

JVM 的角度看,注解本身对代码逻辑没有任何影响,如何使用注解完全由工具决定。

Java的注解可以分为三类:

  • 第一类:是由编译器使用的注解:换句话说就是给编译器看的,不是给 JVM 看的。例如:
    • @Override : 让编译器检查该方法是否正确的实现了 重写操作。
    • @Deprecated : 表示所修饰的元素(类,方法等)已过时了,不建议使用它了。
    • @SuppressWarnings: 告诉编译器忽略此处代码产生的警告。
  • 第二类: 是由工具处理 .class 文件使用的注解,比如有些工具会在加载 class 的时候,对 class 做动态修改,实现一些特殊的功能。这类注解会被编译进入到 .class 文件,但加载结束后并不会存在于内存中。这类注解只被一些底层使用,一般我们不必自己处理。
  • 第三类: 是在程序运行期间能够读取的注解,它们在加载后一直存在于 JVM 中,这也是最常用的注解。例如:一个配置了@PostConstruct 的方法会在调用构造方法后自动被调用,(这是Java代码读取该注解实现的功能,JVM 并不会识别该注解)。

3. 文档注释中的注解

在这里插入图片描述

在这里插入图片描述

  • @author 标明开发该类模块的作者,多个作者之间使用,分割。
  • @version 标明该类的模块的版本。
  • @see 参考转向,也就是相关类的主题。
  • @since 从哪个版本开始增加的。
  • @param 对方法中某参数的说明,如果没有参数就不能写。
  • @return 对方法返回值的说明,如果方法的返回值类型是 void 就不能写
  • @exception 对方法可能抛出的异常进行说明,如果方法没有用 throws 显抛出的异常就不能写 其中:
    • @param @ return 和 @ exeption 这三个标记都是只用于方法的。
    • @param 的格式要求:@param 形参名 形参类型 形参说明
    • @return 的格式要求:@return 返回值类型 返回值说明
    • @exception 的格式要求:@exception 异常类型 异常说明
    • @ param 和 @exception 可以并列多个。

4. 自定义注解

Annotaion注解 其实也是一种引用数据类型,编译之后也是生成 xxx.class 字节码文件的。

  • 定义新的 Annotation 注解 类型使用 @interface 关键字

  • 自定义注解自动实现了 java.lang.annotation.Annotation接口

在这里插入图片描述

在这里插入图片描述

自定义注解的格式如下:

public @interface MyAnnotation {
    
}

// 
[修饰列表] @interface 注解名/(注解类名) {
    
}

使用 IDEA 创建一个 注解类型: 鼠标右键 ——> new 一个选择 :

在这里插入图片描述

如下查看该 我们该自定义的注解 MyAnnotation 的 UML 图:可以清楚的看到该 注解类型是自动继承了该 java.lang.annotation.Annotation 接口的

在这里插入图片描述

但是事实上却是自动实现了 java.lang.annotation.Annotation 接口。

在这里插入图片描述

Java 8之前,注解只能是在声明的地方所使用,Java8 开始,注解可以应用 在任何地方 。这里的任何地方包括:包,类,构造器,方法,成员变量,参数,局部变量的声明 。这些信息被保存在 注解 Annotaion 的“ name = value” 键值对中。

举例如下: 并没有出现任何的报错的情况。

在这里插入图片描述

4.1 注解中的属性

在注解中可以定义属性。

Java中的注解中的属性:看着像方法,但实际在注解当中是属性 name

格式如下:

String value();
// 数据类型 属性名();  // 看似是方法,其实在注解中是属性

注解中的属性可以是任何类型:byte, short, int, long, float, double, boolean, char, String, long, Class, 枚举类型。再或者是自定义类型。

举例:

public @interface MyAnnotation {
    
    String value();

}

注意: 如果该注解中定义了属性,则声明使用该注解时 必须 为其注解中的属性值赋上值,不然,是会报错的。

如下,我们为该 @MyAnnotation 注解定义了属性,使用时却没有赋值,报如下编译错误。

在这里插入图片描述

为注解中的属性赋值的格式如下:

@MyAnnotaion(value="Tom") // 注意:在该注解中定义的是什么类型的值,就赋值对应的值,不然会报错的
// @注解名(注解中的属性名=对应赋值的属性值)

举例:

在这里插入图片描述

如果该注解中只有一个属性值,并且该注解的属性名为 value ,则在赋值时,可以省略其 为value的属性名,直接写值

注意一定要满足两个条件:1. 该注解中只有一个属性值,2.该属性名为 value

举例:

在这里插入图片描述


为注解中的多个属性赋值格式如下: 多个属性值,使用逗号分隔开来,就可以了。

 @MyAnnotation(value = "Tom",value2 = "123")
// @注解名(注解中的属性名=值,注解中的属性名=值) :多个属性值使用逗号分隔开。

注意: 当注解中存在多个属性值时,其中所有该注解中的属性值都必须赋值,不然编译报错,如下:

在这里插入图片描述

必须将注解中的所有属性值都赋值上值才行:如下:如果注解中存在两个或两个以上的属性,就算其中存在一个属性名为 value ,其赋值时,该value 属性名是不可以省略的。必须写明所有的属性名的进行赋值。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

注解中的属性可以设置默认值,使用关键字``格式如下:

String value() default "Tom";
// 数据类型 属性名() default  默认值;  注意需要和定义的类型保证一致。

举例:

public @interface MyAnnotation {
    String value() default "Tom";

}

注解中属性设置了,默认值的是可以选择不进行赋值操作,使用定义的默认值。

举例如下:

在这里插入图片描述

4.2 注解中属性为:数组的赋值

注解中的属性值是可以定义为数组属性的格式如下:

String[] arr(); // 定义数组为属性值
数据类型[] 属性名(); 

举例:

public @interface MyAnnotation {

    String value();

    String[] arr();

}

注解中以数组为属性的赋值格式如下:

@MyAnnotation(value = "Tom",arr = {"hello","world"})
@注解名(属性名=,属性名={,})

举例:

在这里插入图片描述

当数组属性所赋值的参数只有一个时,可以省略{} 花括号。如下

在这里插入图片描述

5. JDK 内置的三个基本注解

下面我们来认识一下,JDK 中三个常见的基本注解。

5.1 @Override: 限定重写父类方法, 该注解只能用于方法

在这里插入图片描述

@Override : 的作用就是在编译期间:让编译器检查该方法是否正确的实现了 重写 操作。其中的重写的方法名是否存在错误,方法的返回值类型是否是父类中/接口中的一致。不一致编译报错,提示我们改正。

@OVerride 注解的源码,可以看到该注解是没有定义属性的。

package java.lang;

import java.lang.annotation.*;

/**
 * Indicates that a method declaration is intended to override a
 * method declaration in a supertype. If a method is annotated with
 * this annotation type compilers are required to generate an error
 * message unless at least one of the following conditions hold:
 *
 * <ul><li>
 * The method does override or implement a method declared in a
 * supertype.
 * </li><li>
 * The method has a signature that is override-equivalent to that of
 * any public method declared in {@linkplain Object}.
 * </li></ul>
 *
 * @author  Peter von der Ah&eacute;
 * @author  Joshua Bloch
 * @jls 9.6.1.4 @Override
 * @since 1.5
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

注意 : 该注解只能使用在方法上(因为该注解的源码中被@Target(ElementType.METHOD)元注解修饰了),在其他位置上是会编译报错的。如下:

在这里插入图片描述


@OVerride 注解的使用: 较少了我们编程程序时,上的简单符号上以及一些基本的语法错误。

在这里插入图片描述

5.2 @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。

在这里插入图片描述

@Deprecated : 该注解表示:表示所修饰的元素(类,方法等)已过时了,不建议使用它了。建议替换成其他的方法。

@Depecated 源码: 可以看到该注解是没有定义属性的。

package java.lang;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

/**
 * A program element annotated &#64;Deprecated is one that programmers
 * are discouraged from using, typically because it is dangerous,
 * or because a better alternative exists.  Compilers warn when a
 * deprecated program element is used or overridden in non-deprecated code.
 *
 * @author  Neal Gafter
 * @since 1.5
 * @jls 9.6.3.6 @Deprecated
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

常见的,在我们的 java.util.lang 包下的 Date 中的 Date(String s) 构造器是被 @Deprecated 注解修饰了的。

在这里插入图片描述

在IDEA 中 如果我们调用了,被 @Deprecated 修饰的属性,方法,构造器,会给一个直观的将该属性/方法以删除线的方式显示处理并提示你建议使用别的方式替换 。如下

在这里插入图片描述

我们也可以自己写一个这样的被@Deprecated 修饰的属性/方法/类/构造器。举例如下:

在这里插入图片描述

5.3 @SuppressWarnings: 抑制编译器警告

在这里插入图片描述

@SuppressWarnings ** :指示应该在注解元素(以及包含在该注解元素中所有程序元素中的所有程序元素)中取消显示指定的编译器警告。换句话说:就是告诉编译器忽略此处代码产生的警告**。 注意是警告不是异常。

@SuppressWarnings的源码 ,可以看到该注解定义了一个名为 value 的属性。


package java.lang;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

/**
 * Indicates that the named compiler warnings should be suppressed in the
 * annotated element (and in all program elements contained in the annotated
 * element).  Note that the set of warnings suppressed in a given element is
 * a superset of the warnings suppressed in all containing elements.  For
 * example, if you annotate a class to suppress one warning and annotate a
 * method to suppress another, both warnings will be suppressed in the method.
 *
 * <p>As a matter of style, programmers should always use this annotation
 * on the most deeply nested element where it is effective.  If you want to
 * suppress a warning in a particular method, you should annotate that
 * method rather than its class.
 *
 * @author Josh Bloch
 * @since 1.5
 * @jls 4.8 Raw Types
 * @jls 4.12.2 Variables of Reference Type
 * @jls 5.1.9 Unchecked Conversion
 * @jls 5.5.2 Checked Casts and Unchecked Casts
 * @jls 9.6.3.5 @SuppressWarnings
 */
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    /**
     * The set of warnings that are to be suppressed by the compiler in the
     * annotated element.  Duplicate names are permitted.  The second and
     * successive occurrences of a name are ignored.  The presence of
     * unrecognized warning names is <i>not</i> an error: Compilers must
     * ignore any warning names they do not recognize.  They are, however,
     * free to emit a warning if an annotation contains an unrecognized
     * warning name.
     *
     * <p> The string {@code "unchecked"} is used to suppress
     * unchecked warnings. Compiler vendors should document the
     * additional warning names they support in conjunction with this
     * annotation type. They are encouraged to cooperate to ensure
     * that the same names work across multiple compilers.
     * @return the set of warnings to be suppressed
     */
    String[] value();
}

举例: 这里我们定义一个 int num = 1 / 0 语句,IDEA 该我们提示了警告了。

在这里插入图片描述

当我们加上了 @SuppressWarnings IDEA 就没有这个警告了。如下:

在这里插入图片描述

在这里插入图片描述

具体的其他应用大家可以移步至:🔜🔜🔜
https://blog.csdn.net/qq_43842093/article/details/122386115?ops_request_misc=&request_id=&biz_id=102&utm_term=%20@SuppressWarnings%E7%9A%84%E4%BD%BF%E7%94%A8&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-122386115.142
Eclipse Galileo版本支持的抑制警告的名称:

关键字用途
allto suppress all warnings (抑制所有警告)
boxingto suppress warnings relative to boxing/unboxing operations (抑制装箱、拆箱操作时候的警告)
castto suppress warnings relative to cast operations (抑制映射相关的警告)
dep-annto suppress warnings relative to deprecated annotation (抑制启用注释的警告)
deprecationto suppress warnings relative to deprecation (抑制过期方法警告)
fallthroughto suppress warnings relative to missing breaks in switch statements (抑制确在switch中缺失breaks的警告)
finallyto suppress warnings relative to finally block that don’t return (抑制finally模块没有返回的警告)
hidingto suppress warnings relative to locals that hide variable(抑制相对于隐藏变量的局部变量的警告)
incomplete-switchto suppress warnings relative to missing entries in a switch statement (enum case)(忽略没有完整的switch语句)
nlsto suppress warnings relative to non-nls string literals( 忽略非nls格式的字符)
nullto suppress warnings relative to null analysis( 忽略对null的操作)
rawtypesto suppress warnings relative to un-specific types when using generics on class params( 使用generics时忽略没有指定相应的类型)
restrictionto suppress warnings relative to usage of discouraged or forbidden references( 抑制禁止使用劝阻或禁止引用的警告)
serialto suppress warnings relative to missing serialVersionUID field for a serializable class( 忽略在serializable类中没有声明serialVersionUID变量)
static-accessto suppress warnings relative to incorrect static access( 抑制不正确的静态访问方式警告)
synthetic-accessto suppress warnings relative to unoptimized access from inner classes( 抑制子类没有按最优方法访问内部类的警告)
uncheckedto suppress warnings relative to unchecked operations( 抑制没有进行类型检查操作的警告)
unqualified-field-accessto suppress warnings relative to field access unqualified( 抑制没有权限访问的域的警告)
unusedto suppress warnings relative to unused code( 抑制没被使用过的代码的警告)

6. 元注解

有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)。Java标准库已经定义了一些元注解,我们只需要使用元注解,通常不需要自己去编写元注解。

6.1 @Target

在这里插入图片描述

@Target 源码:其中存在一个类型为 ElementType[] 枚举类型数组属性名为 value 的属性。

package java.lang.annotation;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

ElementType的枚举源码 :

/package java.lang.annotation;
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

@Target : 最常用的元注解是@Target。使用@Target可以定义Annotation能够被应用于源码的哪些位置:

  • 类或接口:ElementType.TYPE
  • 字段:ElementType.FIELD
  • 方法:ElementType.METHOD
  • 构造方法:ElementType.CONSTRUCTOR
  • 方法参数:ElementType.PARAMETER

举例:

在这里插入图片描述

在这里插入图片描述

@Target元注解中的 value 属性是枚举数组类型的,可以赋值多个值:比如表示该注解可以声明在方法,变量,类中 ,举例:

在这里插入图片描述

6.2 @Retention

在这里插入图片描述

@Retention 源码 : 我们可以看到如下注解中只定义了一个RetentionPolicy 的枚举类型名为 value 的属性名的属性

package java.lang.annotation;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

RetentionPolicy 枚举类型的源码

package java.lang.annotation;


public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

@Retention : 另一个重要的元注解@Retention定义了Annotation的生命周期:

@Rentention 时必须为该 value 成员变量指定值

  • 仅编译期:RetentionPolicy.SOURCE 表示该注解的生命周期只在编译期间有效,在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释。
  • 仅class文件:RetentionPolicy.CLASS : 在class文件中有效(即class保留) , 当运行 Java 程序时, JVM 不会保留注解。 这是默认值
  • 运行期:RetentionPolicy.RUNTIME,注意:只有定义该属性的注解,才能被反射读取到。上面两种方式都无法被反射读取到的。

如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME,所以,务必要加上@Retention(RetentionPolicy.RUNTIME)这个元注解:

举例:

在这里插入图片描述

6.3 @Documented

在这里插入图片描述

@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。

  • 定义为Documented的注解必须设置Retention值为RUNTIME

@Documented 的源码 从源码看,该注解没有任何属性。


package java.lang.annotation;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

6.4 @Inherited

在这里插入图片描述

@Inherited: 被它修饰的 Annotation 将具有继承性。如果某个类使用了被

@Inherited : 修饰的 Annotation, 则其子类将自动具有该注解。

  • 比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类类级别的注解

  • 实际应用中,使用较少

@Inherited 源码 从源码看,该注解没有任何属性。


package java.lang.annotation;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

7. 通过反射获取到注解信息

想要让反射可以读取到注解中的信息,则该反射中的元注解必须是: @Retention(RetentionPolicy.RUNTIME) 才行。

举例: 这里我们使用反射读取到 fun() 方法中的 注解中的 value 属性值:

注解

package blogs.blog10;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)  // 生命周期在:运行期,才可以被反射读取到
public @interface MyAnnotation {
    String value() default "Tom";

}

package blogs.blog10;


import java.lang.reflect.Method;

public class AnnotationTest {

    public static void main(String[] args) {
        Method method = null;

        try {
            // 获取类加载器,类对象
            Class clazz = Class.forName("blogs.blog10.AnnotationTest"); // 全类路径名

            // 获取 fun()方法
            method = clazz.getDeclaredMethod("fun");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 判断该方法是否存在该注解,存在才读取该注解上的属性值
        if(method.isAnnotationPresent(MyAnnotation.class)) {
            // 获取该注解对象
            MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
            // // 获取该注解的属性值,就像对象.属性一样
            String value = annotation.value();
            System.out.println(value);
        }

    }

    @MyAnnotation("lihua")
    public void fun() {
        int num = 0;
    }

}




在这里插入图片描述

8. 总结:

  1. 设计注解类型时,必须考虑该类型注解的基数。现在可以使用注解零次,一次,或者如果注解的类型被标记为 @Repeatable 多次。也可以通过使用 @Target 元注解来限制注解类型的使用位置。例如,您可以创建只能在方法和字段上使用的可重复注解类型。重要的是仔细设计注解类型,以确保使用注解的程序员发现它尽可能灵活和强大。
  2. 注解的作用:减少程序中的错误,提高程序员的开发效率。以及框架上的运用。
  3. 注意:注解中的属性必须赋值,不然编译无法通过,除非该属性设置了默认值信息,建议注解中的属性设置上默认值。
  4. 当注解中只有一个属性,并且该属性名为 value ,则在赋值上可以省略属性名。
  5. 注解多个值上的赋值,以及数组类型的属性值的赋值。
  6. 元注解:修饰注解上的注解,特别掌握:@Target,@Retention 这两个元注解,其中的属性值上的赋值的意义。

9. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善 。谢谢大家,江湖再见,后会有期 !!!

在这里插入图片描述

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

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

相关文章

oracle11g忘记system密码,重置密码

OPW-00001: 无法打开口令文件 cmd.exe 使用管理员身份登录 找到xxx\product\11.2.0\dbhome_1\database\PWDorcl.ora文件&#xff0c;删除 执行orapwd fileD:\app\product\11.2.0\dbhome_1\database\PWDorcl.ora passwordtiger (orapwd 在\product\11.2.0\dbhome_1\BIN目录下…

DolphinScheduler第一章:环境安装

系列文章目录 DolphinScheduler第一章&#xff1a;环境安装 文章目录系列文章目录前言一、环境准备1.上传文件2.数据库配置3.配置安装文件二、集群部署1.数据部署2.部署 DolphinScheduler3. DolphinScheduler 启停命令总结前言 我们现在开始学习hadoop中的DolphinScheduler组…

Vim 命令速查表

Vim 命令速查表 简介&#xff1a;Vim 命令速查表&#xff0c;注释化 vimrc 配置文件&#xff0c;经典 Vim 键盘图&#xff0c;实用 Vim 书籍&#xff0c;Markdown 格式&#xff0c;目录化检索&#xff0c;系统化学习&#xff0c;快速熟悉使用&#xff01; Vim 官网 | Vim | Vim…

小学生学Arduino---------点阵(三)动态的显示与清除

学习目标&#xff1a; 1、理解“整数值”的概念与使用 2、理解“N1”指令的意义 3、掌握“反复执行多次”指令的使用 4、掌握屏幕模块的清除功能指令 5、理解“反复执行”指令与“反复执行多次”指令的嵌套使用 6、搭建电路图 7、编写程序 效果&#xff1a; 整数包括&#xf…

HTTP cookie格式与约束

cookie是前端编程当中经常要使用到的概念&#xff0c;我们可以使用cookie利用浏览器来存放用户的状态信息保存用户做了一些什么事情。session是服务器端维护的状态。session又是如何和cookie关联起来。后面介绍cookie和session的使用。Cookie 是什么&#xff1f;RFC6265, HTTP …

2022-2023年营销报告(B站平台) | 5大行业势态、流量大盘全景洞察

一直以来&#xff0c;手持高活跃、高粘性用户群体的B站是行业用来观察年轻人消费习惯的重要平台。以至于用户群体的不断壮大带动了B站的商业价值。如今B站的商业舞台越来越大&#xff0c;不断地向外界招手&#xff0c;欢迎更多品牌积极加入到这个千万年轻人聚集的内容社区。为了…

如何使用Kadence Blocks构建迷人的Kadence产品网格

在本教程中&#xff0c;我将逐步教您如何使用 Kadence Blocks 构建一个五列Kadence产品网格&#xff0c;它可以作为全宽区块放置在您的博客文章的顶部。使用这个包含五列的产品网格是在文章顶部展示产品、对每个产品进行简要描述&#xff0c;然后包含一个供用户访问该站点的按钮…

校园社交平台【源码好优多】

简介 本项目是为满足大学生的校园社交需求而设计的&#xff0c;动态模块提供发布/删除/搜索/点赞/收藏/评论动态功能&#xff0c;个人模块提供关注与私信以及用户修改个人信息功能&#xff0c;聊天模块提供即时聊天功能。该项目为前后端分离项目并且后端实现分布式&#xff0c…

蓝桥杯入门即劝退(十九)两两交换链表

-----持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法&#xff0c;欢迎订阅专栏共同学习交流&#xff01; 你的点赞、关注、评论、是我创作的动力&#xff01; -------希望我的文章对你有所帮助-------- 一、题目描述 给你一个链表&#xff0c;两两交换其中…

JavaEE简单示例——<select>中的查询参数传递和结果集封装自动映射关系

简单介绍&#xff1a; 在之前我们在讲SQL映射文件中的映射查询语句的<select>标签的时候&#xff0c;对其中的四个常用属性的讲解并不是那么的透彻&#xff0c;今天就来详细的解释<select>的四个常用属性的具体含义以及<select>标签在进行查询的时候查询参数…

LQB02控制LED灯,74HC138芯片,74HC02芯片,74HC573芯片。

一&#xff0c;硬件图解读。 二&#xff0c;控制LED需要的74HC595程序编程。 三&#xff0c;控制某个LED亮&#xff0c;其他保持不变&#xff0c;或者控制整8个LED&#xff0c;其他不变&#xff1b; 四&#xff0c;读取某个LED的状态&#xff0c;一秒时间读取一次&#xff0c;如…

mapreduce与yarn

文章目录一、MapReduce1.1、MapReduce思想1.2、MapReduce实例进程1.3、MapReduce阶段组成1.4、MapReduce数据类型1.5、MapReduce关键类1.6、MapReduce执行流程1.6.1、Map阶段执行流程1.6.2、Map的shuffle阶段执行流程1.6.3、Reduce阶段执行流程1.7、MapReduce实例WordCount二、…

版本控制软件SVN

SVN学习 1 版本控制软件定义及用途 版本控制软件是为适应软件配置管理的需要&#xff0c;控制软件的修改&#xff0c;减少混乱&#xff0c;提高软件生产效率&#xff0c;其是软件质量保证的重要环节软件配置管理是对软件修改进行标识、组织和控制的技术&#xff0c;用来协调和…

MASA MAUI Plugin (八)Android相册多选照片(Intent 方式)

背景 MAUI的出现&#xff0c;赋予了广大.Net开发者开发多平台应用的能力&#xff0c;MAUI 是Xamarin.Forms演变而来&#xff0c;但是相比Xamarin性能更好&#xff0c;可扩展性更强&#xff0c;结构更简单。但是MAUI对于平台相关的实现并不完整。所以MASA团队开展了一个实验性项…

代码随想录NO49 | 动态规划 _LeetCode1143.最长公共子序列 1035.不相交的线 53. 最大子序和

动态规划 _LeetCode1143.最长公共子序列 1035.不相交的线 53. 最大子序和今天继续子序列问题&#xff01; 1143.最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符…

docker全解

目录说明docker简介为什么是docker容器与虚拟机比较容器发展简史传统虚拟机技术容器虚拟化技术docker能干什么带来技术职级的变化开发/运维&#xff08;Devops)新一代开发工程师Docker应用场景why docker&#xff1f;docker的优势docker和dockerHub官网Docker安装CentOS Docker…

10 种 Spring事务失效场景

10 种 Spring事务失效场景 1.概述 Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事务 API&#xff0c;实现了一致的编程模型&#xff0c;而Spring的声明式事务功能更是提供了极其方便的事务配置方式&#xff0c;配合Spring Boot的自动…

supervisor看守进程

supervisor可以用于看守正在运行的服务&#xff0c;如果服务以外停止&#xff0c;他会在设置的时间间隔内重新启动该服务。 本测试使用的系统是TencentOS3.1. 安装supervisor最简单方法是使用yum。 yum install supervisor supervisor需要python3支持&#xff0c;因此请先确…

【Android玩机】跟大家聊聊面具Magisk的使用(安装、隐藏)

目录:1、Magisk中文网2、隐藏面具和Root&#xff08;一共3种方法&#xff09;1、Magisk中文网 &#xff08;1&#xff09;首先Magisk有一个中文网&#xff0c;对新手非常友好 &#xff08;2&#xff09;这网站里面主要包含&#xff1a;6 部分 &#xff08;3&#xff09;按照他给…

c++常用stl算法

1、头文件 这些算法通常包含在头文件<algorithm> <functional> <numeric>中。 2、常用遍历算法 for_each(v.begin(),v.end(), 元素处理函数/仿函数) 注意&#xff1a;在使用transform转存时&#xff0c;目标容器需要提取开辟合适的空间。 void printfunc(…