目录
枚举、注解与反射学习笔记
一、枚举
- 格式
权限修饰符 enum 枚举名称 {
实例1,实例2,实例3,实例4;
} - 简介
JDK1.5引入了新的类型——枚举。在JDK1.5 之前,我们定义常量都是: public static fianl… 。很难管理。
枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。用于定义有限数量的一组同类常量,例如:
错误级别:
低、中、高、急
一年的四季:
春、夏、秋、冬
商品的类型:
美妆、手机、电脑、男装、女装…
在枚举类型中定义的常量是该枚举类型的实例。
public class Level2 {
//1.5版本之前的枚举
public static final Level2 LOW = new Level2(1);
public static final Level2 MIDIUM = new Level2(3);
public static final Level2 HIGH = new Level2(5);
private int value;
private Level2(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public enum Level {
//1.5版本后格式1
LOW(1),MIDIUM(3),HIGH(5) ;
private Level(int value) {
this.value = value;
}
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
//1.5版本后格式2
public enum Level1 {
LOW,MIDIUM,HIGH;
}
最后一种为最常用的方式,枚举值默认为从0开始的有序数值。以 Level1枚举类型举例,它的枚举常量依次为 LOW:0,MIDIUM:1,HIGH:2
-
Enum抽象类常见方法
-
枚举类使用注意事项
- 一旦定义了枚举,最好不要妄图修改里面的值,除非修改是必要的。
- 枚举类默认继承的是java.lang.Enum类而不是Object类
- 枚举类不能有子类,因为其枚举类默认被final修饰 只能有private构造方法 switch中使用枚举时,直接使用常量名,不用携带类名
- 不能定义name属性,因为自带name属性
- 不要为枚举类中的属性提供set方法,不符合枚举最初设计初衷。
二、注解
-
简介
- Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
- Java 语言中的类、方法、变量、参数和包等都可以被标注。和注释不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。当然它也支持自定义 Java 标注。
- 主要用于:
- 编译格式检查
- 反射中解析
- 生成帮助文档
- 跟踪代码依赖 等
-
内置注解
- @Override : 重写
- 定义在java.lang.Override
- @Deprecated:废弃
- 定义在java.lang.Deprecated
- @SafeVarargs
- Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
- @FunctionalInterface: 函数式接口 *
- Java 8 开始支持,标识一个匿名函数或函数式接口。
- @Repeatable:标识某注解可以在同一个声明上使用多次
- Java 8 开始支持,标识某注解可以在同一个声明上使用多次
- SuppressWarnings:抑制编译时的警告信息。
- 定义在java.lang.SuppressWarnings
- 三种使用方式
- @Override : 重写
1. @SuppressWarnings("unchecked") [^ 抑制单类型的警告]
2. @SuppressWarnings("unchecked","rawtypes") [^ 抑制多类型的警告]
3. @SuppressWarnings("all") [^ 抑制所有类型的警告]
-
元注解 :作用在其他注解的注解
- @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
- @Documented - 标记这些注解是否包含在用户文档中 javadoc。
- @Target - 标记这个注解应该是哪种 Java 成员。
- @Inherited - 标记这个注解是自动继承的
-
自定义注解:
- 格式:@interface 自定义注解名{}
- 注意事项
- 定义的注解,自动继承了java.lang,annotation.Annotation接口
- 注解中的每一个方法,实际是声明的注解配置参数,方法的名称就是 配置参数的名称
方法的返回值类型,就是配置参数的类型。只能是:基本类型/Class/String/enum - 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value
- 注解元素必须要有值,我们定义注解元素时,经常使用空字符串、0作为默认值。
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
参数类型 参数名() default 默认值;
}
三、反射
JAVA反射机制是在运行状态中,获取任意一个类的结构 , 创建对象 , 得到方法,执行方法 , 属性 ;这种在运行状态动态获取信息以及动态调用对象方法的功能被称为java语言的反射机制。
1.所有类型的Class对象
在Java中,每一个字节码文件,被加载到内存后,都存在一个对应的Class类型的对象。
2.得到Class的三种方式
- 如果在编写代码时, 指导类的名称, 且类已经存在, 可以通过包名.类名.class 得到一个类的 类对象。
- 如果拥有类的对象, 可以通过Class 对象.getClass() 得到一个类的 类对象。
- 如果在编写代码时, 知道类的名称 , 可以通过Class.forName(包名+类名): 得到一个类的 类对象。
上述的三种方式, 在调用时, 如果类在内存中不存在, 则会加载到内存 ! 如果类已经在内存中存在, 不会重复加载, 而是重复利用 !
特殊的类对象
- 基本数据类型的类对象:
基本数据类型.class
包装类.type - 基本数据类型包装类对象:
包装类.class
3.获取Constructor以及使用
Class<Person> pclass = (Class<Person>) Class.forName("com.java.demo.Person");
//获取无参的构造方法
Constructor<Person> c = pclass.getConstructor();
//获取有参的构造方法
Constructor<Person> c1 = pclass.getConstructor(String.class,int.class);
//获取私有权限的构造方法,getDeclaredConstructor获取所有权限的构造方法
Constructor<Person> c2 = pclass.getDeclaredConstructor(String.class);
//使用无参构造方法创建对象
Person p = c.newInstance();
//使用有参构造方法创建对象,需要传参。
Person p1 = c1.newInstance("name",18);
//使用私有权限的构造方法创建对象,需要先忽略权限检查。
c2.setAccessible(true);
Person p2 = c2.newInstance("name");
4.获取Method以及使用
- getMethod(String methodName , class… clss)
根据参数列表的类型和方法名, 得到一个方法(public修饰的) - getMethods();
得到一个类的所有方法 (public修饰的) - getDeclaredMethod(String methodName , class… clss)
根据参数列表的类型和方法名, 得到一个方法(除继承以外所有的:包含私有, 共有, 保护, 默认) - getDeclaredMethods();
得到一个类的所有方法 (除继承以外所有的:包含私有, 共有, 保护, 默认) - invoke(Object o,Object… para) :
调用方法 ,
参数1. 要调用方法的对象
参数2. 要传递的参数列表 - getName()
获取方法的方法名称 - setAccessible(boolean flag)
如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的方法)
5.获取Field以及使用
- getField(属性名);getDeclaredField(属性名)
- set(Object o , Object value);
参数1. 要设置属性值的 对象
参数2. 要设置的值,设置指定对象的属性的值 - getName():获取属性的名称
- setAccessible(boolean flag)
如果flag为true 则表示忽略访问权限检查 !(可以访问任何权限的属性)
6.获取获取注解信息
.1、获取类/属性/方法的全部注解对象
Annotation[] annotations01 = Class/Field/Method.getAnnotations();
for (Annotation annotation : annotations01) {
System.out.println(annotation);
}
2、根据类型获取类/属性/方法的注解对象
注解类型 对象名 = (注解类型) c.getAnnotation(注解类型.class);