Java注解以及自定义注解

Java注解以及自定义注解

要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为

我们提供的元注解和相关定义注解的语法。

1、注解

1.1 注解的官方定义

注解是一种元数据形式。即注解是属于java的一种数据类型,和类、接口、数组、枚举类似。

注解用来修饰,类、方法、变量、参数、包。

注解不会对所修饰的代码产生直接的影响。

1.2 注解的使用范围

注解有许多用法,其中有:为编译器提供信息 - 注解能被编译器检测到错误或抑制警告。编译时和部署时的处理 -

软件工具能处理注解信息从而生成代码,XML文件等等。运行时的处理 - 有些注解在运行时能被检测到。

2、元注解

一个最最基本的注解定义就只包括了两部分内容:1、注解的名字;2、注解包含的类型元素。但是,我们在使用

JDK自带注解的时候发现,有些注解只能写在方法上面(比如@Override);有些却可以写在类的上面(比如

@Deprecated)。当然除此以外还有很多细节性的定义,那么这些定义该如何做呢?接下来就该元注解出场了!

元注解:专门修饰注解的注解。它们都是为了更好的设计自定义注解的细节而专门设计的。Java5.0定义了4个标准

的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。

Java5.0 定义的元注解:

1、@Target

2、@Retention

3、@Documented

4、@Inherited

这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应

分参数的使用说明。

2.1 @Target

@Target注解,是专门用来限定某个自定义注解能够被应用在哪些Java元素上面的。

@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、

Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、

catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

作用:用于描述注解的使用范围(即被描述的注解可以用在什么地方)

取值(ElementType)有:

1、CONSTRUCTOR:用于描述构造器

2、FIELD:用于描述域

3、LOCAL_VARIABLE:用于描述局部变量

4、METHOD:用于描述方法

5、PACKAGE:用于描述包

6、PARAMETER:用于描述参数

7、TYPE:用于描述类、接口(包括注解类型) 或enum声明

它使用一个枚举类型定义如下:

public enum ElementType {/** 类,接口(包括注解类型)或枚举的声明 */TYPE,/** 属性的声明 */FIELD,/** 方法的声明 */METHOD,/** 方法形式参数声明 */PARAMETER,/** 构造方法的声明 */CONSTRUCTOR,/** 局部变量声明 */LOCAL_VARIABLE,/** 注解类型声明 */ANNOTATION_TYPE,/** 包的声明 */PACKAGE,TYPE_PARAMETER,TYPE_USE
}

使用实例:

package com.test3;import java.lang.annotation.ElementType;
import java.lang.annotation.Target;@Target(ElementType.TYPE)
public @interface Table {/*** 数据表名称注解,默认值为类名称* @return*/public String tableName() default "className";
}
package com.test3;import java.lang.annotation.ElementType;
import java.lang.annotation.Target;@Target(ElementType.FIELD)
public @interface NoDBColumn {
}
package com.test3;import java.lang.annotation.ElementType;
import java.lang.annotation.Target;//@CherryAnnotation被限定只能使用在类、接口或方法上面
@Target(value = {ElementType.TYPE, ElementType.METHOD})
public @interface CherryAnnotation {String name();int age() default 18;int[] array();
}

注解Table可以用于注解类、接口(包括注解类型) 或enum声明,而注解NoDBColumn仅可用于注解类的成员变

量。

2.2 @Retention

@Retention注解,翻译为持久力、保持力。即用来修饰自定义注解的生命力。

注解的生命周期有三个阶段:1、Java源文件阶段;2、编译到class文件阶段;3、运行期阶段。同样使用了

RetentionPolicy 枚举类型定义了三个阶段:

作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即被描述的注解在什么范围内有效)

取值(RetentionPoicy)有:

1、SOURCE:在源文件中有效(即源文件保留)

2、CLASS:在class文件中有效(即class保留)

3、RUNTIME:在运行时有效(即运行时保留)

Retention meta-annotation类型有唯一的value作为成员,它的取值来自

java.lang.annotation.RetentionPolicy的枚举类型值。

public enum RetentionPolicy {// 注解将被编译器忽略掉SOURCE,// 注解将被编译器记录在class文件中,但在运行时不会被虚拟机保留,这是一个默认的行为CLASS,// 注解将被编译器记录在class文件中,而且在运行时会被虚拟机保留,因此它们能通过反射被读取到RUNTIME
}

我们再详解一下:

如果一个注解被定义为RetentionPolicy.SOURCE,则它将被限定在Java源文件中,那么这个注解即不会参与编

译也不会在运行期起任何作用,这个注解就和一个注释是一样的效果,只能被阅读Java文件的人看到;

如果一个注解被定义为RetentionPolicy.CLASS,则它将被编译到Class文件中,那么编译器可以在编译时根据

注解做一些处理动作,但是运行时JVM(Java虚拟机)会忽略它,我们在运行期也不能读取到;

如果一个注解被定义为RetentionPolicy.RUNTIME,那么这个注解可以在运行期的加载阶段被加载到Class对象

中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,

从而执行不同的程序代码段。我们实际开发中的自定义注解几乎都是使用的RetentionPolicy.RUNTIME;在默认

的情况下,自定义注解是使用的RetentionPolicy.CLASS

具体实例如下:

package com.test3;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {public String name() default "fieldName";public String setFuncName() default "setField";public String getFuncName() default "getField";public boolean defaultDBValue() default false;
}

Column注解的的RetentionPolicy的属性值是RUNTIME,这样注解处理器可以通过反射,获取到该注解的属性

值,从而去做一些运行时的逻辑处理。

2.3 @Documented

@Documented注解,是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中,因此可以

被例如javadoc此类的工具文档化。

Documented是一个标记注解,没有成员。

package com.test3;import java.lang.annotation.*;@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column1 {public String name() default "fieldName";public String setFuncName() default "setField";public String getFuncName() default "getField";public boolean defaultDBValue() default false;
}

2.4 @Inherited

@Inherited注解,是指定某个自定义注解如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注

解。@Inherited注解只对那些@Target被定义为ElementType.TYPE的自定义注解起作用。

@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了

@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,

方法并不从它所重载的方法继承annotation。

当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这

种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查

将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

实例代码:

package com.test3;import java.lang.annotation.Inherited;@Inherited
public @interface Greeting {public enum FontColor {BULE, RED, GREEN};String name();FontColor fontColor() default FontColor.GREEN;
}

注解的继承依赖如下一个因素:

1、首先要想Annotation能被继承,需要在注解定义的时候加上@Inherited,并且如果要被反射应用的话,还

需要@Retention(RetentionPolicy.RUNTIME)标识。

2、JDK文档中说明的是:只有在类上应用Annotation才能被继承,而实际应用结果是:除了类上应用的

Annotation能被继承外,没有被重写的方法的Annotation也能被继承。

3、当方法被重写后,Annotation不会被继承。

4、Annotation的继承不能应用在接口上。

3、自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细

节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声

明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、

Class、String、enum)。可以通过default来声明参数的默认值。

3.1 定义注解格式

public @interface 注解名 {定义体}
public @interface CherryAnnotation {
}

根据我们在自定义类的经验,在类的实现部分无非就是书写构造、属性或方法。但是,在自定义注解中,其实现

只能定义一个东西:注解类型元素(annotation type element)。语法:

public @interface CherryAnnotation {public String name();public int age();public int[] array();
}
public @interface CherryAnnotation {public String name();public int age() default 18;public int[] array();
}

3.2 注解参数的可支持数据类型

1、所有基本数据类型(int,float,boolean,byte,double,char,long,short)

2、String类型

3、Class类型

4、enum类型

5、Annotation类型

6、以上所有类型的数组

注解里面定义的是:注解类型元素!

3.3 定义注解类型元素时需要注意如下几点

1、只能用public或默认(default)这两个访问权修饰,例如String value();这里把方法设为default默认类型。

2、参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,

Enum,Class,annotations等数据类型,以及这一些类型的数组。

3、如果只有一个参数成员,最好把参数名称设为value,后加小括号。

4、()不是定义方法参数的地方,也不能在括号中定义任何参数,仅仅只是一个特殊的语法。

5、default代表默认值,值必须和第2点定义的类型一致。

6、如果没有默认值,代表后续使用注解时必须给该类型元素赋值。

可以看出,注解类型元素的语法非常奇怪,即又有属性的特征(可以赋值),又有方法的特征(打上了一对括

号)。但是这么设计是有道理的,我们在后面的章节中可以看到:注解在定义好了以后,使用的时候操作元素类型

像在操作属性,解析的时候操作元素类型像在操作方法。

3.4 简单的自定义注解和使用注解实例

package com.test;import java.lang.annotation.*;/*** 水果名称注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {String value() default "";
}
package com.test;import java.lang.annotation.*;/*** 水果颜色注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {/*** 颜色枚举*/public enum Color {BULE, RED, GREEN};/*** 颜色属性** @return*/Color fruitColor() default Color.GREEN;}
package com.test;public class Apple {@FruitName("Apple")private String appleName;@FruitColor(fruitColor = FruitColor.Color.RED)private String appleColor;public void setAppleColor(String appleColor) {this.appleColor = appleColor;}public String getAppleColor() {return appleColor;}public void setAppleName(String appleName) {this.appleName = appleName;}public String getAppleName() {return appleName;}
}

3.5 注解元素的默认值

注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值

不可为null。因此,使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存

在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能

定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用

法。

package com.test;import java.lang.annotation.*;/*** 水果供应者注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {/*** 供应商编号** @return*/public int id() default -1;/*** 供应商名称** @return*/public String name() default "";/*** 供应商地址** @return*/public String address() default "";
}

3.6 特殊语法

特殊语法一

如果注解本身没有注解类型元素,那么在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法

@注解名()等效!

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
@Documented
public @interface FirstAnnotation {
}
//等效于 @FirstAnnotation()
@FirstAnnotation
public class JavaBean{
}

特殊语法二

如果注解本身只有一个注解类型元素,而且命名为value,那么在使用注解的时候可以直接使用:

@注解名(注解值),其等效于:@注解名(value = 注解值)

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
@Documented
public @interface SecondAnnotation {String value();
}
//等效于 @SecondAnnotation(value = "this is second annotation")
@SecondAnnotation("this is annotation")
public class JavaBean{
}

特殊用法三

如果注解中的某个注解类型元素是一个数组类型,在使用时又出现只需要填入一个值的情况,那么在使用注解时可

直接写为:@注解名(类型名 = 类型值),它和标准写法:@注解名(类型名 = {类型值})等效!

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
@Documented
public @interface ThirdAnnotation {String[] name();
}
//等效于 @ThirdAnnotation(name = {"this is third annotation"})
@ ThirdAnnotation(name = "this is third annotation")
public class JavaBean{
}

特殊用法四

如果一个注解的@Target是定义为Element.PACKAGE,那么这个注解是配置在package-info.java中的,而不能

直接在某个类的package代码上面配置。

上面三节定义了注解,并在需要的时候给相关类,类属性加上注解信息,如果没有响应的注解信息处理流程,注解

可以说是没有实用价值。如何让注解真真的发挥作用,主要就在于注解处理方法,下一步我们将学习注解信息的获

取和处理!

4、自定义注解的配置使用

基于上一节,已对注解有了一个基本的认识:注解其实就是一种标记,可以在程序代码中的关键节点(类、方法、

变量、参数、包)上打上这些标记,然后程序在编译时或运行时可以检测到这些标记从而执行一些特殊操作。因此

可以得出自定义注解使用的基本流程:

第一步,定义注解——相当于定义标记;

第二步,配置注解——把标记打在需要用到的程序代码中;

第三步,解析注解——在编译期或运行时检测到标记,并进行特殊操作。

在这里插入图片描述

4.1 在具体的Java类上使用注解

首先,定义一个注解和一个供注解修饰的简单Java类。

package com.test1;import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
@Documented
public @interface CherryAnnotation {String name();// 类型元素int age() default 18;int[] score();
}
package com.test1;public class Student {public void study(int times) {for (int i = 0; i < times; i++) {System.out.println("Good Good Study, Day Day Up!");}}
}

简单分析下:

CherryAnnotation的@Target定义为ElementType.METHOD,那么它书写的位置应该在方法定义的上方,即:

public void study(int times)之上。由于我们在CherryAnnotation中定义的有注解类型元素,而且有些元素是没有

默认值的,这要求我们在使用的时候必须在标记名后面打上(),并且在()内以“元素名=元素值“的形式挨个填上所有

没有默认值的注解类型元素(有默认值的也可以填上重新赋值),中间用“,”号分割。

所以最终书写形式如下:

package com.test1;public class Student {@CherryAnnotation(name = "cherry-peng", age = 23, score = {99, 66, 77})public void study(int times) {for (int i = 0; i < times; i++) {System.out.println("Good Good Study, Day Day Up!");}}
}

4.2 自定义注解的运行时解析(反射操作获取注解)

这一节是使用注解的核心,读完此节即可明白,如何在程序运行时检测到注解,并进行一系列特殊操作!

只有当注解的保持力处于运行阶段,即使用@Retention(RetentionPolicy.RUNTIME)修饰注解时,才能在JVM

运行时,检测到注解,并进行一系列特殊操作。

在运行期探究和使用编译期的内容(编译期配置的注解),要用到Java中的灵魂技术——反射!

Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。

package com.test1;import java.lang.reflect.Method;/*** @author zhangshixing* @date 2021年11月01日 9:32*/
public class TestAnnotation {public static void main(String[] args){try {//获取Student的Class对象Class stuClass = Class.forName("com.test1.Student");//说明一下,这里形参不能写成Integer.class,应写为int.classMethod stuMethod = stuClass.getMethod("study",int.class);if(stuMethod.isAnnotationPresent(CherryAnnotation.class)){System.out.println("Student类上配置了CherryAnnotation注解!");//获取该元素上指定类型的注解CherryAnnotation cherryAnnotation = stuMethod.getAnnotation(CherryAnnotation.class);System.out.println("name: " + cherryAnnotation.name() + ", age: " + cherryAnnotation.age()+ ", score: " + cherryAnnotation.score()[0]);}else{System.out.println("Student类上没有配置CherryAnnotation注解!");}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}
}
# 程序输出
Student类上配置了CherryAnnotation注解!
name: cherry-peng, age: 23, score: 99

4.3 注解处理器类库(java.lang.reflect.AnnotatedElement)

Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java

java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接

口主要有如下几个实现类:

Class:类定义

Constructor:构造器定义

Field:类的成员变量定义

Method:类的方法定义

Package:类的包定义

java.lang.reflect包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API

扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能

是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了

某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:

isAnnotationPresent(Class<? extends Annotation> annotationClass)方法是专门判断该元素上是否配

置有某个指定的注解;

getAnnotation(Class<A> annotationClass)方法是获取该元素上指定的注解。之后再调用该注解的注解类型

元素方法就可以获得配置时的值数据;如果该类型注解不存在,则返回null。

反射对象上还有一个方法getAnnotations(),该方法可以获得该对象身上配置的所有的注解。它会返回给我们

一个注解数组,需要注意的是该数组的类型是Annotation类型,这个Annotation是一个来自于

java.lang.annotation包的接口。

Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注解。与此接口中的其他方法不

同,该方法将忽略继承的注解。(如果没有注解直接存在于此元素上,则返回长度为零的一个数组)。该方法的调

用者可以随意修改返回的数组;这不会对其它调用者返回的数组产生任何影响。

如果我们要获得的注解是配置在方法上的,那么我们要从Method对象上获取;如果是配置在属性上,就需要从该

属性对应的Field对象上去获取,如果是配置在类型上,需要从Class对象上去获取。总之在谁身上,就从谁身上去

获取!

一个简单的注解处理器

/***********注解声明***************/package com.test2;import java.lang.annotation.*;/*** 水果名称注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {String value() default "";
}
package com.test2;import java.lang.annotation.*;/*** 水果颜色注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {/*** 颜色枚举** @author peida*/public enum Color {BULE, RED, GREEN};/*** 颜色属性** @return*/Color fruitColor() default Color.GREEN;}
package com.test2;import java.lang.annotation.*;/*** 水果供应者注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {/*** 供应商编号** @return*/public int id() default -1;/*** 供应商名称** @return*/public String name() default "";/*** 供应商地址** @return*/public String address() default "";
}
/***********注解使用***************/package com.test2;public class Apple {@FruitName("Apple")private String appleName;@FruitColor(fruitColor = FruitColor.Color.RED)private String appleColor;@FruitProvider(id = 1, name = "陕西红富士集团", address = "陕西省西安市延安路89号红富士大厦")private String appleProvider;public void setAppleColor(String appleColor) {this.appleColor = appleColor;}public String getAppleColor() {return appleColor;}public void setAppleName(String appleName) {this.appleName = appleName;}public String getAppleName() {return appleName;}public void setAppleProvider(String appleProvider) {this.appleProvider = appleProvider;}public String getAppleProvider() {return appleProvider;}public void displayName() {System.out.println("水果的名字是:苹果");}
}
/***********注解处理器***************/package com.test2;import java.lang.reflect.Field;public class FruitInfoUtil {public static void getFruitInfo(Class<?> clazz) {String strFruitName = " 水果名称:";String strFruitColor = " 水果颜色:";String strFruitProvicer = "供应商信息:";Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(FruitName.class)) {FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);strFruitName = strFruitName + fruitName.value();System.out.println(strFruitName);} else if (field.isAnnotationPresent(FruitColor.class)) {FruitColor fruitColor = (FruitColor) field.getAnnotation(FruitColor.class);strFruitColor = strFruitColor + fruitColor.fruitColor().toString();System.out.println(strFruitColor);} else if (field.isAnnotationPresent(FruitProvider.class)) {FruitProvider fruitProvider = (FruitProvider) field.getAnnotation(FruitProvider.class);strFruitProvicer = " 供应商编号:" + fruitProvider.id() + " 供应商名称:" + fruitProvider.name() + " 供应商地址:" + fruitProvider.address();System.out.println(strFruitProvicer);}}}
}
/***********输出结果***************/package com.test2;public class FruitRun {/*** @param args*/public static void main(String[] args) {FruitInfoUtil.getFruitInfo(Apple.class);}}
 # 程序输出水果名称:Apple水果颜色:RED供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延安路89号红富士大厦

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

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

相关文章

几种取时间的方法(附代码)

1.上古版 最原始的取时间的方法大概就是timelocaltime了&#xff0c;见代码&#xff1a; #include <stdio.h>#include <time.h>// gcc -o time_1 time_1.cint main(){time_t tm_now;time(&tm_now);// 或者写成 tm_now time(NULL);//1.直接打印&#xff1a;197…

Python入门学习篇(十二)——内置函数匿名函数

1 内置函数——数学函数 1.1 绝对值函数 1.1.1 语法 abs(参数) # 里面的参数既可以是整数,也可以是小数1.1.2 示例代码 m -1.99 n -9 print(f"{m}的绝对值为: {abs(m)}") print(f"{n}的绝对值为: {abs(n)}")1.1.3 运行截图 1.2 求商和余数 1.2.1 语…

Linux基础知识学习

开发工具&#xff1a;Xshell7VMware 首先要明确的是在Linux系统中“目录”文件夹 而所谓"家目录"指的是每个用户所拥有的一个目录&#xff0c;通常默认在 /home 目录下&#xff0c;其名称与用户的用户名相同。 ~代表的是就就是家目录 cd ~就可以直接进入当前用户下…

PostgreSQL 作为向量数据库:入门和扩展

PostgreSQL 拥有丰富的扩展和解决方案生态系统&#xff0c;使我们能够将该数据库用于通用人工智能应用程序。本指南将引导您完成使用 PostgreSQL 作为向量数据库构建生成式 AI 应用程序所需的步骤。 我们将从pgvector 扩展开始&#xff0c;它使 Postgres 具有特定于向量数据库…

ZigBee案例笔记 - 无线点灯

文章目录 无线点灯实验概述工程关键字工程文件夹介绍Basic RF软件设计框图简单说明工程操作Basic RF启动流程Basic RF发送流程Basic RF接收流程 无线点灯案例无线点灯现象 无线点灯实验概述 ZigBee无线点灯实验&#xff08;即Basic RF工程&#xff09;&#xff0c;由TI公司提供…

C语言实验3:函数的定义

目录 一、实验要求 二、实验原理 1.函数头 2.函数体 3.函数的定义及使用 三、实验内容 1. sum函数 代码 截图 分析 2. sum函数 代码 截图 分析 3. rank_grade函数 代码 截图 分析 4. rank_grade函数 代码 截图 分析 5. 函数的嵌套使用 代码 截图 分析…

uniapp中uview组件库的丰富Upload 上传上午用法

目录 基础用法 #上传视频 #文件预览 #隐藏上传按钮 #限制上传数量 #自定义上传样式 API #Props #Methods #Slot #Events 基础用法 可以通过设置fileList参数(数组&#xff0c;元素为对象)&#xff0c;显示预置的图片。其中元素的url属性为图片路径 <template>…

python文件打包实战技巧

众所周知&#xff0c;python是一种脚本语言&#xff0c;python程序必须在python环境下运行&#xff0c;所以如果想把自己写的程序给别人看的话&#xff0c;就比较麻烦&#xff0c;他需要先配置python环境&#xff0c;对于电脑小白来说这是“要命”的事情。而且如果是客户的话&a…

PulseGAN

研究背景 远程光电容积描记术 (rPPG) 是一种非接触式技术&#xff0c;用于测量面部视频中的心脏信号。健康监测和情绪识别等许多领域都迫切需要高质量的 rPPG 脉冲信号。然而&#xff0c;由于脉搏信号不准确的限制&#xff0c;现有的大多数rPPG方法只能用于获取平均心率&#…

AD域组策略

题目&#xff1a; 除manager 组和IT组&#xff0c;所有用户隐藏C盘&#xff1b;除manager 组和IT组&#xff0c;所有普通给用户禁止使用cmdIT01用户登陆域后&#xff0c;会自动增加驱动器X&#xff0c;该驱动器自动关联DC1的C:\tools文件夹&#xff1b;sales用户组的InternetE…

ESP32S3+HX8347+3线SPI运行LVGL例程

一、clone lv_port_esp32到本地 git clone https://github.com/lvgl/lv_port_esp32.git 二、增加hx8347.c、hx8347.h components\lvgl_esp32_drivers\lvgl_tft下新增2个文件&#xff1a;hx8347.c、hx8347.h。因为lv_port_esp32中没有hx8347的驱动&#xff0c;需要自己写。这两个…

1.2.0 IGP高级特性之FRR

理论部分参考文档&#xff1a;Segment Routing TI-LFA FRR保护技术 - 华为 一、快速重路由技术 FRR(Fast Reroute)快速重路由 实现备份链路的快速切换&#xff0c;也可以与BFD联动实现对故障的快速感知。 随着网络的不断发展&#xff0c;VoIP和在线视频等业务对实时性的要求越…

web:[BJDCTF2020]The mystery of ip(ssti模板注入、Smarty 模板引擎)

题目 进入页面显示如下 点击flag页面得到ip 点击hint页面 在hint.php的源代码页面中发现 由题目可以知道要从ip入手 这里尝试抓包加上X-Forwarded-For请求头修改为127.0.0.1 因为直接将127.0.0.1输出到页面&#xff0c;可以猜测是ssti模板注入 可以继续验证 这里发现输入什么…

【数据结构】八、查找

一、基本概念 静态查找&#xff1a;只查找&#xff0c;不改变集合内数据元素 动态查找&#xff1a;有则输出元素&#xff0c;无则添加元素 二、静态查找表 2.1顺序查找 在线性表、链表、树中依次查找 2.2折半查找&#xff08;二分查找&#xff09; 在有序的线性表中&…

macos下转换.dmg文件为 .iso .cdr文件的简单方法

为了让镜像文件在mac 和windows平台通用, 所以需要将.dmg格式的镜像文件转换为.iso文件, 转换方法也非常简单, 一行命令即可 hdiutil convert /path/to/example.dmg -format UDTO -o /path/to/example.iso 转换完成后的文件名称默认是 example.iso.cdr 这里直接将.cdr后缀删…

C#高级 08Json操作

1.概念 Json是存储和交换文本信息的语法。类似于XML。Json比XML更小、更快、更易解析。Json与XML一样是一种数据格式。Json是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。Json采取完全独立于语言的文本格式&#xff0c; 但是也使用了类似于C语言的习惯。这些特性使…

2047过滤空格(C语言)

目录 一&#xff1a;题目 二&#xff1a;思路分析 三&#xff1a;代码 一&#xff1a;题目 二&#xff1a;思路分析 1.首先&#xff0c;这道题是一个字符串的问题&#xff0c;我们要先知道字符串存放在char类型的数组中的&#xff0c;并不是一个变量就可直接存放的下一个完整…

1.Linux快速入门

Linux快速入门 Linux操作系统简介Linux操作系统优点Linux操作系统发行版1. Red Hat Linux2. CentOS3. Ubuntu4. SUSE Linux5. Fedora Linux 32位与64位操作系统的区别Linux内核命名规则 Linux操作系统简介 Linux操作系统是基于UNIX以网络为核心的设计思想&#xff0c;是一个性…

云计算:OpenStack 配置云主机实例的存储挂载并实现外网互通

目录 一、实验 1. 环境 2.配置存储挂载 3.云主机实例连接外部网络&#xff08;SNAT&#xff09; 4.外部网络连接云主机实例&#xff08;DNAT&#xff09; 二、问题 1.云主机 ping 不通外部网络 2.nova list 查看云主机列表报错 3.nova list 与 virsh list --all有何区…

【代码随想录】刷题笔记Day42

前言 这两天机器狗终于搞定了&#xff0c;一个控制ROS大佬&#xff0c;一个计院编程大佬&#xff0c;竟然真把创新点这个弄出来了&#xff0c;牛牛牛牛&#xff08;菜鸡我只能负责在旁边喊加油&#xff09;。下午翘了自辩课来刷题&#xff0c;这次应该是元旦前最后一刷了&…