[Java]Java 枚举注解异常和常用类

Posted Spring-_-Bear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Java]Java 枚举注解异常和常用类相关的知识,希望对你有一定的参考价值。

一、枚举

1. 自定义枚举类

  1. 枚举是一组常量的集合,属于一种特殊的类,里面只包含一组有限的特定的对象
  2. 自定义枚举类:构造器私有化、不提供 setXxx() 方法、对枚举属性使用 statc + final 修饰以实现底层优化
class Season 
   private final String name;
   private final String description;

   public static final Season SPRING = new Season("春天", "温暖");
   public static final Season SUMMER = new Season("夏天", "炎热");
   public static final Season AUTUMN = new Season("秋天", "凉爽");
   public static final Season WINTER = new Season("冬天", "寒冷");

   private Season(String name, String description) 
       this.name = name;
       this.description = description;
   

2. enum 枚举类

enum 作为一个特殊的类,依然可以实现接口,但已经继承了 Enum 类,所以不能继承其它类

enum Season 
   // 必须位于行首且以逗号间隔,分号结尾,如果使用的是无参构造器创建枚举对象,则括号可以省略
   SPRING("春天", "温暖"),
   SUMMER("夏天", "炎热"),
   AUTUMN("秋天", "凉爽"),
   WINTER("冬天", "寒冷");

   private final String name;
   private final String description;

   private Season(String name, String description) 
       this.name = name;
       this.description = description;
   

使用 Javap 反编译 enum 类

使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类,而且是一个 final

3. Enum 类成员方法

方法名功能
toString()返回当前对象名,子类可重写
name()返回当前对象常量名,子类不可重写
ordinal()返回当前对象的位置号,默认从 0 开始
values()返回当前枚举类中的所有常量
valueOf()将字符串转换枚举对象
compareTo()比较两个枚举常量的位置号

二、注解

1. Override 注解

  1. 注解(Annotation)也称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息
  2. 与注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息
  3. 在 Java SE 中,注解的使用目的比较简单,例如标记过时的方法、忽略警告等;在 Java EE 中注解占据重要角色,例如用来配置应用程序的任何切面、代替 Java EE 旧版中所遗留的冗杂代码和 XML 配置等
  4. 重写方法时如果添加了 @Override 注解,则编译器就会检查是否真的重写了父类的方法,如果未重写则编译通不过
  5. @interface 并不指此类是接口,而是说明此类是注解类,在 JDK 1.5 之后加入
  6. @Target(ElementType.METHOD) 是修饰注解的注解,称为元注解,用于说明此注解作用的范围
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override 

2. Deprecated注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value=CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE)
public @interface Deprecated 

3. SupressWarnings注解

@Target(TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE)
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings 
   String[] value();

4. 四种元注解

// 指定注解的作用域:SOURCE、CLASS、RUNTIME
@Retention	
// 指定注解使用的使用位置	      
@Target	
// 指定注解在 javadoc 中体现,使用 @Documented 元注解的注解 @Retention 作用域必须为 RUNTIME		        
@Documented	
// 指定子类可以继承父类的注解	
@Inherited		       

三、异常

1. 异常分类及体系图

  1. Error(错误):Java 虚拟机无法解决的严重问题,如 JVM 系统内部错误、资源耗尽等严重情况
  2. Exception(异常):其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。分为编译时异常和运行时异常
  3. 若程序处理了异常,程序继续执行。若有可能抛出异常而未处理,则由 JVM 打印异常信息后退出程序
  4. 如果出现异常,则 try 块中发生异常语句后的语句不再执行

2. try-catch-finally-return

public int method() 
   int i = 1;
   try 
	       i++;
	       String[] names = new String[3];
	       if (names[i].equals("lcx")) 
	       
	       return i;
    catch (NullPointerException e) 
       return ++i;
    finally 
       // return result: 4
       return ++i;
   


public int method1() 
   int i = 1;
   try 
       i++;
       String[] names = new String[3];
       if (names[i].equals("lcx")) 
       
       return i;
    catch (NullPointerException e) 
       // return result: 3
       return ++i;
    finally 
       ++i;
   

3. throws

  1. 如果一个方法中的语句执行时可能生成某种异常,但不能确定如何处理这种异常,则可以在方法声明处显式地抛出异常,由调用者自行处理
  2. 编译异常必须处理,对于运行时异常,如不处理则默认 throws
  3. 子类重写父类的方法时,子类抛出异常的类型要么和父类抛出的一致,要么只能是父类抛出异常的子类

4. 自定义异常

  1. 如果继承 Exception,则属于编译异常,必须显式处理或抛出
  2. 如果继承 RuntimeException,则属于运行时异常,可以默认 throws 处理,较为方便

5. throw 和 throws 的区别

意义位置抛出内容说明
throws异常处理的一种方式方法声明处异常类型
throw手动生成异常对象方法体中异常对象

四、常用类

1. 八大 Wrapper 类

除 Boolean 和 Character 外,其余包装类均继承父类 Number

2. 装箱和拆箱

jdk 5 以前是手动装箱和拆箱,自动装箱底层调用的是对应包装类的 valueOf() 方法

// 手动装箱
Integer integer = Integer.valueOf(i);
// 手动拆箱
int ii = integer.intValue();

3. 包装类与 String 间的转换

  1. 包装类转 String
Integer i = 100;
// 方式 1
String str = i + "";
// 方式 2
String str = i.toString();
// 方式 3
String str = String.valueOf(i);
  1. String 转包装类
String str = "123";
// 方式 1
Integer i = Integer.parseInt(str);
// 方式 2 
Integer i = new Integer(str);

4. Integer 的创建机制

自动装箱机制,在 [-128,127] 范围内直接返回,否则 new Integer(i)

public static Integer valueOf(int i) 
   if (i >= IntegerCache.low && i <= IntegerCache.high)
       return IntegerCache.cache[i + (-IntegerCache.low)];
   return new Integer(i);


// 经典例题
Integer i = new Integer(1);
Integer ii = new Integer(1);
// false
System.out.println(i == ii);

Integer j = 1;
Integer jj = 1;
// true
System.out.println(j == jj);

Integer k = 128;
Integer kk = 128;
// false
System.out.println(k == kk);

只要有基本数据类型与包装类型进行比较时,判断的是值是否相等

Integer i = 127;
int ii = 127;
// true
System.out.println(i == ii);

Integer j = 128;
int jj = 128;
// true
System.out.println(j == jj);

5. String 创建机制剖析

  1. 方式 1:先从常量池查找是否有 “lcx” 数据空间,如果有,直接将 s1 指向 “lcx”;没有则新建后指向,s1 最终指向的是常量池的空间地址
String s1 = "lcx";
  1. 方式 2:先在堆中创建空间,维护了 String 的字段 value[] 属性,value 指向常量池的 “lcx” 空间;如果常量池没有 “lcx”,则新建;如果有,则通过 value 指向。s2 最终指向的是堆中的空间地址即 value 的地址
String s2 = new String("lcx");

6. String 经典测试题

// Test 1
String a = "lcx";
String b = new String("lcx");
// true:a 指向常量池中 "lcx" 的地址,b.intern() 返回常量池中 "lcx" 的地址
System.out.println(a == b.intern());
// false:b 返回 String 类的字段 value[] 的地址
System.out.println(b == b.intern());

// Test 2
String s1 = new String("abc");
String s2 = new String("abc");
// false:s1,s2 -> 不同的 value[]
System.out.println(s1 == s2);
// true:引用到常量池的同一个地址
System.out.println(s1.intern()==s2.intern());

7. String 对象特性

常量相加看池,变量相加看堆

// Test 1
// 只创建了一个字符串常量 "hello123"
String a = "hello" + "123";
// b -> 常量池的 "hello"
String b = "hello";
// c -> 常量池的 "123"
String c = "123";
// d -> 堆中 value,value 指向常量池中的 "hello123"
// 调用 StringBuilder 的 append 方法连接两次,然后再 new String()
String d = b + c;

// Test 2
// str 指定堆中的 value,value 指向常量池中的 "lcx"
String str = new String("lcx");
// 字符数组对象存放于堆中
final char[] ch = 'j','a','v','a';
public void change(String str, char[] ch) 
   str = "java";
   ch[0] = 'h';

public static void main(String[] args) 
   Test test = new Test();
   test.change(test.str, test.ch);
   // output result: lcx and hava
   System.out.print(test.str + " and ");
   System.out.println(test.ch);

8. String 常用方法

  1. 调用字符串的 replace() 方法若忽略返回值,则原字符串并未发生变化
  2. 调用 compartTo() 方法时,若其中一个字符串是另一个字符串的子串,则返回长度之差

9. StringBuffer

  1. StringBuffer 也是一个 final 类,但其字段 value[] 不是 final 类型的。StringBuffer 线程安全

  2. String 保存的是字符串常量,value 引用到常量池;而 StringBuffer 保存的是字符串变量,数据存放在堆中

  3. StringBuffer value[] 无参构造器默认初始化容量为 16;若构造器传入的是字符串,则初始化容量为字符串长度加上 16

  4. StringBuilder 线程不安全,与 StringBuffer 使用方法基本一致

10. StringBuffer 的 append() 方法

String str = null;

StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(str);
// output:null
System.out.println(stringBuffer);

// NullPointerException
StringBuffer stringBuffer1 = new StringBuffer(str);
System.out.println(stringBuffer1);

11. Arrays

  1. 使用 Arrays.binarySearch() 方法对有序数组进行二分查找时,若不存在该元素,则返回该元素应在数组中位置下标的负值
  2. Arrays.asList() 可以将数组转换为 List 类型的集合,运行类型为 Arrays$ArrayList,即 Arrays 类中的静态内部类 ArrayList

12. 模拟 Arrays.sort(int[], Comparator<T>) 排序

import java.util.Arrays;
import java.util.Comparator;

/**
* @author Spring-_-Bear
* @version 2021-12-07 20:06
*/
public class Test 
   public static void main(String[] args) 
       Integer[] arrays = new Integer[]1, 31, 523, 452, 13, 64, 23, 75;
       Test test = new Test();
       // 面向接口编程 + 动态绑定(多态)
       test.bubble(arrays, new Comparator<Integer>() 
           @Override
           public int compare(Integer o1, Integer o2) 
               return o1 - o2;
           
       );
       System.out.println(Arrays.toString(arrays));
   

   public void bubble(Integer[] arrays, Comparator<Integer> comparator) 
       int len = arrays.length;
       for (int i = 0; i < len - 1; i++) 
           for (int j = 0; j < len - 1 - i; j++) 
               if (comparator.compare(arrays[j], arrays[j + 1]) > 0) 
                   int temp = arrays[j];
                   arrays[j] = arrays[j + 1];
                   arrays[j + 1] = temp;
               
           
       
   

13. BigDecimal

BigDecimal bigDecimal = new BigDecimal("242131.24321335243234123");
// 为避免结果为无限循环小数,可对结果指定精度以解决 ArithmeticException
BigDecimal res = bigDecimal.divide(new BigDecimal(1.1), BigDecimal.ROUND_CEILING);
System.out.println(res);

14. 第二、三代日期类

  1. Calendar 构造器私有,可通过 getInstance() 方法获取到一个实例

  2. JDK 1.0 中出现的 java.util.Date 类,大多数方法在 jdk 1.1 引入的 Calendar 类中已被弃用,第二代日期类 Calendar 也存在着以下一些问题:

  1. 可变性:像日期和时间这样的类应该是不可变的
  2. 偏移性:年份从 1900 开始,月份从 0 开始
  3. 格式化:不能对 Calendar 进行格式化
  4. 线程不安全,不能处理闰秒(每隔两天,多出 1s)
  1. JDK 8 引入的第三代日期类:LocalDate(日期)、LocalTime(时间)、LocalDateTime(日期时间)
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss");
System.out.println(formatter.format(now));

以上是关于[Java]Java 枚举注解异常和常用类的主要内容,如果未能解决你的问题,请参考以下文章

Java之枚举注解反射

Java基础——枚举与注解

Java_枚举类和注解

Java 基础知识点 笔记总结

java之枚举和注解

13 Java枚举和注解