java基础之枚举和注解
枚举
简介
枚举:enumeration,jdk1.5中引入的新特性,用于管理和使用常量
入门案例
第一步:定义枚举,这里定义一个动物类,里面枚举了多种动物
public enum AnimalEnum {CAT, // 猫DOG, // 狗PIG // 猪
}
第二步:使用枚举类,这里会打印枚举类中的枚举值
public static void main(String[] args) {// 打印枚举类中的枚举值System.out.println("AnimalEnum.CAT = " + AnimalEnum.CAT); // CAT// 枚举值的字符串形式,和它的声明是一致的,可以把枚举值当做一个字符串常量来使用System.out.println("AnimalEnum.CAT.toString().equals(\"CAT\") = " + AnimalEnum.CAT.toString().equals("CAT")); // true
}
总结:可以把枚举类中的枚举值当做字符串常量去使用,入门案例中演示了枚举类最基本的使用方式。
基本使用
语法
枚举类中声明的常量,本质上,是以枚举类为数据类型的实例。
定义枚举类的格式:
[访问修饰符] enum <enum_name> {常量[(构造器参数)] [{ // 抽象方法的实现 }] [, ....] [;]成员变量;构造方法;自定义方法;抽象方法;
}
从格式上看,枚举类中可以定义构造方法、普通方法、抽象方法,因为枚举类中声明的常量本质上是以枚举类为数据类型的实例,这些实例中可以存储数据,也可以有自己的行为,不过在枚举类中定义方法时在语法上有一些要求。
编写枚举类的语法要求:
- 先定义枚举值,后定义方法,枚举值和方法之间用分号隔开。
- 为枚举类定义成员变量和构造方法:构造方法定义了枚举值中可以存储什么数据,构造方法默认被private修饰,所以用户无需为构造方法指明访问修饰符,这是为了防止枚举类被外部实例化。
- 为枚举类定义普通方法:普通方法可以为枚举值添加一些行为。
- 为枚举类定义抽象方法:枚举类中可以声明一个抽象方法,然后每个枚举类的实例实现此抽象方法。枚举类还可以实现某个接口,功能上类似于在枚举类中定义抽象方法。
案例1:为枚举类定义构造方法和普通方法
第一步:定义枚举类
public enum ColorEnum {// 枚举类中如果定义了构造方法,声明枚举值时要使用这个构造方法,它表示枚举值中可以存储的数据RED(1, "RED", "红色"),BLUE(2, "BLUE", "蓝色"),BLACK(3, "BLACK", "黑色");public Integer i;public String name;public String desc;// 构造方法ColorEnum(int i, String name, String desc) {this.i = i;this.name = name;this.desc = desc;}// 普通方法public void say() {System.out.println("我的颜色是:" + this.name);}
}
第二步:使用枚举类
public static void main(String[] args) {// 1. 使用枚举值System.out.println("ColorEnum.RED = " + ColorEnum.RED); // ColorEnum.RED = RED// 2. 枚举值中的普通方法ColorEnum.RED.say(); // 我的颜色是:RED
}
案例2:为枚举类定义抽象方法
第一步:定义枚举类
public enum OperationEnum {PLUS(1, "加法") {@Overridepublic double apply(double x, double y) {return x + y;}},MINUS (2, "减法") {@Overridepublic double apply(double x, double y) {return x - y;}};public final Integer id;public final String name;// 构造方法OperationEnum(Integer id, String name) {this.id = id;this.name = name;}// 声明抽象方法public abstract double apply(double x, double y);
}
第二步:使用枚举类
public static void main(String[] args) {// 枚举类中的抽象方法double apply = OperationEnum.PLUS.apply(1, 2);System.out.println("apply = " + apply); // 3
}
案例3:枚举类实现接口
// 定义接口
public interface Inter {double apply(double a, double b);
}// 定义枚举类
public enum Operation implements Inter {MINUS{public double apply(double a, double b){return a - b;}},PLUS{public double apply(double a, double b){return a + b;}};
}
使用方式和在枚举类中定义抽象方法基本类型。
枚举类的反编译
枚举类是一种特殊的类,枚举类和普通类一样,也会生成一个类文件,Java编译器会为枚举类添加许多方法。
案例:入门案例中的Animal类,使用javap命令来反编译 javap -v AnimalEnum.class
,这里只展示反编译后的部分结果。
// 枚举类的底层继承了Enum类
public final class org.wyj.enumeration.AnimalEnum extends java.lang.Enum<org.wyj.enumeration.AnimalEnum>
{public static final org.wyj.enumeration.AnimalEnum CAT; // CATdescriptor: Lorg/wyj/enumeration/AnimalEnum;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUMpublic static final org.wyj.enumeration.AnimalEnum DOG; // DOGdescriptor: Lorg/wyj/enumeration/AnimalEnum;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUMpublic static final org.wyj.enumeration.AnimalEnum PIG; // PIGdescriptor: Lorg/wyj/enumeration/AnimalEnum;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM// values方法,返回枚举类中的所有实例public static org.wyj.enumeration.AnimalEnum[] values();descriptor: ()[Lorg/wyj/enumeration/AnimalEnum;flags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=0, args_size=00: getstatic #1 // Field $VALUES:[Lorg/wyj/enumeration/AnimalEnum;3: invokevirtual #2 // Method "[Lorg/wyj/enumeration/AnimalEnum;".clone:()Ljava/lang/Object;6: checkcast #3 // class "[Lorg/wyj/enumeration/AnimalEnum;"9: areturnLineNumberTable:line 3: 0// valueOf方法,根据字符串常量来查找枚举类实例public static org.wyj.enumeration.AnimalEnum valueOf(java.lang.String);descriptor: (Ljava/lang/String;)Lorg/wyj/enumeration/AnimalEnum;flags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: ldc #4 // class org/wyj/enumeration/AnimalEnum2: aload_03: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;6: checkcast #4 // class org/wyj/enumeration/AnimalEnum9: areturnLineNumberTable:line 3: 0LocalVariableTable:Start Length Slot Name Signature0 10 0 name Ljava/lang/String;
}
案例2:反编译有抽象方法的枚举类,javap -v OperationEnum.class
// 有抽象方法的枚举类,枚举类在底层实际上是一个抽象类
public abstract class org.wyj.enumeration.OperationEnum extends java.lang.Enum<org.wyj.enumeration.OperationEnum>
{public static final org.wyj.enumeration.OperationEnum PLUS;descriptor: Lorg/wyj/enumeration/OperationEnum;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUMpublic static final org.wyj.enumeration.OperationEnum MINUS;descriptor: Lorg/wyj/enumeration/OperationEnum;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
}
枚举类中的每个枚举值都会生成一个匿名内部类,javap -v "OperationEnum\$1.class"
,注意,这里美元符在命令行需要特殊处理
final class org.wyj.enumeration.OperationEnum$1 extends org.wyj.enumeration.OperationEnum
{// 构造方法org.wyj.enumeration.OperationEnum$1(java.lang.String, int, java.lang.Integer, java.lang.String);descriptor: (Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;)Vflags:Code:stack=6, locals=5, args_size=50: aload_01: aload_12: iload_23: aload_34: aload 46: aconst_null7: invokespecial #1 // Method org/wyj/enumeration/OperationEnum."<init>":(Ljava/lang/String;ILjava/lang/Integer;Ljava/lang/String;Lorg/wyj/enumeration/OperationEnum$1;)V10: returnLineNumberTable:line 5: 0LocalVariableTable:Start Length Slot Name Signature0 11 0 this Lorg/wyj/enumeration/OperationEnum$1;0 11 3 id Ljava/lang/Integer;0 11 4 name Ljava/lang/String;// 实现父类中的抽象方法public double apply(double, double);descriptor: (DD)Dflags: ACC_PUBLICCode:stack=4, locals=5, args_size=30: dload_11: dload_32: dadd // add命令,证明这是加法3: dreturnLineNumberTable:line 8: 0LocalVariableTable:Start Length Slot Name Signature0 4 0 this Lorg/wyj/enumeration/OperationEnum$1;0 4 1 x D0 4 3 y D
}
总结:反编译结果中枚举类的成员,可以看到,
- 枚举类默认继承了Enum类
- 枚举类中有两个重要的静态方法:
- values():
public static 枚举类[] values();
:返回枚举类中所有常量组成的数组 - valueOf(String):
public static 枚举类 valueOf(java.lang.String);
:传入枚举类中常量的字符串形式,返回枚举类中的常量
- values():
- 声明了抽象方法的枚举类,枚举类中的每个枚举值都会使用一个匿名内部类来实现
枚举类的默认父类 Enum类
所有的枚举类都默认继承了Enum类。
源码分析:
public abstract class Enum<E extends Enum<E>>implements Comparable<E>, Serializable {// 枚举值的字符串形式private final String name;public final String name() {return name;}// 表示枚举值在枚举类中被声明的顺序,从0开始计数private final int ordinal;public final int ordinal() {return ordinal;}// 构造方法protected Enum(String name, int ordinal) {this.name = name;this.ordinal = ordinal;}// 重写Object类中的方法public String toString() {return name;}public final boolean equals(Object other) {return this==other;}public final int hashCode() {return super.hashCode();}protected final Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException();}// 两个枚举值的比较public final int compareTo(E o) {Enum<?> other = (Enum<?>)o;Enum<E> self = this;if (self.getClass() != other.getClass() && // optimizationself.getDeclaringClass() != other.getDeclaringClass())throw new ClassCastException();return self.ordinal - other.ordinal;}// 阻止反序列化private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {throw new InvalidObjectException("can't deserialize enum");}private void readObjectNoData() throws ObjectStreamException {throw new InvalidObjectException("can't deserialize enum");}
}
枚举值的默认父类几乎不会被使用到,这里只做了解
实战案例
案例1:switch和枚举类
如果switch语句对应的变量是一个枚举类的实例,case语句后必须直接使用枚举类中的常量
案例:
public static void main(String[] args) {AnimalEnum DOG = AnimalEnum.DOG;switch (DOG) {case DOG:System.out.println("狗"); // 狗break;case PIG:System.out.println("猪");break;case CAT:System.out.println("猫");break;default:System.out.println("未知");break;}
}
案例2:生产中定义枚举类的常见方式
public enum ColorEnum {// 枚举类中如果定义了构造方法,声明枚举值是要使用这个构造方法,它表示枚举值中可以存储的数据RED(1, "RED", "红色"),BLUE(2, "BLUE", "蓝色"),BLACK(3, "BLACK", "黑色");public final Integer id;public final String name;public final String desc;// 构造方法ColorEnum(int id, String name, String desc) {this.id = id;this.name = name;this.desc = desc;}// 根据id获取枚举值实例public ColorEnum getEnumById(Integer id) {ColorEnum[] values = values();for (ColorEnum value : values) {if (value.id.equals(id)) {return value;}}return null;}// 返回枚举值的集合public List<ColorEnum> getEnumList() {return Arrays.asList(values());}// 普通方法public void say() {System.out.println("我的颜色是:" + this.desc);}
}
这里需要注意的是,每个枚举值都有自己的id和name,id用于数据库的存储,name用于平时使用,同时,定义了根据id来获取枚举值的方法,这是实际开发中用的最多的。
注解
简介
注解:Annotation,Java1.5引入的功能,它可以被标注在类、方法、字段上,用于指明某种特性,也可以用它来存储配置信息。
注解的使用,有两种场景,
- 一种是在源码中,告诉程序员某个信息,例如@Override注解,告诉程序员当前方法是父类中某个方法的重写,
- 一种是在运行时,通过反射获取注解信息,此时,注解可以用于存储配置信息。
基本使用
java中的元注解
元注解:负责标注其它的注解,用于指明注解的特性,是用户自定义注解是需要用到的
java中的5个元注解:
1、@Retention:指定注解的生命周期
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {RetentionPolicy value(); // 指定注解的生命周期
}
这里涉及到的两个枚举类:
a. 定义了注解的生命周期常量的枚举类:
// 定义了注解有哪些生命周期
public enum RetentionPolicy {// 注解只存在于源码中,会被编译器丢掉。注解只存在于源码阶段SOURCE,// 注解会被编译器编译到类文件中,但是运行时不会把注解信息加载到虚拟机中,这是默认的生命周期。// 注解只存在于源码阶段和编译阶段CLASS,// 注解会被加载到虚拟机中,此时可以通过反射获取注解中存储的信息,// 注解存在于源码阶段、编译阶段和运行时阶段RUNTIME
}
b. 定义了注解的使用位置常量的枚举类:
// 枚举类中的常量代表代表一个编译单元中的某个位置
public enum ElementType {// 类、接口或枚举TYPE,// 字段,包括枚举常量FIELD,// 方法声明METHOD,// 参数PARAMETER,// 构造器CONSTRUCTOR,// 局部变量LOCAL_VARIABLE,// 注解,一个可以应用于注解上的注解,类似于元注解。ANNOTATION_TYPE,// 包PACKAGE,// 表示注解可以应用于类型参数声明,案例 public class MyClass<@MyAnnotation T> {}TYPE_PARAMETER,// 表示注解可以应用于类型使用的地方,例如变量声明、方法返回类型、方法参数类型等TYPE_USE
}
2、@Documented:被@Documented注解的注解会被javadoc之类的工具处理,它们的信息会被添加到帮助文档中,默认情况下,注解是不会被添加到帮助文档中的。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
3、@Target:指明了注解可以出现在什么位置。默认情况下,枚举可以被应用到除了泛型、包以外的任何地方
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {// 一个ElementType类型的数组,表明注解可以被应用在什么位置ElementType[] value();
}
4、@Inherited:继承。表示一个注解可以被继承
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
5、@Repeatable:java1.8新增的注解,允许一个类型的注解在同一个程序元素上重复出现。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {// 指定哪个注解可以重复出现Class<? extends Annotation> value();
}
java中自带的注解
1、@Override:只能用于方法,只存在于源码阶段,表明当前方法重写了父类的方法。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
2、@Deprecated:这个注解会被添加到文档中,存在于运行阶段,可以注解类、方法等。一个程序元素被@Deprecated注解,表明开发者不推荐用户使用这个程序元素
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
3、@SuppressWarnings:告诉编译器忽略指定类型的告警,可以标注在类、字段、方法、局部变量等位置。
使用方式:
- 告诉编译器忽略类型转换警告信息:@SuppressWarnings(“unchecked”)
- 告诉编译器忽略被过时告警:@SuppressWarnings(“deprecation”),使用了被@Deprecated标注的元素,编译器会发出过时告警
- 告诉编译器同时忽略多个告警信息:
- 第一种写法:@SuppressWarnings(“unchecked”, “deprecation”)
- 第二种写法:@SuppressWarnings(value={“unchecked”, “deprecation”})
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {// 指定告警类型String[] value();
}
4、@FunctionalInterface:这个注解会被添加到文档中,存在于运行阶段,可以注解接口,表明被它注解的接口是一个函数式接口,也就是接口中只有一个方法的接口。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
5、@SafeVarargs:这个注解会被添加到文档中,存在于运行阶段,可以注解构造器、方法。参数安全类型注解,它的目的是提醒开发者不要用参数做一些不安全的操作,它的存在会阻止编译器产生 unchecked 这样的警告。它是在 Java 1.7 的版本中加入的。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {}
自定义注解
自定义注解的语法:
[public] @interface 注解名 { 参数类型 成员变量名() [default 值];....
}
语法讲解:
- 注解只有成员变量,没有成员方法。
- 声明成员变量的格式:
数据类型 成员变量名() [default 值]
。成员变量可以有默认值,通过default关键字来指定。 - 如果注解中只有一个属性,那么属性名称应该为value,这是一个默认的约定。
注解的使用:把注解放在合适的位置,@注解名(属性=值 [,...])
,
- 如果注解中没有属性,那么括号可以省略不写。
- 如果属性有默认值,那么在使用时就不需要为属性赋值了如果想要覆盖原有的属性也可以赋值。
- 如果属性名是value,value可以省略不写
注解的获取:在运行阶段,需要通过反射,获取注解中的信息,如果想要让注解被反射获取,注解必须要被@Retention(RetentionPolicy.RUNTIME)
注解,它表示注解的生命周期策略是运行时存在。
标记注解:不包含任何成员变量的注解
使用案例
案例1:自定义一个普通注解,指定一个类的初始化方法
第一步:定义注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InitMethod {// 注解中存储的数据,这里没有什么意义,仅仅演示如何操作注解的属性String value();String name() default "im";
}
第二步:使用注解,注解如果没有指定使用范围,默认可以使用在类上、方法上
public class InitDemo {public InitDemo() { }@InitMethod(value = "1", name = "2")public void test1(int b) {int a = 1;System.out.println("执行test1方法");}
}
第三步:通过反射获取注解
public static void main(String[] args) {try {Class<?> aClass = Class.forName("org.wyj.anno.InitDemo");// 获取类上的注解Annotation[] declaredAnnotations = aClass.getDeclaredAnnotations();for (Annotation declaredAnnotation : declaredAnnotations) {System.out.println("declaredAnnotation = " + declaredAnnotation);}// 获取方法上的指定注解Method[] methods = aClass.getMethods();for (Method method : methods) {if (method.isAnnotationPresent(InitMethod.class)) {InitMethod annotation = method.getAnnotation(InitMethod.class);System.out.println(annotation);System.out.println(annotation.value() + ":" + annotation.name());}}} catch (ClassNotFoundException e) {throw new RuntimeException(e);}
}
总结:这个案例演示了注解的基本使用,实际开发中,这是使用最多的方式
案例2:可重复出现的注解
第一步:定义注解
// 可以重复使用的注解
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Persons.class) // 使用@Repeatable注解把当前注解定义为可重复注解时,要指定它的容器注解
public @interface Person {String role();
}// 注解的容器注解
@Retention(RetentionPolicy.RUNTIME)
public @interface Persons {Person[] value();
}
第二步:注解的使用
@Person(role = "艺术家")
@Person(role = "士兵")
@Person(role = "厨师")
public class Man {
}
第三步:通过反射获取注解
// 测试容器注解
public static void main(String[] args) {try {Class<?> aClass = Class.forName("org.wyj.anno.Man");Person[] annotationsByType = aClass.getAnnotationsByType(Person.class);for (Person person : annotationsByType) {System.out.println(person.role());}} catch (ClassNotFoundException e) {e.printStackTrace();}
}
总结:
- 在使用@Repeatable来注解一个可重复注解的时候,需要提供一个容器注解,容器注解用于装载可重复注解。
- 容器注解:@Repeatable注解需要使用到的工具注解,注解中的属性是一个数组,数组中元素的数据类型是被@Repeatable注解的注解。
案例3:测试注解的继承
第一步:定义注解,一个可以被继承的注解
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedTest {
}
第二步:注解的使用
// 父类
@InheritedTest
public class InheritedDemo {@InitMethod("aaa")public void init() { }
}// 子类
public class InheritedDemoSon extends InheritedDemo { }
第三步:通过反射获取注解
public static void main(String[] args) {try {Class<?> aClass = Class.forName("org.wyj.anno.InheritedDemoSon");// 类上的注解System.out.println(aClass.isAnnotationPresent(InheritedTest.class)); // true// 方法上的注解for (Method method : aClass.getMethods()) {if (method.getName().equals("init")) {System.out.println("method.isAnnotationPresent(InitMethod.class) = "+ method.isAnnotationPresent(InitMethod.class)); // true}}} catch (ClassNotFoundException e) {throw new RuntimeException(e);}
}
总结:
- 注解的继承:在继承关系中,
- 对于方法上的注解,子类会继承父类的方法,同时也会方法上的注解,无论该注解有没有被@Inherited修饰,
- 对于类上的注解,如果它被@Inherited注解修饰,它才可以被子类继承,但也仅限于子类,不包括子类的子类
查看一个注解反编译后的字节码
案例:以@InitMethod为例,javap -v InitMethod.class
public interface org.wyj.anno.InitMethod extends java.lang.annotation.Annotation
{public abstract java.lang.String value();descriptor: ()Ljava/lang/String;flags: ACC_PUBLIC, ACC_ABSTRACTpublic abstract java.lang.String name();descriptor: ()Ljava/lang/String;flags: ACC_PUBLIC, ACC_ABSTRACT
}
总结:可以看到,注解实际上是一个接口,并且每个注解都默认继承Annotation接口,
注解的公共父接口 Annotation接口
所有的注解默认都会继承Annotation接口,这个动作由编译器来完成
源码:
public interface Annotation {boolean equals(Object obj);int hashCode();String toString();Class<? extends Annotation> annotationType();
}
总结
这里介绍了注解的基本特性,演示了注解的基本使用。如果有补充,欢迎评论。
Q&A
1、枚举类的构造方法,为什么不可以是public?
由于枚举实例是固定的,开发者不能在运行时创建新的枚举实例。因此,构造方法不能是public的,Java编译器自动将枚举的构造方法设为private,以确保枚举实例只能在枚举类内部定义。这是为了确保枚举实例的唯一性和安全性。
2、枚举类可以同时是泛型类吗?
不可以,枚举类不可以是泛型类,但是枚举类中可以定义泛型方法,因为枚举类不可以从外部实例化,所以在枚举类上声明泛型没有意义。
相关文章:
java基础之枚举和注解
枚举 简介 枚举:enumeration,jdk1.5中引入的新特性,用于管理和使用常量 入门案例 第一步:定义枚举,这里定义一个动物类,里面枚举了多种动物 public enum AnimalEnum {CAT, // 猫DOG, // 狗PIG // …...
前端开发本地配置 HTTPS 全面详细教程
分为两步:生成证书、本地服务配置使用证书一、HTTPS 的基本概念 HTTPS 是一种安全的 HTTP 协议,它通过 SSL/TLS 对数据进行加密,确保数据在传输过程中不被窃取或篡改。在前端开发中,某些功能(如 Geolocation API、Web…...
C语言中宏的高级应用
一、宏的核心高级特性 1. 变参宏(Variadic Macros) 支持不定数量参数,用于灵活处理格式化字符串、日志输出等场景。 #include <stdio.h>// 定义支持可变参数的调试宏 #define DEBUG_LOG(format, ...) \printf("[DEBUG] %s:%d |…...
Simulink 数据字典(Data Dictionary)详解:使用场景、存储内容与调用方法
1. 引言 在 Simulink 建模中,随着模型复杂度增加,参数管理变得尤为重要。传统方法(如 MATLAB 工作区变量或脚本)在团队协作或大型项目中容易导致数据分散、版本混乱。数据字典(Data Dictionary) 提供了一种…...
部署yolo到k230教程
训练:K230 借助 AICube部署AI 视觉模型 YOLO等教程_嘉楠 ai cube多标签分类-CSDN博客K230模型训练ai cube报错生成部署文件异常_aicube部署模型显示生成部署文件异常-CSDN博客 部署: # 导入必要的库和模块 import os import ujson # 超快的JS…...
【高频考点精讲】第三方库安全审计:如何避免引入带漏洞的npm包
大家好,我是全栈老李。今天咱们聊一个前端工程师必须掌握的生存技能——如何避免把带漏洞的npm包引入项目。这可不是危言耸听,去年某大厂就因为在生产环境用了有漏洞的lodash版本,被黑客利用原型污染漏洞直接攻破后台系统。 为什么npm包会变成"定时炸弹"? npm生…...
【后端】主从单体数据库故障自动切换,容灾与高可用
在现代企业级应用中,数据库的高可用性和容灾能力是保障业务连续性的关键。尤其是在一些对稳定性要求较高的业务场景中,当主数据库发生故障时,如何快速切换到备用数据库并确保业务不受影响,成为了一个重要课题。本文将介绍一种基于 SpringBoot 和 Druid 数据源的解决方案,通…...
AI编程案例拆解|基于机器学习XX评分系统-后端篇
文章目录 5. 数据集生成使用KIMI生成数据集 6. 后端部分设计使用DeepSeek生成神经网络算法设计初始化项目在Cursor中生成并提问前后端交互运行后端命令 注意事项 关注不迷路,励志拆解100个AI编程、AI智能体的落地应用案例为了用户的隐私性,关键信息会全部…...
数据库设置外键的作用
数据库外键(Foreign Key)是关系型数据库中用于建立表与表之间关联关系的重要约束,其核心作用是确保数据的一致性、完整性和关联性。以下是外键的主要作用及相关说明: 1. 建立表间关联关系 外键通过引用另一张表的主键࿰…...
从基础到实战的量化交易全流程学习:1.1 量化交易本质与行业生态
从基础到实战的量化交易全流程学习:1.1 量化交易本质与行业生态 在金融市场数字化转型的浪潮中,量化交易凭借数据驱动的科学性与自动化执行的高效性,成为连接金融理论与技术实践的核心领域。本文作为系列开篇,将从本质解析、行业生…...
路由交换网络专题 | 第八章 | GVRP配置 | 端口安全 | 端口隔离 | Mux-VLAN | Hybrid
拓扑图 (1)通过 LSW1 交换机配置 GVRP 协议同步 VLAN 信息到所有接入层设备。 基于 GARP 机制:GVRP 是通用属性注册协议 GARP(Generic Attribute Registration Protocol)的一种应用,用于注册和注销 VLAN 属…...
重定向和语言级缓冲区【Linux操作系统】
文章目录 重定向重定向的原理重定向系统调用接口进程替换不会影响重定向bash命令行中输入,输出,追加重定向的区别输出重定向输入重定向追加重定向命令行中只支持向文件描述符为0,1,2的标准流进行>,>>…...
Channel如何安全地尝试发送数据
在 Go 语言中,无法直接检查 channel 是否关闭(没有类似 IsClosed(ch) 的方法),但可以通过 非阻塞发送 或 select 语句 安全地尝试发送数据,避免向已关闭的 channel 发送数据导致 panic。以下是具体实现方式:…...
MH2103 MH22D3系列的JTAG/SWD复用功能和引脚映射,IO初始化的关键点
MH21xx和MH22xx内核集成了串行/JTAG调试接口(SWJ-DP)。这是标准的ARM CoreSight调试接 口,包括JTAG-DP接口(5个引脚)和SW-DP接口(2个引脚)。 ● JTAG调试接口(JTAG-DP)为AHP-AP模块提供5针标准JTAG接口。 ● 串行调试接口(SW-DP)为AHP-AP模块提供2针(时钟࿰…...
Tortoise-ORM级联查询与预加载性能优化
title: Tortoise-ORM级联查询与预加载性能优化 date: 2025/04/26 12:25:42 updated: 2025/04/26 12:25:42 author: cmdragon excerpt: Tortoise-ORM通过异步方式实现级联查询与预加载机制,显著提升API性能。模型关联关系基础中,定义一对多关系如作者与文章。级联查询通过s…...
【C++11】列表初始化
📝前言: 这篇文章我们来讲讲C11引入的列表初始化{},注意这不是构造函数里的初始化列表!!! 在阅读文章之前,请你记住一句重点:万物皆可{}初始化 🎬个人简介:努…...
基于Cherry Studio + DeepSeek 搭建本地私有知识库!
在当今数字化时代,知识管理变得越来越重要。无论是个人还是企业,都希望能够高效地存储、管理和检索知识。而借助 AI 技术,我们可以实现更加智能的知识库系统。本文将详细介绍如何使用 Cherry Studio 和 DeepSeek 搭建本地私有知识库ÿ…...
栈相关算法题解题思路与代码实现分享
目录 前言 一、最小栈(LeetCode 155) 题目描述 解题思路 代码实现(C) 代码解释 二、栈的压入、弹出序列(剑指 Offer JZ31) 题目描述 解题思路 代码实现(C) 代码解释 总结…...
MongoDB Atlas与MongoDB连接MCP服务器的区别解析
MongoDB Atlas作为全托管的云数据库服务,与本地自建MongoDB实例在连接MCP(Model Context Protocol)服务器时存在显著差异。以下从配置方式、安全机制、功能特性三个维度对比两者的区别: 连接配置差异 • 本地MongoDB:…...
服务器传输数据存储数据建议 传输慢的原因
一、JSON存储的局限性 1. 性能瓶颈 全量读写:JSON文件通常需要整体加载到内存中才能操作,当数据量大时(如几百MB),I/O延迟和内存占用会显著增加。 无索引机制:查找数据需要遍历所有条目(时间复…...
【大模型】Coze AI 智能体工作流从配置到使用实战详解
目录 一、前言 二、工作流介绍 2.1 什么是工作流 2.2 工作流与对话流 2.2.1 两者区别 2.3 工作流节点介绍 2.3.1 工作流节点说明 2.3.2 开始节点与结束节点 2.4 工作流入口 2.4.1 自定义智能体入口 2.4.2 从资源库新增工作流 2.5 工作流使用限制 三、工作流配置与使…...
Java后端开发——分层解耦详解
文章目录 一、三层架构1.1 概述1.2 具体实现方法 二、分层解耦2.1 以往问题2.2 概念解释2.3 解耦思路 三、Spring核心:IOC & DI3.1 快速入门3.2 IOC(控制反转)详解3.3 DI(依赖注入)详解 注入方式 标签:…...
论文如何降低AIGC?(完整指南版)
最近一段时间,关于论文AIGC率太高怎么办的问题,真的是知乎、小红书、B站到处都是! 尤其是今年知网一升级,连纯手写的内容都能给你标疑似AIGC,简直离谱啊兄弟姐妹们😭! 那论文到底怎么降低AIGC…...
【LCMM】纵向轨迹模型,组轨迹模型
latent_class_mixed_models 基础知识 增长混合模型(GMM)和潜在类别增长模型(LCGA)的核心区别确实主要在于是否允许类别内存在随机效应,但两者的差异还涉及模型灵活性、假设和应用场景等方面。以下是详细对比…...
Flask + ajax上传文件(三)--图片上传与OCR识别
本教程将详细介绍如何使用Flask框架构建一个图片上传与文字识别(OCR)的Web应用。我们将使用EasyOCR作为OCR引擎,实现一个支持中文和英文识别的完整应用。 环境准备 首先,确保你已经安装了Python 3.7+环境,然后安装必要的依赖库: pip install flask easyocr pillow werkz…...
观察者模式 (Observer Pattern)
观察者模式(Observer Pattern)是一种行为型设计模式。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象的状态发生变化时,会自动通知所有观察者对象,使它们能够自动更新自己的状态。 一、基础 1. 意图 核心目的:定义对象间的一种一对…...
【Leetcode 每日一题】2444. 统计定界子数组的数目
问题背景 给你一个整数数组 n u m s nums nums 和两个整数 m i n K minK minK 以及 m a x K maxK maxK。 n u m s nums nums的定界子数组是满足下述条件的一个子数组: 子数组中的 最小值 等于 m i n K minK minK。子数组中的 最大值 等于 m a x K maxK maxK…...
LeetCode热题100——70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到楼顶。 1 阶 1 阶2 阶 示例 2: …...
黑马Java基础笔记-4
方法 什么是方法 方法是程序中最小的执行单元。 形参和实参 调用 直接调用 getSum(10,20,30);赋值调用 int sum getSum(10,20,30);输出调用 System.out.println(getSum(10,20,30));方法的重载 在同一个类中,定义了多个同名的方法,这些同名的方法…...
【Python】Python中的浅拷贝和深拷贝
在Python中,浅拷贝(shallow copy)和深拷贝(deep copy)是两种不同的对象复制方式,它们在复制对象时的行为有所不同: 浅拷贝(Shallow Copy) 浅拷贝是创建一个新对象&…...
使用 LangGraph 和 Elasticsearch 构建强大的 RAG 工作流
作者:来自 Elastic Neha Saini 在这篇博客中,我们将向你展示如何配置和自定义 LangGraph Retrieval Agent 模板与 Elasticsearch,以构建一个强大的 RAG 工作流,实现高效的数据检索和由 AI 驱动的响应。 Elasticsearch 原生集成了…...
云原生--核心组件-容器篇-2-认识下Docker(三大核心之镜像,容器,仓库)
1、Docker基本概念 (1)、定义 Docker是一种开源的应用容器引擎,是基于操作系统级虚拟化技术。允许开发者将应用程序及其依赖项打包到一个可移植的容器中,然后发布到任何支持Docker的环境中运行。Docker容器是轻量级、独立且可执…...
智慧园区IOT项目与AI时代下的机遇 - Java架构师面试实战
在互联网大厂的Java求职者面试中,面试官通常会针对实际业务场景提出一系列问题。以下是关于智慧园区IOT项目及AI时代下的机遇的面试模拟对话。 第一轮提问 面试官:马架构,请简要介绍下智慧园区IOT项目的整体架构设计。 马架构:…...
Unity中文件上传以及下载,获取下载文件大小的解决方案
首先现在Unity插件那么的广泛的情况下,很多东西都不需要自己实现,直接使用第三方插件就可以了,但为什么这里需要自己写,接下来说明原因。 在Unity商城中有很多关于关于网络接口调用的插件,其中有一款叫BestHTTP这款使用比较广泛的插件,不知道朋友们是不是都知道,是不是…...
Word/WPS 删除最后一页空白页,且保持前面布局样式不变
如题,试了多种方法,都不行。主要是可能的原因太多了,没有通解,这只是适用于我的情况。 解决方案: 首先光标放在倒数第二页(即想保留的最后一页),点击页面右下角这个小箭头ÿ…...
MySQL长事务的隐患:深入剖析与解决方案
MySQL长事务的隐患:深入剖析与解决方案 一、什么是长事务? 在数据库系统中,长事务(Long Transaction)通常指执行时间超过预期或系统设定阈值的事务。对于MySQL而言,虽然没有严格的时间定义,但一般认为执行时间超过数…...
【Tauri】桌面程序exe开发 - Tauri+Vue开发Windows应用 - 比Electron更轻量!8MB!
效果图 Tauri的二进制文件体积显著小于Electron,安装包通常缩小80%以上。应用启动更快,内存占用更低,尤其在老旧设备上体验更流畅。 写在前面 Tauri官网 https://tauri.app/zh-cn/支持语言:js、ts、rust、.net编译出来的exe文件&…...
2025春季NC:3.1TheTrapeziumRule
3.1TheTrapeziumRule 📐 The Idea Instead of finding the exact area under a curve y = f ( x ) y = f(x) y=...
【摩尔定律】
一、摩尔定律的核心定义 原始表述(1965年) “集成电路上可容纳的晶体管数量,每隔约 18-24个月 便会增加一倍,同时性能提升一倍,而成本下降一半。” 简化理解 芯片的 晶体管密度 和…...
Maven 依赖冲突调解与版本控制
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
《Python Web部署应知应会》Flask网站隐藏或改变浏览器URL:从Nginx反向代理到URL重写技术
Flask网站隐藏或改变浏览器显示URL地址的实现方案:从Nginx反向代理到URL重写技术 引言 在Web应用开发中,URL路径的安全性往往被忽视,这可能导致网站结构和后端逻辑被攻击者轻易推断。对于Flask框架开发的网站,如何隐藏或改变浏览…...
6.2 内容生成与营销:个性化内容创作与营销策略优化
随着消费者对个性化体验的需求日益增长,传统的内容创作与营销方式已难以满足市场竞争的需要。基于大语言模型(LLM)与智能代理(Agent)的技术为企业提供了全新的解决方案,能够实现高效、精准、规模化的内容生…...
平面连杆机构(上)
1、平面四杆机构的类型与演化 1)平面四杆机构的类型 a、铰链四杆机构:曲柄摇杆机构、双曲柄机构、双摇杆机构 b、其他四杆机构:曲柄滑块机构、导杆机构、滑块机构、双滑块机构、偏心轮四杆机构...... 2)平面四杆机构的演化 a、…...
【数据结构刷题】顺序表与ArrayList
【数据结构刷题】顺序表与ArrayList 1. 杨辉三角2. 合并两个有序数组 1. 杨辉三角 LC链接:杨辉三角 //杨辉三角import java.util.ArrayList; import java.util.List;public class Demo1 {public List<List<Integer>> generate(int numRows) {List<…...
顶点着色器和片元着色器染色+表面体着色器染色
顶点/片元着色器染色 创建材质球及Shader同名文件VFColor //Update NOTE:replaced mul(UNITY_MATRIX_MVP,*) with UnityObjectToClipPos(*) Shader "CreateTest/VFColor" {Properties{_Color("颜色",Color)(1,1,1,1)}SubShader{Pass{//顶点片…...
240426 leetcode exercises
240426 leetcode exercises jarringslee 文章目录 240426 leetcode exercises[1669. 合并两个链表](https://leetcode.cn/problems/merge-in-between-linked-lists/?envTypeproblem-list-v2&envIdlinked-list)🔁基础版 保存断点,先拼再补…...
代码随想录算法训练营Day35
卡码网46.携带研究材料 力扣494.目标和【meidum】 力扣416.分割等和子集【medium】 一、卡码网46.携带研究材料 题目链接:卡码网46.携带研究材料 视频链接:代码随想录 题解链接:代码随想录 1、思路 dp[i][j] 表示从下标为 [0-i] 的物品里任意…...
C++17 折叠表达式
C17 引入的折叠表达式(Fold Expressions) 是处理可变参数模板(Variadic Templates)的革命性特性。它通过简洁的语法,使得对参数包(Parameter Pack)的操作更加直观和高效,避免了传统的…...
Ubuntu编译opencv源码
准备 Ubuntu版本:22.04opencv版本:4.9.0没下载Ubuntu镜像的可以在清华镜像下载 本文以4.9.0版本演示,可根据自身情况选择 安装JDK和依赖项 本次编译主要为了获取java在linux环境下的动态库,所以需要在虚拟机上下载jdk # 安装…...
一种滑窗像素自差值的深度学习损失函数
公司项目,已申请专利。 深度学习作为新兴技术在图像领域蓬勃发展,因其自主学习图像数据特征避免了人工设计算法的繁琐,精准的检测性能、高效的检测效率以及对各种不同类型的图像任务都有比较好的泛化性能,使得深度学习技术在图像领…...