您的位置:首页 > 健康 > 美食 > 效果图公司排名_邯郸网站推广_百度站长seo_制作一个app软件需要多少钱

效果图公司排名_邯郸网站推广_百度站长seo_制作一个app软件需要多少钱

2024/10/31 5:05:45 来源:https://blog.csdn.net/gaosw0521/article/details/142981926  浏览:    关键词:效果图公司排名_邯郸网站推广_百度站长seo_制作一个app软件需要多少钱
效果图公司排名_邯郸网站推广_百度站长seo_制作一个app软件需要多少钱

1 Java 注解

1.1 概念

  • 定义:注解(Annotation)是在 Java 1.5 时引入的概念,同 classinterface 一样,属于一种类型。
  • 作用:注解提供了一系列数据用来装饰程序代码(类、方法、字段等),但注解并不是所装饰代码的一部分,它对代码的运行效果没有直接影响,由编译器决定该执行哪些操作。

1.2 注解的生命周期策略

  • 定义:定义在 RetentionPolicy 枚举中。
  • 类型
    • SOURCE:在源文件中有效,被编译器丢弃。
    • CLASS:在编译器生成的字节码文件中有效,但在运行时会被处理类文件的 JVM 丢弃。
    • RUNTIME:在运行时有效。这是注解生命周期中最常用的一种策略,它允许程序通过反射的方式访问注解,并根据注解的定义执行相应的代码。

1.3 注解的类型

  • 定义:定义在 ElementType 枚举中。
  • 类型
    • TYPE:用于类、接口、注解、枚举。
    • FIELD:用于字段(类的成员变量),或者枚举常量。
    • METHOD:用于方法。
    • PARAMETER:用于普通方法或者构造方法的参数。
    • CONSTRUCTOR:用于构造方法。
    • LOCAL_VARIABLE:用于变量。
    • ANNOTATION_TYPE:用于注解。
    • PACKAGE:用于包。
    • TYPE_PARAMETER:用于泛型参数。
    • TYPE_USE:用于声明语句、泛型或者强制转换语句中的类型。
    • MODULE:用于模块。

1.4 代码示例

1.4.1 编写JsonField 注解

/*** @package: com.yunyang.javabetter.oop.annotation* @description: 自定义JsonField 注解* @author: Yunyang* @date: 2024/10/16  14:18* @version:1.0**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonField {public String value() default "";
}

分析:

  • JsonField 注解的生命周期是 RUNTIME,也就是运行时有效。
  • JsonField 注解装饰的目标是 FIELD,也就是针对字段的。
  • 创建注解需要用到 @interface 关键字。
  • JsonField 注解有一个参数,名字为 value,类型为 String,默认值为一个空字符串。
  • value 允许注解的使用者提供一个无需指定名字的参数。举个例子,我们可以在一个字段上使用 @JsonField(value = “沉默王二”),也可以把 value = 省略,变成 @JsonField(“沉默王二”)。
  • default ""允许我们在一个字段上直接使用 @JsonField,而无需指定参数的名和值。

1.4.2 编写Writer

假设有一个 Writer 类,他有 3 个字段,分别是 age、name 和 bookName,后 2 个是必须序列化的字段。就可以这样来用 @JsonField 注解。

/*** @package: com.yunyang.javabetter.oop.annotation* @description: Writer类* @author: Yunyang* @date: 2024/10/16  14:26* @version:1.0**/
public class Writer {private int age;@JsonField("writerName")private String name;@JsonFieldprivate String bookName;public Writer(int age, String name, String bookName) {this.age = age;this.name = name;this.bookName = bookName;}// getter / setter@Overridepublic String toString() {return "Writer{" +"age=" + age +", name='" + name + '\'' +", bookName='" + bookName + '\'' +'}';}
}

分析:

  • name 上的 @JsonField 注解提供了显式的字符串值。
  • bookName 上的 @JsonField 注解使用了缺省项。

1.4.3 编写序列化类 JsonSerializer

/*** @package: com.yunyang.javabetter.oop.annotation* @description: 序列化类 JsonSerializer* @author: Yunyang* @date: 2024/10/16  14:27* @version:1.0**/
public class JsonSerializer {/*** serialize() 方法是用来序列化对象的,它接收一个 Object 类型的参数* @param object* @return* @throws IllegalAccessException*/public static String serialize(Object object) throws IllegalAccessException {Class<?> objectClass = object.getClass();Map<String, String> jsonElements = new HashMap<>();// objectClass.getDeclaredFields()// 通过反射的方式获取对象声明的所有字段,然后进行 for 循环遍历for (Field field : objectClass.getDeclaredFields()) {// 通过 field.setAccessible(true) 将反射对象的可访问性设置为 true,供序列化使用field.setAccessible(true);// 通过 isAnnotationPresent() 判断字段是否装饰了 JsonField 注解if(field.isAnnotationPresent(JsonField.class)){// 如果是的话,调用 getSerializedKey() 方法,以及获取该对象上由此字段表示的值,并放入 jsonElements 中jsonElements.put(getSerializedKey(field), (String) field.get(object));}}return toJsonString(jsonElements);}/*** getSerializedKey() 方法用来获取字段上注解的值,如果注解的值是空的,则返回字段名* @param field* @return*/private static String getSerializedKey(Field field) {String annotationValue = field.getAnnotation(JsonField.class).value();if(annotationValue.isEmpty()){return field.getName();} else {return annotationValue;}}/*** toJsonString() 方法借助 Stream 流的方式返回格式化后的 JSON 字符串* @param jsonMap* @return*/private static String toJsonString(Map<String, String> jsonMap) {String elementsString = jsonMap.entrySet().stream().map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"").collect(Collectors.joining(","));return "{" + elementsString + "}";}}

1.4.4 测试类 JsonFieldTest

/*** @package: com.yunyang.javabetter.oop.annotation* @description: 测试类 JsonFieldTest* @author: Yunyang* @date: 2024/10/16  14:42* @version:1.0**/
public class JsonFieldTest {public static void main(String[] args) throws IllegalAccessException {Writer writer = new Writer(18, "zhangsan", "Java进阶之路");System.out.println(JsonSerializer.serialize(writer));}
}

运行结果:

{"bookName":"Java进阶之路","writerName":"zhangsan"}

分析:

  • Writer 类的 age 字段没有装饰 @JsonField 注解,所以没有序列化
  • Writer 类的 name 字段装饰了 @JsonField 注解,并且显示指定了字符串“writerName”,所以序列化后变成了 writerName
  • Writer 类的 bookName 字段装饰了 @JsonField 注解,但没有显式指定值,所以序列化后仍然是 bookName

2 Java 枚举

2.1 概念

  • 定义:枚举(enum)是 Java 1.5 时引入的关键字,表示一种特殊类型的类,继承自 java.lang.Enum

2.2 新建枚举 PlayerType

public enum PlayerType {TENNIS,FOOTBALL,BASKETBALL
}

2.2.1 反编译后的字节码

public final class PlayerType extends Enum
{public static PlayerType[] values(){return (PlayerType[])$VALUES.clone();}public static PlayerType valueOf(String name){return (PlayerType)Enum.valueOf(com/cmower/baeldung/enum1/PlayerType, name);}private PlayerType(String s, int i){super(s, i);}public static final PlayerType TENNIS;public static final PlayerType FOOTBALL;public static final PlayerType BASKETBALL;private static final PlayerType $VALUES[];static {TENNIS = new PlayerType("TENNIS", 0);FOOTBALL = new PlayerType("FOOTBALL", 1);BASKETBALL = new PlayerType("BASKETBALL", 2);$VALUES = (new PlayerType[] {TENNIS, FOOTBALL, BASKETBALL});}
}

2.2.2 Java 编译器对枚举的隐式工作

  • 继承:枚举类隐式继承自 java.lang.Enum
  • 构造方法:编译器会为枚举生成一个私有的构造方法。
  • 静态变量和数组:编译器会为枚举生成静态变量和数组来存储枚举常量。
  • 静态块:编译器会使用静态块来初始化静态变量和数组。
  • 静态方法:编译器会提供 values()valueOf(String name) 等静态方法。

2.3 枚举的作用域

  • 内部类:枚举可以定义在一个类的内部,作用域限定于外部类中。
public class Player {private PlayerType type;public enum PlayerType {TENNIS,FOOTBALL,BASKETBALL}public boolean isBasketballPlayer() {return getType() == PlayerType.BASKETBALL;}public PlayerType getType() {return type;}public void setType(PlayerType type) {this.type = type;}
}

分析:

PlayerType 就相当于 Player 的内部类

2.4 枚举的比较

  • 使用 == 运算符:由于枚举是 final 的,可以使用 == 运算符比较两个枚举是否相等。
  • 不使用 equals() 方法
    • == 运算符在比较时不会抛出 NullPointerException
    • == 运算符在编译时会检查类型匹配,而 equals() 方法不会。

2.5 枚举与 switch 语句

  • 用法:枚举可以用于 switch 语句,与基本数据类型的用法一致。
  • 示例
switch (playerType) {case TENNIS:return "网球运动员费德勒";case FOOTBALL:return "足球运动员C罗";case BASKETBALL:return "篮球运动员詹姆斯";case UNKNOWN:throw new IllegalArgumentException("未知");default:throw new IllegalArgumentException("运动员类型: " + playerType);}

2.6 枚举与带参数的构造方法

如果枚举中需要包含更多信息的话,可以为其添加一些字段,比如下面示例中的 name,此时需要为枚举添加一个带参的构造方法,这样就可以在定义枚举时添加对应的名称了。

  • 示例
public enum PlayerType {TENNIS("Tennis"),FOOTBALL("Football"),BASKETBALL("Basketball");private String name;PlayerType(String name) {this.name = name;}public String getName() {return name;}
}

2.7 EnumSet

  • 定义EnumSet 是专门针对枚举类型的 Set 接口的实现类,非常高效。
  • 创建:不能使用 new 关键字创建 EnumSet,可以使用静态工厂方法。
  • 示例
/*** @package: com.yunyang.javabetter.oop.enumdemo* @description:  EnumSet* @author: Yunyang* @date: 2024/10/16  15:28* @version:1.0**/
public class EnumSetTest {public enum PlayerType{TENNIS,FOOTBALL,BASKETBALL}public static void main(String[] args) {EnumSet<PlayerType> enumSetNone = EnumSet.noneOf(PlayerType.class);System.out.println(enumSetNone);EnumSet<PlayerType> enumSetAll = EnumSet.allOf(PlayerType.class);System.out.println(enumSetAll);}
}

运行结果:

[]
[TENNIS, FOOTBALL, BASKETBALL]

分析:

使用 noneOf() 静态工厂方法创建了一个空的 PlayerType 类型的 EnumSet;使用 allOf() 静态工厂方法创建了一个包含所有 PlayerType 类型的 EnumSet。

2.8 EnumMap

  • 定义EnumMap 是专门针对枚举类型的 Map 接口的实现类,效率比 HashMap 高。
  • 创建:可以使用 new 关键字创建 EnumMap
  • 示例
/*** @package: com.yunyang.javabetter.oop.enumdemo* @description: EnumMap* @author: Yunyang* @date: 2024/10/16  15:33* @version:1.0**/
public class EnumMapTest {public enum PlayerType {TENNIS("网球"),FOOTBALL("足球"),BASKETBALL("篮球");private String name;PlayerType(String name) {this.name = name;}}public static void main(String[] args) {EnumMap<PlayerType, String> enumMap = new EnumMap<>(PlayerType.class);enumMap.put(PlayerType.BASKETBALL,"篮球运动员");enumMap.put(PlayerType.FOOTBALL,"足球运动员");enumMap.put(PlayerType.TENNIS,"网球运动员");System.out.println(enumMap);System.out.println(enumMap.get(PlayerType.BASKETBALL));System.out.println(enumMap.get(PlayerType.FOOTBALL));System.out.println(enumMap.get(PlayerType.TENNIS));System.out.println(enumMap.containsKey(PlayerType.TENNIS));}
}

运行结果:

{TENNIS=网球运动员, FOOTBALL=足球运动员, BASKETBALL=篮球运动员}
篮球运动员
足球运动员
网球运动员
true

2.9 枚举实现单例

2.9.1 概念

  • 单例模式:保证一个类仅有一个对象,并提供全局访问点。
  • Java 标准库有一些类就是单例,比如说 Runtime 这个类

2.9.2 volatile、synchronized关键字实现单例

/*** @package: com.yunyang.javabetter.oop.enumdemo* @description: volatile、synchronized关键字实现单例* @author: Yunyang* @date: 2024/10/16  15:38* @version:1.0**/
public class Singleton {private volatile static Singleton singleton;private Singleton() {}public static Singleton getSingleton() {if(singleton == null){synchronized (Singleton.class){if(singleton == null){singleton = new Singleton();}}}return singleton;}
}

2.9.3 枚举实现单例

/*** @package: com.yunyang.javabetter.oop.enumdemo* @description: 枚举实现单例* @author: Yunyang* @date: 2024/10/16  15:40* @version:1.0**/
public enum EasySingleton {INSTANCE;
}
  • 优点:枚举默认实现了 Serializable 接口,Java 虚拟机保证该类为单例。

3 思维导图

在这里插入图片描述
在这里插入图片描述

4 参考链接

  1. Java注解,请别小看我
  2. Java枚举:小小enum,优雅而干净

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com