反射和注解的知识

 2023-09-11 阅读 17 评论 0

摘要:反射 反射的理论 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。 类的加载过程 类加

反射

反射的理论

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

类的加载过程

类加载的生命周期包括以下几个部分:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading),其中验证、准备、解析三个部分统称链接
在这里插入图片描述
在这里插入图片描述

类加载器

类与类加载器 对于任何一个类,都需要由加载它的类加载器和这个类来确定其在JVM中的唯一性。也就是说,两个类来源于同一个Class文件,并且被同一个类加载器加载,这两个类才相等。

反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

获取Class类的对象

反射会产生主动引用

//主动引用(调用构造函数)
Student student=new Student();
//也会产生主动引用(调用构造函数)
Class c2=Class.forName("com.kuang.Student");
在这里插入代码片
public static void main(String[] args) throws ClassNotFoundException {//方式一:通过对象获得MyYield2 myYield2=new MyYield2();Class c1=myYield2.getClass();//方式二:通过forName函数获得Class c2=Class.forName("com.kuang.MyYield2");//方式三:通过类名获得Class c3= MyYield2.class;//方式四:基本内置类的包装来有一个Type属性Class c4=Integer.TYPE;//获得父类类型Class c5=myYield2.getClass().getSuperclass();System.out.println(c1);System.out.println(c2);System.out.println(c3);System.out.println(c4);System.out.println(c5);System.out.println(c1.hashCode());System.out.println(c2.hashCode());System.out.println(c3.hashCode());System.out.println(c4.hashCode());System.out.println(c5.hashCode());
}

java反射和注解原理,在这里插入图片描述

反射获取的各种方法和属性

class Student {private String name;private Integer age;private Date Birthday;public Student(){}private Student(String name){this.name=name;}private Student(Integer age){this.age=age;}private Student(Date Birthday){this.Birthday=Birthday;}public Student(String name,Integer age){this.name=name;this.age=age;}public Student(Integer age,String name){this.name=name;this.age=age;}public Student(String name,Date Birthday){this.name=name;this.Birthday=Birthday;}public Student(Date Birthday,String name){this.name=name;this.Birthday=Birthday;}public Student(Integer age,Date Birthday){this.age=age;this.Birthday=Birthday;}public Student(Date Birthday,Integer age){this.age=age;this.Birthday=Birthday;}public Student(String name,Integer age,Date Birthday){this.age=age;this.name=name;this.Birthday=Birthday;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getBirthday() {return Birthday;}public void setSex(Date sex) {this.Birthday = Birthday;}
}

反射

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {//方式一:通过对象获得Student student=new Student();Class c1=student.getClass();//方式二:通过forName函数获得Class c2=Class.forName("com.kuang.Student");//方式三:通过类名获得Class c3= Student.class;//方式四:基本内置类的包装来有一个Type属性Class c4=Integer.TYPE;//获得父类类型Class c5=student.getClass().getSuperclass();System.out.println(c1);System.out.println(c2);System.out.println(c3);System.out.println(c4);System.out.println(c5);System.out.println(c1.hashCode());System.out.println(c2.hashCode());System.out.println(c3.hashCode());System.out.println(c4.hashCode());System.out.println(c5.hashCode());//加载Class对象//会报出不存在该类的异常Class c=Class.forName("com.kuang.Student");//获取所有公用构造方法System.out.println("================获取所有公共的构造方法=================");Constructor[] constructors=c.getConstructors();for (Constructor constructor:constructors) {System.out.println("公共的构造方法:"+constructor);}//获取所有构造方法System.out.println("================获取所有的构造方法=================");Constructor[] declaredconstructors=c.getDeclaredConstructors();for (Constructor constructor:declaredconstructors) {System.out.println("所有构造方法:"+constructor);}//获取公有&无参构造方法System.out.println("================获取公有&无参构造方法=================");//会报出没有该方法的异常Constructor constructor1=c.getConstructor(null);System.out.println("公有&无参构造方法:"+constructor1);//获取公有&有参构造方法System.out.println("================获取公有&有参构造方法=================");//会报出没有该方法的异常Constructor constructor2=c.getConstructor(new Class[]{String.class,Integer.class, Date.class});System.out.println("公有&有参构造方法:"+constructor2);Constructor constructor3=c.getConstructor(new Class[]{String.class,Integer.class});System.out.println("公有&有参构造方法:"+constructor3);//获取私有&有参构造方法System.out.println("================获取私有&有参构造方法=================");//会报出没有该方法的异常Constructor declaredconstructor1=c.getDeclaredConstructor(new Class[]{String.class});System.out.println("私有&有参构造方法:"+declaredconstructor1);}

注解(annotation)

什么注解?

  1. 注解不是程序本身,可以对程序作出解释
  2. 可以被其它程序读取
  3. 有一定的的约束功能

常见内置注解

@Override:用于修饰此方法覆盖了父类的方法;

@Deprecated:用于修饰已经过时的方法;
@SuppressWarnnings:用于通知java编译器禁止特定的编译警告

元注解(meta-annotation)

除了直接使用JDK 定义好的注解,我们还可以自定义注解,在JDK 1.5中提供了4个标准的用来对注解类型进行注解的注解类,我们称之为 meta-annotation(元注解),他们分别是:

  1. @Target
    Target注解的作用是:描述注解的使用范围(即:被修饰的注解可以用在什么地方) 。Target注解用来说明那些被它所注解的注解类可修饰的对象范围:注解可以用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在ElementType 枚举中。
public enum ElementType {     
TYPE, // 类、接口、枚举类     
FIELD, // 成员变量(包括:枚举常量)     
METHOD, // 成员方法     
PARAMETER, // 方法参数     
CONSTRUCTOR, // 构造方法     
LOCAL_VARIABLE, // 局部变量     
ANNOTATION_TYPE, // 注解类     
PACKAGE, // 可用于修饰:包     
TYPE_PARAMETER, // 类型参数,JDK 1.8 新增     
TYPE_USE // 使用类型的任何地方,JDK 1.8 新增 
}
  1. @Retention
    Reteniton注解的作用是:描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时) 。Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在RetentionPolicy枚举中。
public enum RetentionPolicy {    SOURCE,    // 源文件保留   CLASS,       // 编译期保留,默认值    RUNTIME   // 运行期保留,可通过反射去获取注解信息}

反射的词语解释?为了验证应用了这三种策略的注解类有何区别,分别使用三种策略各定义一个注解类做测试。

@Retention(RetentionPolicy.SOURCE)
public @interface SourcePolicy {
}
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimePolicy {
}
@Retention(RetentionPolicy.CLASS)
public @interface ClassPolicy { 
}

用定义好的三个注解类分别去注解一个方法。

public class RetentionTest {  
@SourcePolicy public void sourcePolicy() { }  
@ClassPolicy public void classPolicy() { }  
@RuntimePolicy public void runtimePolicy() { }
}

在这里插入图片描述
3. @Documented
Documented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。为了验证Documented注解的作用到底是什么,我们创建一个带有 @Documented 的自定义注解类。

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target; 
@Documented@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedtAnnotation {  
public String value() default "这是@Documented注解为文档添加的注释";
}

再创建一个 MyDocumentedTest 类。

@MyDocumentedtAnnotationpublic 
class MyDocumentedTest {  
@Override 
@MyDocumentedtAnnotation 
public String toString() {  
return this.toString(); 
}}

在这里插入图片描述
命令执行完成之后,会在当前目录下生成一个 doc 文件夹,其内包含以下文件。
在这里插入图片描述
查看 index.html 帮助文档,可以发现在类和方法上都保留了 MyDocumentedtAnnotation 注解信息。
在这里插入图片描述
修改 MyDocumentedtAnnotation 注解类,去掉上面的 @Documented 注解。

import java.lang.annotation.ElementType;
import java.lang.annotation.Target; 
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedtAnnotation {  
public String value() 
default "这是@Documented注解为文档添加的注释";
}

重新生成帮助文档,此时类和方法上的 MyDocumentedtAnnotation 注解信息都不见了。
在这里插入图片描述
4. @Inherited
Inherited注解的作用是:使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。接下来我们使用代码来进行测试,首先创建一个被@Inherited修饰的注解类MyInheritedAnnotation。

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 
@Inherited@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyInheritedAnnotation {  
public String name() 
default "pengjunlee";
}

java反射有什么用。创建一个带有 MyInheritedAnnotation 注解的父类和一个无任何注解的子类。

@MyInheritedAnnotation(name="parent")
public class Parent { 
}
public class Child extends Parent{  public static void main(String[] args) {  Class<Child> child=Child.class;  MyInheritedAnnotation annotation = child.getAnnotation(MyInheritedAnnotation.class);  System.out.println(annotation.name()); }
}

运行程序,打印结果如下:

parent

注解应用

应用举例
首先自定义一个注解类。

package com.pengjunlee;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inheritedpublic 
@interface MyAnnotation {  public String name() default "pengjunlee";
}

在 AnnotationTest 中使用反射获取注解信息。

package com.pengjunlee; 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method; 
@MyAnnotation(name = "name of type")
public class AnnotationTest {  @MyAnnotation(name = "name of method") public String hello() {       return "hello";    }  public static void main(String[] args) throws NoSuchMethodException, SecurityException {      Class<AnnotationTest> annotationTest = AnnotationTest.class;      // 获取类上的所有注解      Annotation[] annotations = annotationTest.getAnnotations();       for (Annotation annotation : annotations) {          // 获取注解的全类名System.out.println(annotation.annotationType().getName());    }     // 获取 hello() 方法      Method method = annotationTest.getMethod("hello", new Class[] {});        // hello() 方法上是否有 MyAnnotation 注解     if (method.isAnnotationPresent(MyAnnotation.class)) {        // 获得注解          MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);          // 获取注解的内容       System.out.println(annotation.name());        }  }
}

运行程序,打印结果如下:

com.pengjunlee.MyAnnotation
name of method

在这里插入图片描述

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/47597.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息