02-Java SE-注解和反射

目录

1.注解

1.1内置注解:

1.2元注解:

1.3自定义注解

2.反射

得到class类的几种方式

Java内存分析:

分析类的初始化 

类加载器:

获取类的运行时结构

重点:通过反射 动态创建对象 执行方法

性能对比分析(普通、反射开启安全机制、反射关闭安全机制):

 通过反射操作泛型:

反射操作注解:

总结:


1.注解

Annotation是JDK5.0开始引入的新技术。

1.1内置注解:

1.2元注解:

元注解的作用是负责注解其他注解 。

 @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期

(source(注解在程序是源代码.java的时候会被识别) <  class(注解在程序是字节码文件.class的时候可以被识别) < runtime(注解在程序运行时可以被识别))

@Target表示我们的注解可以使用在什么地方。

枚举ElementType如下:



package java.lang.annotation;

/**
 * The constants of this enumerated type provide a simple classification of the
 * syntactic locations where annotations may appear in a Java program. These
 * constants are used in {@link Target java.lang.annotation.Target}
 * meta-annotations to specify where it is legal to write annotations of a
 * given type.
 *
 * <p>The syntactic locations where annotations may appear are split into
 * <em>declaration contexts</em> , where annotations apply to declarations, and
 * <em>type contexts</em> , where annotations apply to types used in
 * declarations and expressions.
 *
 * <p>The constants {@link #ANNOTATION_TYPE} , {@link #CONSTRUCTOR} , {@link
 * #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} ,
 * {@link #PARAMETER} , {@link #TYPE} , and {@link #TYPE_PARAMETER} correspond
 * to the declaration contexts in JLS 9.6.4.1.
 *
 * <p>For example, an annotation whose type is meta-annotated with
 * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
 * field declaration.
 *
 * <p>The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS
 * 4.11, as well as to two declaration contexts: type declarations (including
 * annotation type declarations) and type parameter declarations.
 *
 * <p>For example, an annotation whose type is meta-annotated with
 * {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field
 * (or within the type of the field, if it is a nested, parameterized, or array
 * type), and may also appear as a modifier for, say, a class declaration.
 *
 * <p>The {@code TYPE_USE} constant includes type declarations and type
 * parameter declarations as a convenience for designers of type checkers which
 * give semantics to annotation types. For example, if the annotation type
 * {@code NonNull} is meta-annotated with
 * {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull}
 * {@code class C {...}} could be treated by a type checker as indicating that
 * all variables of class {@code C} are non-null, while still allowing
 * variables of other classes to be non-null or not non-null based on whether
 * {@code @NonNull} appears at the variable's declaration.
 *
 * @author  Joshua Bloch
 * @since 1.5
 * @jls 9.6.4.1 @Target
 * @jls 4.1 The Kinds of Types and Values
 */
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}
@Target注解需要传入的是数组值,定义的属性ElementType[] value()为,@Target源码如下:
package java.lang.annotation;

/**
 * Indicates the contexts in which an annotation type is applicable. The
 * declaration contexts and type contexts in which an annotation type may be
 * applicable are specified in JLS 9.6.4.1, and denoted in source code by enum
 * constants of {@link ElementType java.lang.annotation.ElementType}.
 *
 * <p>If an {@code @Target} meta-annotation is not present on an annotation type
 * {@code T} , then an annotation of type {@code T} may be written as a
 * modifier for any declaration except a type parameter declaration.
 *
 * <p>If an {@code @Target} meta-annotation is present, the compiler will enforce
 * the usage restrictions indicated by {@code ElementType}
 * enum constants, in line with JLS 9.7.4.
 *
 * <p>For example, this {@code @Target} meta-annotation indicates that the
 * declared type is itself a meta-annotation type.  It can only be used on
 * annotation type declarations:
 * <pre>
 *    &#064;Target(ElementType.ANNOTATION_TYPE)
 *    public &#064;interface MetaAnnotationType {
 *        ...
 *    }
 * </pre>
 *
 * <p>This {@code @Target} meta-annotation indicates that the declared type is
 * intended solely for use as a member type in complex annotation type
 * declarations.  It cannot be used to annotate anything directly:
 * <pre>
 *    &#064;Target({})
 *    public &#064;interface MemberType {
 *        ...
 *    }
 * </pre>
 *
 * <p>It is a compile-time error for a single {@code ElementType} constant to
 * appear more than once in an {@code @Target} annotation.  For example, the
 * following {@code @Target} meta-annotation is illegal:
 * <pre>
 *    &#064;Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
 *    public &#064;interface Bogus {
 *        ...
 *    }
 * </pre>
 *
 * @since 1.5
 * @jls 9.6.4.1 @Target
 * @jls 9.7.4 Where Annotations May Appear
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

@Target注解的使用案例如下:

package com.minstone;

import net.bytebuddy.implementation.bind.annotation.RuntimeType;

import java.lang.annotation.*;

/**
 * 测试元注解
 */
@MyAnnotation
public class Test01 {
    public static void main(String[] args) {

    }

    @MyAnnotation
    public void test(){

    }
}


// 表示我们的注解可以用在什么地方
@Target(value = {ElementType.METHOD})
// 表示我们的注解在什么地方生效
// runtime > class > sources
// 定义为runtime的runtime、class、sources 3个阶段生效
// 定义为class的可以在class、sources 2个阶段生效
// 定义为sources的只能在sources阶段生效
@Retention(value = RetentionPolicy.SOURCE)
// 表示是否将我们的注解生成在 JAVAdoc中
@Documented
// 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{

}

1.3自定义注解

注解可以显示赋值,如果没有默认值,我们就必须给注解赋值。

自定义注解未设置参数默认值,在使用该注解的时候不给该参设值则报错

 自定义注解为设置参数默认值,使用该注解的时候不给该参设值则正常

 

2.反射

反射学习的大纲:

Java反射机制概述

理解Class类并获取Class实例

类的加载与ClassLoader

创建运行时类的对象

获取运行时类的完整结构

调用运行时类的指定结构

静态语言和动态语言的区别:

 Java Reflection(反射)

反射是什么,反射和正常方式的区别?如下:

 Java 反射机制提供的功能 有哪些?

Java 反射的优点和缺点 是什么?

反射相关的主要API

得到class类的几种方式

哪一些类型可以有class对象? 

类输出展示:

Java内存分析:

类的加载与ClassLoader 的理解:

  类的加载过程:

分析类的初始化 

什么时候会发生类的初始化:

 初始化代码:

输出结果:

所以反射和手动new 对象();都是一样的,都属于类的主动引用。

类的被动引用:(不会发生类的初始化)

// 子类调用父类的 static 属性,不会初始化子类

// Son [] = new Son[5]新建一个子类的数字,只是分配一块内存空间 给该数组,是不存在子类的初始化的

// 调用子类的 常量 private static final int M = f1; 

父类和子类都不会去初始化

原因:常量 是在类加载的链接过程中 的第二阶段(准备)的时候就会给该常量分配内存空间并且赋值。 

类加载器:

Java代码的在计算机中经历的三个阶段

1. 源代码 (.java)编译为

2.字节码文件(class)编译为

3.计算机能够识别的二进制文件。

 引导类加载器,C++编写,负责Java平台核心库 rt.jar

 rt.jar 里面的内容:java.lang \ java.io \ java.beans等等

 在Java中获取根加载器、扩展类加载器、系统类的加载器

 当前类 是 什么类加载器加载的?JDK内置的类是什么 类加载器加载的? 

系统类加载器可以加载的路径有哪些?

程序:

 输出结果:

 这些路径下面的类都可以被加载到,如何不在该路径下面就无法加载该类

类的加载不是凭空的而是由类加载器加载的,是需要遵守规则的。

 顺便提一口双亲委派机制:

        如果你自定义一个java.lang.String类的话,程序在加载的时候会去往父类一层层的寻找,java原生的是否存在该类,如果存在的话,java只会用它自带的类,而不是去加载用户自定义的同名的类。

原因:这是出于安全的考虑,java自带的安全机制。

获取类的运行时结构

小结:

在实际操作中,取得类的信息的操作代码,并不会经常开发。

一定要熟悉java.lang.reflect包的作用,反射机制。

如何取得属性,方法,构造器的名称,修饰符等。

重点:通过反射 动态创建对象 执行方法

有了Class对象,能做什么?

如何通过反射来操作方法?

 

 如何通过反射操作属性?

注意:使用反射操作属性的时候,不能直接操作私有属性,我们需要关闭程序的安全监测,

属性或者方法的serAccessible(true)

setAccessible的使用:

性能对比分析(普通、反射开启安全机制、反射关闭安全机制):

package com.minstone;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test05 {
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test01();
        test02();
        test03();
    }


    private static void test01(){
        User user = new User();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            user.getName();
        }
        long endtime = System.currentTimeMillis();
        System.out.println("普通方法执行10亿次的时间:"+ (endtime - start) + "ms");
    }

    private static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class<? extends User> c1 = user.getClass();
        // 获取getName方法
        Method getName = c1.getDeclaredMethod("getName", null);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            // 执行getName方法,传入对象,和方法的入参
            getName.invoke(user, null);
        }
        long endtime = System.currentTimeMillis();
        System.out.println("反射开启安全检查策略,执行10亿次的时间:"+ (endtime - start) + "ms");
    }

    private static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class<? extends User> c1 = user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        // 关闭安全检查策略
        getName.setAccessible(true);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user, null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射关闭安全检查策略,执行10亿次的时间:" + (endTime - startTime) + "ms");
    }
}

结果:

普通方法执行10亿次的时间:18ms
反射开启安全检查策略,执行10亿次的时间:12828ms
反射关闭安全检查策略,执行10亿次的时间:5682ms

Process finished with exit code 0

 通过反射操作泛型:

 打印结果:

反射操作注解:

练习使用反射操作注解

package com.minstone;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 联系反射操作注解
 */
public class Test06 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class<?> c1 = Class.forName("com.minstone.Student2");
        // 通过反射获取注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        // 获取类 上注解的value的值
        Tablekuang tablekuang = c1.getAnnotation(Tablekuang.class);
        String value = tablekuang.value();
        System.out.println(value);

        // 获取属性 上注解的value的值
        Field[] declaredFields = c1.getDeclaredFields(); // 获取所以的字段
//        Field nameDeclaredFields = c1.getDeclaredField("name");  // 获取指定名字的字段
        for (Field field : declaredFields) {
            Fieldkuang fieldkuang = field.getAnnotation(Fieldkuang.class);
            String cloumnName = fieldkuang.cloumnName();
            int length = fieldkuang.length();
            String type = fieldkuang.type();
            System.out.println(field.getName()+ " " + cloumnName + " " + type + " " + length);
        }
    }
}

@Tablekuang("db_student")
class Student2{

    @Fieldkuang(cloumnName = "db_name", type = "varchar", length = 10)
    private String name;

    @Fieldkuang(cloumnName = "db_age", type = "int", length = 4)
    private int age;

    @Fieldkuang(cloumnName = "db_id", type = "int", length = 4)
    private int id;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getId() {
        return id;
    }
}



/**
 * 类名的注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablekuang{
    String value();
}


/**
 * 属性的注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldkuang{
    String cloumnName();
    String type();
    int length();
}

输出结果:

@com.minstone.Tablekuang(value=db_student)
db_student
name db_name varchar 10
age db_age int 4
id db_id int 4

Process finished with exit code 0

总结:

什么是注解

        内置注解

        自定义注解

什么是反射

学习地址:

【狂神说Java】注解和反射_哔哩哔哩_bilibili

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值