• Java_注解与反射


    P1.注解

    C1.概述

    • 注解(Annotation)

    • 作用:

      • 不是程序本身,可以对程序做出解释

        • 这点和注释(Comment)一样

      • 可以被其它程序读取

        • 比如:编译器

    • 格式:

      • @注释名

      • @注释名(value="unchecked")

    • 使用的地方:

      • package

      • class

      • method

      • field

        相当于给它们添加了额外的辅助信息;

        我们可以通过反射机制编程实现对这些元数据的访问

    C2.内置注解

    • @Override

      • 定义在java.lang.Override

      • 只能修饰方法

      • 表示一个方法声明打算重写超类中的另一个方法声明

    • @Deprecated

      • 定义在java.lang.Deprecated

      • 可修饰方法、属性、类

      • 表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择

    • @SupperWarnings

      • 定义在java.lang.SupperWarnings

      • 用来抑制编译时的警告信息

      • 必须要有参数

      • 例子:

        • @SupperWarnings("all")

        • @SupperWarnings("unchecked")

        • @SupperWarnings(value={"unchecked", "deprecation"})

    C3.元注解

    • 元注解 => 负责注解其它注解

    • java.lang.annotation包中

    • 1) @Target

      • 描述注解的使用范围

    • 2) @Retention

      • 表示需要在什么级别保存该注释信息

        • 用于描述注解的生命周期

      • SOURCE < CLASS < RUNTIME

    • 3) @Documented

      • 说明该注解将被包含在Javadoc中

    • 4) @Inherited

      • 说明子类可以继承父类中的该注解

     package demo;
     
     import java.lang.annotation.Documented;
     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;
     
     @MyAnnotation
     public class Test01 {
     
      @MyAnnotation
      public void test() {
     
      }
     }
     
     @Inherited
     @Documented
     @Retention(RetentionPolicy.RUNTIME)
     @Target(value= {ElementType.TYPE, ElementType.METHOD})
     @interface MyAnnotation {
     
     }

    C4.自定义注解

    • 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口

    • 自定义注释的格式:public @interface 注释名 { 定义内容 }

      • 其中的每一个方法实际上是声明了一个配置参数

        • 方法的名称 => 参数的名称

        • 返回值类型 => 参数类型

        • default => 声明参数的默认值

        • 如果只有一个参数成员,一般参数名为value

        • 注解元素必须要有值

          • 我们定义注解元素时,通常使用空字符串、0作为默认值

     package demo;
     
     import java.lang.annotation.ElementType;
     import java.lang.annotation.Retention;
     import java.lang.annotation.RetentionPolicy;
     import java.lang.annotation.Target;
     
     @MyAnnotation2(age=10, schools= {})
     @MyAnnotation3("abc")
     public class Test02 {
     
      @MyAnnotation2(age=10, name="haha", schools="njcit")
      public void fun() {
     
      }
     }
     
     @Target({ ElementType.TYPE, ElementType.METHOD })
     @Retention(RetentionPolicy.RUNTIME)
     @interface MyAnnotation2 {
      String name() default "";
      int age();
      int id() default -1;
     
      String[] schools();
     }
     
     @Target({ ElementType.TYPE, ElementType.METHOD })
     @Retention(RetentionPolicy.RUNTIME)
     @interface MyAnnotation3 {
      String[] value();
     }

    P2.反射

    C1.概述

    • “动态语言”与“静态语言”:

      • 动态语言:

        • 在运行时可以改变其结构

          • 例如新的函数、对象,甚至代码可以被引进,已有的函数可以被删除或者其他结构上的变化

          • 即,在运行时代码可以根据某些条件改变自身接哦股

        • 如:C#、Js、PHP、Python等

      • 静态语言:

        • 运行时结构不可变的语言

        • 如:Java、C、C++

        • 准动态语言

          • Java具有一定的动态性

          • 我们可以通过反射机制获得类似动态语言的特性

    • 反射机制允许程序在执行期间,借助Reflection API取得任何类的内部信息,并直接操作任意对象的内部属性及方法

    • 加载完类后,在堆内存的方法区中就会产生一个Class类型的对象

      • 一个类只有一个Class对象

      • 该对象包含了完整的类的结构信息

        • 通过这个类能够看到类的结构

    • 优缺点:

      • 优点:

        • 可以动态实现创建对象和编译,体现出很大的灵活性

      • 缺点:

        • 对性能有影响

          • 反射基本上是一种解释操作

            • 我们告诉JVM希望它做什么,并且使它满足我们的要求

            • 这类操作往往慢于直接执行相同的操作

    • 反射相关的主要API

      • java.lang.Class

      • java.lang.reflect.Method

      • java.lang.reflect.Field

      • java.lang.reflect.Constructor

    C2.理解Class类并获取Class实例

    • Class对象只能由系统建立对象

    • 一个Class对象对应的是一个加载到JVM中的一个.class文件

    • 每个类的实例都会记得自己是由哪个Class实例所生成

    • 通过Class类可以完整的得到一个类中所有被加载的结构

    • Class类是Reflection的根源,任何你想动态加载、运行的类,唯有先获得相应的Class对象

    • Class类的常用方法:

    • 哪些类型可以有Class对象?

      • class

      • interface

      • 数组

        • 只要元素类型同,即使数组长度不同,它们的Class都一样

      • enum

      • annotation

      • primitive type

      • void

    C3.类的加载与ClassLoader

    • Java内存:

    • 类加载的过程

    • 什么时候发生类初始化:

     // 获取系统类的加载器
     ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
     System.out.println("<appClassLoader> " + appClassLoader);
     
     // 获取系统类加载器的父类加载器 => 扩展类加载器
     ClassLoader extClassLoader = appClassLoader.getParent();
     System.out.println("<extClassLoader> " + extClassLoader);
     
     // 获取扩展类加载器的父类加载器 => 根加载器
     // 因为是C/C++编写的,所以Java获取不到
     ClassLoader rootClassLoader = extClassLoader.getParent();
     System.out.println("<rootClassLoader> " + rootClassLoader);
     
     // 测试当前类是哪个类加载器加载的
     ClassLoader curClassLoader = Class.forName("demo.Test03").getClassLoader();
     System.out.println("<curClassLoader> " + curClassLoader);
     
     // 测试jdk内置类是哪个类加载器加载的
     ClassLoader objClassLoader = Class.forName("java.lang.Object").getClassLoader();
     System.out.println("<jdk内置类的ClassLoader> " + objClassLoader);
     
     // 如何获得系统类加载器可以加载的路径
     System.out.println("系统类加载器可以加载的路径");
     System.out.println(System.getProperty("java.class.path"));
     <appClassLoader>
     sun.misc.Launcher$AppClassLoader@73d16e93
     <extClassLoader>
     sun.misc.Launcher$ExtClassLoader@15db9742
     <rootClassLoader>
     null
     <curClassLoader>
     sun.misc.Launcher$AppClassLoader@73d16e93
     <jdk内置类的ClassLoader>
     null
     系统类加载器可以加载的路径
     D:Program DataworkspaceEclipse2.NewStudy_Java7.Annotationin

    C4.创建运行时类的对象

    • 调用Class对象的newInstance()方法

      • 类必须有一个无参的构造函数

      • 类的构造函数的访问权限必须要足够

    • 如果反射比较多的话,建议关闭“检测”,这样能够提升效率

    C5.获取运行时类的完整结构

    • 通过反射获取完整的运行时类结构

    • Field、Method、Constructor、Superclass、Interface、Annotation......

    C6.调用运行时类的指定结构

    反射操作泛型

    • 泛型 => 一种约束机制

      • Java采用的是泛型擦除机制来引入泛型

      • 仅仅是给编译器javac使用的

        • 一旦编译完成,所有和泛型有关的类型全部擦除

      • 确保数据的安全性和免除强制类型

    • 为了通过反射操作这些类型,Java新增了ParameterizedType、GenericArrayType、TypeVariable、WildcardType几种类型,用于代表不能被归一到Class类中的类型,但是又和原类型齐名的类型

      • ParameterizedType

        • 表示一种参数化类型,如Collection<String>

      • GenericArrayType

        • 表示一种元素类型是参数化类型或者类型变量的数组类型

      • TypeVariable

        • 各种类型变量的公共父接口

      • WildcardType

        • 代表一种通配符类型表达式

    • 获得方法泛型参数的类型:method.getGenericParameterTypes();

     package demo;
     
     import java.lang.reflect.Method;
     import java.lang.reflect.ParameterizedType;
     import java.lang.reflect.Type;
     import java.util.Map;
     
     public class Test05 {
      public void test01(Map<String, User> map, User<Integer> user) {
     
      }
     
      public Map<String, User> test02() {
      return null;
      }
     
      public static void main(String[] args) throws NoSuchMethodException, SecurityException {
      Method method = Test05.class.getMethod("test01", Map.class, User.class);
     
      Type[] genericParameterTypes = method.getGenericParameterTypes();
      for (Type type : genericParameterTypes) {
      System.out.println(" #" + type);
      if (type instanceof ParameterizedType) {
      Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
      for (Type type2 : actualTypeArguments) {
      System.out.println(type2);
      }
      }
      }
     
      Method method2 = Test05.class.getMethod("test02", null);
      Type genericReturnType = method2.getGenericReturnType();
      System.out.println(" #" + genericReturnType);
      if (genericReturnType instanceof ParameterizedType) {
      Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
      for (Type type2 : actualTypeArguments) {
      System.out.println(type2);
      }
      }
      }
     }

    反射操作注解

    • getAnnotations

    • geAnnotation

    • ORM

      • Object Relationship Mapping => 对象关系映射

     package demo;
     
     import java.lang.annotation.Annotation;
     import java.lang.annotation.ElementType;
     import java.lang.annotation.Retention;
     import java.lang.annotation.RetentionPolicy;
     import java.lang.annotation.Target;
     import java.lang.reflect.Field;
     
     public class Test06 {
      public static void main(String[] args) throws ClassNotFoundException {
      Class<?> cls = Class.forName("demo.Student");
     
      System.out.println(" // 获取Student类的所有注解");
      Annotation[] typeAnnotations = cls.getAnnotations();
      for (Annotation annotation : typeAnnotations) {
      System.out.println(annotation);
      }
     
      System.out.println(" // 获取指定注解的值");
      TypeAnnotation typeAnnotation = cls.getAnnotation(TypeAnnotation.class);
      String value = typeAnnotation.value();
      System.out.println(value);
     
      System.out.println(" // 获取Student类属性的所有注解");
      Field[] declaredFields = cls.getDeclaredFields();
      for (Field field : declaredFields) {
      Annotation[] fieldAnnotations = field.getAnnotations();
      for (Annotation annotation : fieldAnnotations) {
      System.out.println(annotation);
      System.out.println(((FieldAnnotation)annotation).dbName());
      System.out.println(((FieldAnnotation)annotation).dbType());
      System.out.println(((FieldAnnotation)annotation).length());
      }
      }
      }
     }
     
     @Deprecated
     @TypeAnnotation("db_user")
     class Student {
      @FieldAnnotation(dbName = "t_id", dbType = "varchar", length = 10)
      private String id;
      @FieldAnnotation(dbName = "t_gender", dbType = "varchar", length = 2)
      private String gender;
     
      public Student(String id, String gender) {
      super();
      this.id = id;
      this.gender = gender;
      }
     
      public Student() {
      super();
      }
     
      public String getId() {
      return id;
      }
     
      public void setId(String id) {
      this.id = id;
      }
     
      public String getGender() {
      return gender;
      }
     
      public void setGender(String gender) {
      this.gender = gender;
      }
     
      @Override
      public String toString() {
      return "Student [id=" + id + ", gender=" + gender + "]";
      }
     }
     
     @Target(ElementType.TYPE)
     @Retention(RetentionPolicy.RUNTIME)
     @interface TypeAnnotation {
      String value();
     }
     
     @Target(ElementType.FIELD)
     @Retention(RetentionPolicy.RUNTIME)
     @interface FieldAnnotation {
      String dbName();
     
      String dbType();
     
      int length();
     }

     

  • 相关阅读:
    The FLARE On Challenge
    CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)
    CVE-2014-0322漏洞成因与利用分析
    CVE-2013-3897漏洞成因与利用分析
    译:《深入解析WINDOWS VISTA APC》——PART 1
    MemoryInjector 无痕注入
    一个APC引起的折腾 之题外记
    一个APC引起的折腾
    2020
    javascriptcore调试笔记
  • 原文地址:https://www.cnblogs.com/daheww/p/10654580.html
Copyright © 2020-2023  润新知