反射与注解

元注解

负责注解其他注解(target )

@Target(value = {ElementType.METHOD,ElementType.TYPE})
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
//表示是否生成在JAVAdoc中
@Documented()
//字类可以继承父类的注解
@Inherited
@interface MyAnnotation{

}

自定义注解

@interface MyAnnotation2 {
    // 注解的参数:参数类型+参数名();
    String name() default "";

    int age() default 0;

    int id() default -1;
    String[] schools() default {"清华大学"};
}

反射

动态语言:运行时可以改变其结构(js)

反射允许类在运行期间获取类的任何内部信息(类名,接口,方法,属性)

  Class  c2 = Class.forName("com.fans.annotion_test");
  Class c3 = Test.class;
  Test2 t = new Test2();
  Class c4  = t.getClass();

哪些类型可以有class对象

class,interface ,数组,枚举,注解,基本数据类型,void

 Class c1 = Object.class;
 Class c2 = Comparable.class;
 Class c3 = String[].class;
 Class c4 = int[][].class;
 Class c5 = Override.class;
 Class c6 = ElementType.class;
 Class c7= Integer.class;
 Class c8 = void.class;
 Class c9 = Class.class;

java内存分析

堆:存放new出来的对象和数组,可以被所有线程共享,不会存放别的对象引用

栈:存放基本变量类型(会包含这个基本类型的具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)

方法区(特殊的堆):可以被所有线程共享,包含了所有的static和class变量

类的加载

​ 1.将类的class文件字节码内容读入内存,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的Class对象。

类的链接

​ 2.将类的二进制文件合并到JRE中

类的初始化

​ jvm对类进行初始化

什么时候发生类的初始化

  1. new 一个类的对象
  2. 调用类的静态成员(除了final变量)和静态方法
  3. 反射调用
  4. 初始化一个类,父类没有初始化,就会初始化父类

不会产生类的初始化

  1. 引用父类的静态域
  2. 通过数组定义类引用
  3. 常量调用(链接阶段就被初始化)

类加载器

  //系统加载器
        ClassLoader system = ClassLoader.getSystemClassLoader();

        // 扩展加载器
        ClassLoader parent = system.getParent();

        // 根加载器,jdk内置类
        ClassLoader parent1 = parent.getParent();


        // 如何获取系统加载器可以加载的路径
        System.getProperty("java.class.path");

//双亲委派机制

创建运行时类的对象

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

​ Field,Method,Constructor,Superclass,Interface,Annotion

  1. ​ 实现的全部接口
  2. 所继承的父类
  3. 全部的构造器
  4. 全部的方法
  5. 全部的field
  6. 注解
 Class cl = Class.forName("com.fans.annotion_test.Person");
        cl.getName();
        cl.getSimpleName();
        cl.getPackage().getName();

        Field[] fields = cl.getFields();//只能找到public属性

         fields = cl.getDeclaredFields();//可以找到全部属性

        Field name = cl.getDeclaredField("name");

        Method[] methods = cl.getMethods();//获取本类以及父类public方法

        methods = cl.getDeclaredMethods();//获取本类所有方法

        Method method = cl.getMethod("getAge",null);
        method = cl.getMethod("setAge", int.class);

        Constructor constructor = cl.getDeclaredConstructor(String.class,int.class);
 Class cl = Class.forName("com.fans.annotion_test.Person");
        Person person = (Person) cl.newInstance();//默认无参构造器,没有无参构造器报错

        Constructor constructor = cl.getDeclaredConstructor(String.class,int.class);
        Person person1  = (Person) constructor.newInstance("feng",10);

        //反射方法
        Method method = cl.getMethod("setAge", int.class);
        method.invoke(person1,10);

        //反射属性,不能直接操作私有属性,需要关闭程序的安全检测
        Field field = cl.getDeclaredField("name");
        field.setAccessible(true);
        field.set(person1,"haha");

性能问题

在这里插入图片描述

反射操作泛型

​ java采用泛型擦除的机制来引入泛型,java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和强制转换问题,但是一旦编译完成,所有和泛型有关的类型全部擦除

 public static void main(String[] args) throws NoSuchMethodException {
        Class test8Class = com.fans.annotion_test.Test8.class;

        Method method = test8Class.getMethod("test1", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for(Type type:genericParameterTypes){
            if(type instanceof ParameterizedType){
               Type[] types =  ((ParameterizedType) type).getActualTypeArguments();
               for (Type type1:types){
                   Log.d("--",type1.toString());
               }
            }
        }


    }

    public void test1(Map<String,Person> map, List<Person> list){

    }

反射获取注解信息

public class Test9 {
    public static void main(String[] args) throws NoSuchFieldException {
        Class cl = Child.class;
        Annotation[] annotations = cl.getAnnotations();
        DataBase annotation = (DataBase) cl.getAnnotation(DataBase.class);
        String value  = annotation.value();

        Field field = cl.getDeclaredField("age");
        FiledA a = field.getAnnotation(FiledA.class);
        String name = a.columnName();
    }

}


@DataBase("db_child")
class Child{
    @FiledA(columnName = "age",type = "int",length = 10)
    private int age;

    @FiledA(columnName = "name",type = "varchar",length = 10)
    private String name;

    public Child() {
    }

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

    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 "Child{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface DataBase{
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledA{
    String columnName();
    String type();
    int length();

}




@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface DataBase{
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledA{
    String columnName();
    String type();
    int length();

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值