[Java]枚举注解异常和常用类
Posted Spring-_-Bear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Java]枚举注解异常和常用类相关的知识,希望对你有一定的参考价值。
一、枚举
1. 自定义枚举类
- 枚举是一组常量的集合,属于一种特殊的类,里面只包含一组有限的特定的对象
- 自定义枚举类:构造器私有化、不提供 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 注解
- 注解(Annotation)也称为元数据(Metadata),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息
- 与注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息
- 在 Java SE 中,注解的使用目的比较简单,例如标记过时的方法、忽略警告等;在 Java EE 中注解占据重要角色,例如用来配置应用程序的任何切面、代替 Java EE 旧版中所遗留的冗杂代码和 XML 配置等
- 重写方法时如果添加了 @Override 注解,则编译器就会检查是否真的重写了父类的方法,如果未重写则编译通不过
- @interface 并不指此类是接口,而是说明此类是注解类,在 JDK 1.5 之后加入
- @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. 四种元注解
- @Retention // 指定注解的作用域:SOURCE、CLASS、RUNTIME
- @Target // 指定注解使用的使用位置
- @Documented // 指定注解在 javadoc 中体现,使用 @Documented 元注解的注解 @Retention 作用域必须为 RUNTIME
- @Inherited // 指定子类可以继承父类的注解
三、异常
1. 异常分类及体系图
- Error(错误):Java 虚拟机无法解决的严重问题,如 JVM 系统内部错误、资源耗尽等严重情况
- Exception(异常):其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。分为编译时异常和运行时异常
- 若程序处理了异常,程序继续执行。若有可能抛出异常而未处理,则由 JVM 打印异常信息后退出程序
- 如果出现异常,则 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
- 如果一个方法中的语句执行时可能生成某种异常,但不能确定如何处理这种异常,则可以在方法声明处显式地抛出异常,由调用者自行处理
- 编译异常必须处理,对于运行时异常,如不处理则默认 throws
- 子类重写父类的方法时,子类抛出异常的类型要么和父类抛出的一致,要么只能是父类抛出异常的子类
4. 自定义异常
- 如果继承 Exception,则属于编译异常,必须显式处理或抛出
- 如果继承 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 间的转换
- 包装类转 String
Integer i = 100;
// 方式 1
String str = i + "";
// 方式 2
String str = i.toString();
// 方式 3
String str = String.valueOf(i);
- 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:先从常量池查找是否有 “lcx” 数据空间,如果有,直接将 s1 指向 “lcx”;没有则新建后指向,s1 最终指向的是常量池的空间地址
String s1 = "lcx";
- 方式 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 常用方法
- 调用字符串的 replace() 方法若忽略返回值,则原字符串并未发生变化
- 调用 compartTo() 方法时,若其中一个字符串是另一个字符串的子串,则返回长度之差
9. StringBuffer
StringBuffer 也是一个 final 类,但其字段 value[] 不是 final 类型的。StringBuffer 线程安全
String 保存的是字符串常量,value 引用到常量池;而 StringBuffer 保存的是字符串变量,数据存放在堆中
StringBuffer value[] 无参构造器默认初始化容量为 16;若构造器传入的是字符串,则初始化容量为字符串长度加上 16
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
- 使用 Arrays.binarySearch() 方法对有序数组进行二分查找时,若不存在该元素,则返回该元素应在数组中位置下标的负值
- 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. 第二、三代日期类
-
Calendar 构造器私有,可通过 getInstance() 方法获取到一个实例
-
JDK 1.0 中出现的 java.util.Date 类,大多数方法在 jdk 1.1 引入的 Calendar 类中已被弃用,第二代日期类 Calendar 也存在着以下一些问题:
- 可变性:像日期和时间这样的类应该是不可变的
- 偏移性:年份从 1900 开始,月份从 0 开始
- 格式化:不能对 Calendar 进行格式化
- 线程不安全,不能处理闰秒(每隔两天,多出 1s)
-
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]枚举注解异常和常用类的主要内容,如果未能解决你的问题,请参考以下文章