注解和反射笔记

目录

1.注解

 2.反射初步

(1)概述:

 (2)class类

 (3)class对象的类型

3.反射的底层和用法分析

(1)类的加载

 (2)类的初始化

 (3)类加载器

(4)获得类运行时的结构

 (5)动态创建对象执行方法

 (6)反射泛型

 (7)获取注解信息


1.注解

 

 

 

 2.反射初步

(1)概述:

 

 

 (2)class类

ps:实体类和之前的略有不一样,实体类就是一个拥有Set和Get方法的类。实体类通常总是和数据库之类的(所谓持久层数据)联系在一起。这种联系是借由框架(如Hibernate)来建立的。

 

 

 

 

 

//class类的创建方法
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这是:" + person.name);

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //方法二:forname获得
        Class<?> c2 = Class.forName("com.example.Student");
        System.out.println(c2.hashCode());
        //方法三:通过类名
        Class c3=Student.class;
        System.out.println(c3.hashCode());
        //方法四:基本内置类型的包装类有一个type属性,但仅仅局限于基本内置类型
        Class<Integer> type = Integer.TYPE;

    }

}


class Person {
    public String name;
    public double height;

    public Person() {
    }

    public Person(String name, double height) {
        this.name = name;
        this.height = height;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return height
     */
    public double getHeight() {
        return height;
    }

    /**
     * 设置
     *
     * @param height
     */
    public void setHeight(double height) {
        this.height = height;
    }

    public String toString() {
        return "Person{name = " + name + ", height = " + height + "}";
    }
}

class Student extends Person {
    public Student() {
        name = "学生";
    }

}

class Teacher extends Person {
    public Teacher() {
        name = "老师";
    }
}
//还有个getsuperclass获得父类类型

结果:

 (3)class对象的类型

 PS:选择然后按alt键可以整体竖着复制

测试:

 比如下面,两个长度不一样的int数组,只有都是一维数组,那么就都只有一个class

 

3.反射的底层和用法分析

(1)类的加载

 链接里面的解析这一步:

 例子:

 这是为什么捏?先方法区加载类的字节码,然后堆里面创建Class类对象,然后栈里面进入main方法,然后继续调用......

 链接阶段m默认初始化为0,然后new A ,要对A的这个对象做初始化,所以把赋值和静态代码块合并起来,所以实际上,顺序是这样的m=300;m=100;最后m就是等于100

 (2)类的初始化

 

 主动加载这几种方法比较常见,下面展示一下被动引用:

 这里调用父类里面的static int b=2,所以只加载Main和父类

 这里什么都没干,就只是main加载了,不加载son类

M是父类里面的常量

 那么常量不会引起父类或子类的加载

就一个main

 (3)类加载器

缓存为了提高效率

 

 

 null意思是根加载器加载的。

扩充:

 双亲委派机制,保证安全性,比如你写了一个java.lang.String,他会一直找到根加载器,如果在这里找到了系统也有一个Java.lang.String,那么他就不会用你自己写的,你自己写就根本用不了,以保证安全和效率

(4)获得类运行时的结构

 

 测试:

 

 

 (5)动态创建对象执行方法

 

 

 法二:

 

 

 

我们已经可以通过反射得到方法、字段、构造器,也可以通过他们创建对象、调用方法、操作属性。

  注意,反射是比较慢的:

 

 

 

 (6)反射泛型

 这里test01(Map<>,list<>){

},然后这里.class获得class对象然后getMethod获取方法,再用Type【】泛型接受参数类型

收到map和list,然后我们还向知道map,list里面具体是什么,就需要用instance of判断这些泛型是不是这个方法的参数类型,如果是再强转,使用geractualtype,用Type【】接受参数类型返回值,从而知道所有的

 然后下面考察的是返回值类型,都是一样的逻辑

 (7)获取注解信息

 最后我亲手试一遍:

//练习反射操作注解
public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class<?> c1 = Class.forName("com.example.Test2");
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //注解的英文就是annotation

        //获取指定的注解的value值
        Taketake take = c1.getAnnotation(Taketake.class);
        String value=take.value();
        System.out.println(value);

        //获得类的指定注解
        Field f =c1.getDeclaredField("name");
        Fielddo annotation = f.getAnnotation(Fielddo.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.length());
        System.out.println(annotation.type());

    }

}

@Taketake("student_db")
class Student {
    @Fielddo(columnName = "name_db", type = "varchar", length = 3)
    private String name;
    @Fielddo(columnName = "age_db", type = "int", length = 10)
    private String age;

    public Student() {
    }

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

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public String getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(String age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

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

//属性的注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fielddo {
    String columnName();

    String type();

    int length();

}

以后可能会在类里面定义一些注解,然后通过反射框架读取然后生成相应的信息。假设数据库里有一张表,我们可以通过定义和这个表对应的类型,然后通过注解生成一些数据库的语言进行增删改查

选择的课程:【狂神说Java】注解和反射_哔哩哔哩_bilibili

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值