1. 注解
注解的本质实际上是一个类。所有的注解都继承于Annotation这个基类。它是一个标注,可以标注在字段、方法、类、注解上,以此来为被标注的元素拓展额外的辅助信息。
- 元注解
Java中定义了4个元注解,用来负责修饰其他的注解。
1. @Target:用于描述被它所修饰的注解的使用范围
ElementType.TYPE:可以修饰类、接口、枚举、注解
ElementType.CONSTRUCTOR:可以修饰构造函数
ElementType.FIELD:可以修饰字段
ElementType.LOCAL_VARIABLE:可以修饰局部变量
ElementType.METHOD:可以修饰方法
ElementType.PACKAGE:可以修饰包
ElementType.PARAMETER:可以修饰方法参数
ElementType.ANNOTATION_TYPE:可以修饰注解
2. @Retention:用于描述被他所修饰的注解的生命周期
SOURCE:被修饰的注解只在源代码中存在
CLASS:被它修饰的注解在class字节码文件中存在(在运行前存在)
RUNTIME:被它修饰的注解直到运行时也依旧存在
3. @Document:被他所修饰的注解会被包含在Javadoc中
- 被它修饰的注解会存在于它所对应的Javadoc文档中
4. @Inherited:被它所修饰了的类的子类,可以继承父类的注解
- 使用@Inherited
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("B");
MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
if(annotation!=null)
System.out.println(annotation.value());
else
System.out.println("None");
//运行结果:XiaoJie
}
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface MyAnnotation{
String value();
}
@MyAnnotation("XiaoJie")
class A{}
class B extends A{}
- 不使用@Inherited
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("B");
MyAnnotation annotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
if(annotation!=null)
System.out.println(annotation.value());
else
System.out.println("None");
//运行结果:None
}
}
@Retention(RetentionPolicy.RUNTIME)
//@Inherited
@interface MyAnnotation{
String value();
}
@MyAnnotation("XiaoJie")
class A{}
class B extends A{}
2. 反射
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意方法和属性;
这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Class类:
Java的反射机制和一个叫Class类的玩意儿有着紧密的联系。在Java中的每一个类,当它被加载的时候,都会产生一个与它唯一对应的Class类实例。不管这个类的实例有多少,它的Class类实例,或者说这些实例对应的Class类实例有且只有一个。
我们可以通过类、类名、类的实例来获取它们所对应的Class类的实例。
当我们得到Class类的实例时,我们就可以通过这个实例来访问它所对应的这个类的任意方法、字段以及注解。
Class类加载时机:
当程序主动引用某个类的时候,如果该类还未被加载到内存中,则系统会经过加载、链接、初始化三个阶段来对类进行加载。而它所对应的Class类会在加载阶段被进行创建。
什么时候会被视为主动引用:
- new一个类的时候
- 调用类的静态成员和静态方法的时候
- 通过反射来对类进行调用的时候
- 子类被加载的时候
参考代码:
public class Program {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
//===========获取Class对象的几种方式===========
//通过Class对象创建对应类的实例
Student student = Student.class.getDeclaredConstructor().newInstance();
student.getScore().put("English",100);
student.getScore().put("Math",100);
student.getScore().put("Chinese",100);
Class cStudent1 = Class.forName("Student");
Class cStudent2 = Student.class;
Class cStudent3 = student.getClass();
//===========通过Class对象获取字段的信息===========
System.out.println("获取字段的信息:");
System.out.println(cStudent1.getDeclaredField("Name"));
System.out.println(cStudent1.getDeclaredField("ID"));
//===========通过Class对象获取泛型的信息===========
System.out.println("获取泛型的信息:");
Field score = cStudent1.getDeclaredField("Score");
Type genericType = score.getGenericType();
if(genericType instanceof ParameterizedType){
Type[] actualTypeArguments =
((ParameterizedType) genericType).getActualTypeArguments();
for(var item : actualTypeArguments) System.out.println(item);
}
//===========通过Class对象获取注解的信息===========
System.out.println("获取注解的信息:");
MyAnnotation annotation =
(MyAnnotation) cStudent1.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value());
//===========通过Class对象获取方法的信息===========
System.out.println("获取方法的信息:");
Method showInformation = cStudent1.getMethod("ShowInformation");
showInformation.invoke(student);
/* 运行结果如下:
* -----------------------------------------------------------------
* 获取字段的信息:
* private java.lang.String Student.Name
* private java.lang.String Student.ID
* 获取泛型的信息:
* class java.lang.String
* class java.lang.Integer
* 获取注解的信息:
* XiaoJieInformation
* 获取方法的信息:
* ========ShowInformation方法开始执行========
* XiaoJie
* 123
* English:100
* Chinese:100
* Math:100
* ========ShowInformation方法执行结束========
*
* Process finished with exit code 0
*/
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String value();
}
@MyAnnotation("XiaoJieInformation")
class Student{
private String Name="XiaoJie";
private String ID="123";
private Map<String,Integer> Score=new HashMap<String, Integer>();
public Map<String, Integer> getScore() {
return Score;
}
public void ShowInformation(){
System.out.println("========ShowInformation方法开始执行========");
System.out.println(Name);
System.out.println(ID);
for(var item : Score.entrySet())
System.out.println(item.getKey()+":"+item.getValue());
System.out.println("========ShowInformation方法执行结束========");
}
}