Java注解和反射

Java注解和反射

@author:HB、ocean

@time:2020-3-20

Annotation 注解

Comment 注释

Reflection 反射

pojo entity 实体类

注解

什么是注解

  1. JDK5.0引入的技术
  2. 可以被其他程序如编译器读取
  3. 格式:@注释名(参数值)
  4. 注解可以检查和约束程序

内置注解

  1. @Overrid 方法重写
  2. @Deprecated 危险不鼓励的写法
  3. @SuppressWarnnings 抑制编译时警告信息(可传递定义好的参数:all、unchecked、value={“unckecked”,“deprecation”}等)

元注解

  1. @Traget 注解使用范围
  2. @Retention 注解生命周期·(SOURCE<CLASS<RUNTIME
  3. @Document 包含javadoc中
  4. @Inherited 说明子类可以继承父类中注解

自定义注解

  1. @interface 注解名

  2. 注解的参数:参数类型 + 参数名(); (可添加 default 默认值、只有一个参数使用value可省略,默认值为-1代表找不到返回-1)

    // 自定义注解
    @MyAnnotation(name = "田一百五十六",age = 18,schools = {"北京大学","TINGHUA"})
    public void test() {
    
    }
    @Target({ElementType.TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotation{
        // 注解的参数:参数类型 + 参数名();;
        String name() default "李四";
        int age() default 0;
        int id() default -1;// 如果默认值为-1,代表不存在
    
        String[] schools();
    }
    

反射

反射概述

  1. 动态语言与静态语言
    • 动态语言:运行时可以改变其结构 Object-C、C#、JavaScript、PHP、Python等
    • 静态语言:运行时结构不可变 Java、C、C++
    • Java可以被称为“准动态语言”,有一定的动态性 反射机制
  2. JavaScript 程序运行后改变x值
function f() {
    var x = "var a = 3;var b = 5;alert(a+b)";
    eval(x)
}
  1. 反射机制允许程序在执行期间借助于Reflection API获得任何类的内部信息,并能操作任意对象内部属性与方法
Class c = Class.forName("java.lang.String")
  1. 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),对象包含完整类结构信息,通过对象可以看到类结构,称之为:反射(AOP动态代理)
  2. 优缺点
    • 优:可以实现动态创建对象和编译,灵活性
    • 缺:对性能有影响,基本上是解释操作,告诉JVM,JVM满足要求,慢于直接执行相应操作

反射相关主要API

  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造器
  • ……

Class类

Object 类定义了以下方法 返回Class类,反射的源头

public final Class getClass()

Class类常用方法

  • static ClassforName(String name) 返回制定类名name的Class对象
  • Object newInstance() 调用缺省构造参数,返回Class对象的一个实例
  • getName() 返回此Class对象所表示的实体(类、接口、数组类或void)的名称
  • Class getSuperClass() 返回当前Class对象的父类的Class对象
  • Class[] getinterfaces() 返回当前Class对象的接口
  • ClassLoader getClassLoader() 返回该类的类加载器
  • Constructor[] getConstructors() 返回一个包含某些Constructor对象的数组
  • Method getMethoed(String name,Class… T) 返回一个Method对象,此对象的形参类型为paramType
  • Field[] getDeclareFields() 返回Field对象的一个数组

获取Class类的方法

  1. 已知具体的类 通过类的calss属性 安全可靠 性能高

    Class c1 = Person.class;
    
  2. 已知某个类的实例 调用该实例的getClass方法

    Class c2 = person.getClass();
    
  3. 已知一个类的全类名,且该类在类路径下 通过Class类静态方法forName() 肯能抛出异常 ClassNotFoundException .

    Class c3 = Class.forName("java.lang.String");
    
  4. 内置基本数据类型 类名.TYPE

    Class c4 = Integer.TYPE;
    
  5. ClassLoader的使用

含有calss对象

Class c3 = Object.class;  // 类
Class c4 = Comparable.class;  // 接口
Class c5 = String[].class;  // 一维数组
Class c6 = int[][].class;  // 二维数组
Class c7 = Override.class;  // 注解
Class c8 = ElementType.class;  // 枚举
Class c9 = Integer.class;  // 基本数据类型
Class c10 = void.class;  // void
Class c11 = Class.class;  // Class

类的加载过程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

类的初始化

  1. 类的主动引用(一定会发生类的初始化)

    • 虚拟机启动 先初始化main方法所在的类
    • 通过new一个类的对象
    • 调用类静态成员(除了final常量)和静态方法
    • 通过反射 java.lang.reflect
  2. 类的被动引用(不会发生类的初始化)

    • 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量 不会导致子类初始化

    • 通过数组定义类引用 不会触发此类的初始化(仅分配名字空间)

      Son[] array = new Son[5];
      
    • 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池当中了)

类加载器

  1. 作用

在这里插入图片描述

在这里插入图片描述

获取系统的类加载器

        // 获取系统的类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        // 获取系统类加载器的父类加载器-->扩展类加载器 sun.misc.Launcher$ExtClassLoader@1b6d3586
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        // 获取系统类加载器的父类加载器-->根加载器(C/C++) 获取不到
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        // 测试当前类加载器是哪个类加载的
        ClassLoader classLoader = Class.forName("com.hb.prc.BHprc2").getClassLoader();
        System.out.println(classLoader);

        // 测试JDK内置类  (根加载器)
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        // 获得类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));

        // 双亲委派机制 向上找包 保证安全性 没有才可以运行 自己写的包名

创建运行时类的对象

  1. getName 与 getSimpleName

    Simple获得的是类名 不加 则是全类名(含包名)

  2. getFields 与 getDeclaredFields 与 getField 与 getDeclaredField

    Declared 可以获得私有的字段 不加则只能获得public

  3. getMethods 与 getDeclaredMethods 同理

    获得本类与父类public方法 Declared获得本类所有方法

  4. 获取指定方法 getMethod 与 getDeclaredMethod 有参数因为方法的重载需要参数如:String.class

  5. 获取构造器 getConstructors 与 getDeclaredConstructors

  6. 获取指定构造器 getConstruor 参数如:String.class、int.class

动态创建对象执行方法

  1. 获取Class对象

  2. getInstance()构造对象 调用无参构造器

  3. 通过构造器创建对象 c1.getDeclaredConstructor(String.class……).getInstance(“李四”……)

  4. 获取方法 getDeclaredMethod(setName,String.class)

    激活 对象 方法的值 setName.invoke(user3,“李四”)

  5. 操作属性 需要设置 setAccessible(true) 关闭Java 语言访问检查

  6. 属性字段.set(名称)来进行赋值

  7. setAccessible(true)可以提高反射的效率,私有成员可访问

  8. System.currentTimeMillis() 获取系统时间

反射操作泛型

在这里插入图片描述

例如:

package com.hb.prc;


import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

// 通过反射获取泛型
public class BHprc6 {


    // 泛型传参
    public  void test01(Map<String,User> map, List<User> list) {
        System.out.println("test01");
    }

    // 泛型返回值
    public  Map<String,User> test02() {
        System.out.println("test02");
        return null;
    }

    // 普通传参数
    public void test03(int a) {
        System.out.println("test03");
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = BHprc6.class.getMethod("test01", Map.class, List.class);

        Type[] genericParameterTypes = method.getGenericParameterTypes();

        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("参数类型" + genericParameterType);// 获得外层信息
            if (genericParameterType instanceof ParameterizedType) {// 泛型参数类型属于参数化类型
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();// 获得真实类型
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("真实泛型信息"+actualTypeArgument);
                }
            }
        }

        method = BHprc6.class.getMethod("test02",null);

        Type genericReturnType = method.getGenericReturnType();

        System.out.println("返回类型"+genericReturnType);

        if (genericReturnType instanceof ParameterizedType) {// 泛型参数类型属于参数化类型
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();// 获得真实类型
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("真实泛型信息"+actualTypeArgument);
            }
        }

        method = BHprc6.class.getMethod("test03", int.class);

        genericParameterTypes = method.getGenericParameterTypes();

        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("普通参数"+genericParameterType);
        }



    }
}

反射操作注解

ORM—对象关系映射Object relationship Mapping

注解和反射完成类和表结构映射关系

package com.hb.prc;

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

// 反射操作注解
public class BHprc7 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.hb.prc.Student");

        // 通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解"+annotation);// 获取注解
        }

        // 获得注解的value值
        Bhtable bhtable = (Bhtable)c1.getAnnotation(Bhtable.class);
        String value = bhtable.value();
        System.out.println("注解的value:"+value);

        // 获得类指定的注解
        Field name = c1.getDeclaredField("name");// 获取指定的属性
        Bhfield annotation = name.getAnnotation(Bhfield.class);// 获取属性的注解
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
        Field id = c1.getDeclaredField("id");// 获取指定的属性
        annotation = id.getAnnotation(Bhfield.class);// 获取属性的注解
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
        Field age = c1.getDeclaredField("age");// 获取指定的属性
        annotation = age.getAnnotation(Bhfield.class);// 获取属性的注解
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());

    }

}
@Bhtable("db_student")
class Student{
    @Bhfield(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Bhfield(columnName = "db_age",type = "int",length = 10)
    private int age;
    @Bhfield(columnName = "db_name",type = "varchar",length = 10)
    private String name;

    public Student() {
    }

    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}


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

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Bhfield{
    String columnName();
    String type();
    int length();
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值