Java 枚举与泛型

Java 枚举

之前写过的文档:https://blog.csdn.net/Roobert_Chao/article/details/78637972

枚举对象的常用方法

枚举对象的常用方法

Java 枚举的本质理解

Java 枚举的本质原理是通过普通类来实现的,经过编译器的加工处理(编译后生成的类是final class 类,且继承了 Enum 类),枚举值加工成为类的静态常量属性,其属性在类加载的静态代码块中被初始化实例赋值。
在这里插入图片描述
查看字节码(.class)文件

  1. 命令行的方式:javap -c 文件所在目录。
    在这里插入图片描述
  2. 使用插件工具 【IDEA】,添加插件 jclasslib bytecode viewer。
  3. 下载本地工具【JBE - Java Bytecode Editor】: http://set.ee/jbe/

上述枚举类型的编译后的代码如下:

public final class cn.chao.override.equals.ColorEnum extends java.lang.Enum<cn.chao.override.equals.ColorEnum> {    // 类变成了 final class 
  // 三种静态常量
  public static final cn.chao.override.equals.ColorEnum RED;
  public static final cn.chao.override.equals.ColorEnum BLUE;
  public static final cn.chao.override.equals.ColorEnum GREEN;
  // 自定义字符串类型的属性
  public java.lang.String color;

  static {};
    Code:
       0: new           #1                  // class cn/chao/override/equals/ColorEnum
       3: dup
       4: ldc           #16                 // String RED
       6: iconst_0
       7: ldc           #17                 // String red
       9: invokespecial #19                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      12: putstatic     #23                 // Field RED:Lcn/chao/override/equals/ColorEnum;
      15: new           #1                  // class cn/chao/override/equals/ColorEnum
      18: dup
      19: ldc           #25                 // String BLUE
      21: iconst_1
      22: ldc           #26                 // String blue
      24: invokespecial #19                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      27: putstatic     #28                 // Field BLUE:Lcn/chao/override/equals/ColorEnum;
      30: new           #1                  // class cn/chao/override/equals/ColorEnum
      33: dup
      34: ldc           #30                 // String GREEN
      36: iconst_2
      37: ldc           #31                 // String green
      39: invokespecial #19                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      42: putstatic     #33                 // Field GREEN:Lcn/chao/override/equals/ColorEnum;
      45: iconst_3
      46: anewarray     #1                  // class cn/chao/override/equals/ColorEnum
      49: dup
      50: iconst_0
      51: getstatic     #23                 // Field RED:Lcn/chao/override/equals/ColorEnum;
      54: aastore
      55: dup
      56: iconst_1
      57: getstatic     #28                 // Field BLUE:Lcn/chao/override/equals/ColorEnum;
      60: aastore
      61: dup
      62: iconst_2
      63: getstatic     #33                 // Field GREEN:Lcn/chao/override/equals/ColorEnum;
      66: aastore
      67: putstatic     #35                 // Field ENUM$VALUES:[Lcn/chao/override/equals/ColorEnum;
      70: return

  public static cn.chao.override.equals.ColorEnum[] values();
    Code:
       0: getstatic     #35                 // Field ENUM$VALUES:[Lcn/chao/override/equals/ColorEnum;
       3: dup
       4: astore_0
       5: iconst_0
       6: aload_0
       7: arraylength
       8: dup
       9: istore_1
      10: anewarray     #1                  // class cn/chao/override/equals/ColorEnum
      13: dup
      14: astore_2
      15: iconst_0
      16: iload_1
      17: invokestatic  #47                 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
      20: aload_2
      21: areturn

  public static cn.chao.override.equals.ColorEnum valueOf(java.lang.String);
    Code:
       0: ldc           #1                  // class cn/chao/override/equals/ColorEnum
       2: aload_0
       3: invokestatic  #55                 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #1                  // class cn/chao/override/equals/ColorEnum
       9: areturn
}

枚举类与常量类

在使用枚举类的时候,发现枚举常量+枚举值,和常量类中常量赋值是一样的。那么为什么会出现枚举类呢 ???

  1. 枚举相对于常量类来说更加的简单,可以不定义枚举值。而常量类中的每个常量必须要手动添加值。
  2. 枚举类自动具备内置方法(如 values 方法可以获得所有值的集合类遍历,ordinal 方法可以获得排序值,compareTo 方法可以基于 ordinal 比较)。常量类不具备这些方法。
  3. 枚举类编译后生成了 final class 类,且继承了 Enum 类(Java 单继承机制),所以枚举类不能够继承,但是定义的枚举类可以通过 implement 实现其他接口。

Java 枚举与线程安全

1. Java 类加载和初始化是 Java 虚拟机(JVM )保证线程安全。
2. static 的常量属性和代码块都是在类加载时初始化完成的。
Java 枚举类编译后的代码,实质上是一个 final 类,枚举常量初始化都是在 static 代码块中进行的,自然就 JVM 保证线程安全。

Java 泛型(参数化类型)

之前写过的文档:https://blog.csdn.net/Roobert_Chao/article/details/78634340
1. 参数化类型,泛型类、泛型接口、泛型方法
2. 提高了代码的重用率,避免在运行时出现 ClassCastException。

Java 泛型是通过 擦除来实现的

  1. Java 泛型是通过擦除来实现的,所以编译后的任何具体泛型类型都被擦除了。
    (替换为非泛型上边界,没有上边界,则上边界就是 Object 类型。)

通过反射增加字符串

在这里插入图片描述
观察如下的代码:输出结果为
输出结果

public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
	ArrayList<Integer> list = new ArrayList<Integer>();
	list.add(1);
	list.getClass().getMethod("add", Object.class).invoke(list, "abc");
	for (int i = 0; i < list.size(); i++) {
		System.out.println(list.get(i));
	}
}

由于在程序中定义的 ArrayList 泛型类型实例化为 Integer 的对象,如果直接调用 add 方法则只能存储整型数据,不过当我们利用反射调用 add 方法时,就可以存储字符串。因为 Integer 泛型实例在编译之后被擦除了,只保留了原始类型 Object 。

  1. 擦除前的类型检查是针对引用的,用这个引用调用泛型方法就会对这个引用调用的方法进行类型检测而无关真正引用的对象。泛型中参数化类型不支持继承关系。且不能是基本类型。
    在这里插入图片描述
  2. 泛型无法进行具体泛型参数类型的运行时检查。而且不能抛出,也不能捕获泛型类对象。
arrayList instanceof ArrayList<String> 是非法的。
arrayList instanceof ArrayList<?> 仅这种方式。
  1. Java 的泛型数组不能采用具体的泛型类型进行初始化。只能通过通配符的形式。
建议:
List<?>[] list = new ListArray<?>[10];

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值