注解和反射

注解和反射

一、注解 Annotation
1.1、元注解
//Target表示我们的注解可以用在那些地方
@Target(value = {ElementType.TYPE,ElementType.METHOD})
//Retention 表示我们的注解在什么地方还有效
@Retention(value = RetentionPolicy.RUNTIME)
//Documented 表示是否将我们的注解生成在JavaDoc中
@Documented
//Inherited 子类可以继承父类的注解
@Inherited
//@interface 定义注解
@interface MyAnnotation{
}
1.2、自定义注解
public class TestAnnotation {
    @MyAnnotation(name = "李四", value = 5)
    public void test() {
    }
}

//自定义注解

//Target表示我们的注解可以用在那些地方
@Target(value = {ElementType.TYPE,ElementType.METHOD})
//Retention 表示我们的注解在什么地方还有效
@Retention(value = RetentionPolicy.RUNTIME)
//Documented 表示是否将我们的注解生成在JavaDoc中
@Documented
//Inherited 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{
    //注解的参数 : 参数类型 + 参数名();
    String name();
    //可以给参数设置默认值
    int id() default 0;
    
    String[] schools() default {"北京大学","清华大学"};

    //只有一个参数时,一般将参数名设为value
    int value();
}
二、反射 Reflection

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法

对于每个类而言,JRE都为其保留一个不变的Class类型的对象(唯一的),一个Class对象包含了特定的

**注:**只要元素类型与维度一样,就是同一个Class

Class 类:

  1. Class本身也是一个类
  2. Class对象只能由系统建立对象 - --(我们只能获取)
  3. 一个加载的类在JVM中只会由一个Class实例
  4. 一个Class对象对应的是一个加载到JVM中的一个 .class 文件
  5. 每个类的实例都会记得自己是由哪个Class实例所生成
  6. 通过Class可以完整地得到一个类中的所有被加载的结构
  7. Class类是Reflection的根源,针对任何你想动态加载、运行的类、唯有先获得相应的Class对象
1.1: 只要元素类型与维度一样,就是同一个class
public static void main(String[] args) {

        int[] ints1 = new int[10];
        int[] ints2 = new int[20];
        System.out.println(ints1.getClass().hashCode());  //  1836019240
        System.out.println(ints2.getClass().hashCode());  //  1836019240

        ArrayList list1 = new ArrayList<>();
        ArrayList list2 = new ArrayList<>();
        System.out.println(list1.getClass().hashCode());  // 325040804
        System.out.println(list2.getClass().hashCode());  // 325040804

        int[][] ints = new int[10][10];
        int[] ints3 = new int[10];
        System.out.println(ints.getClass().hashCode());  // 1173230247
        System.out.println(ints3.getClass().hashCode()); // 1836019240  不同

        A a = new A();
        A a1 = new A(1);
        System.out.println(a.getClass().hashCode());     // 856419764
        System.out.println(a1.getClass().hashCode());    // 856419764
    }
}
class A{
    private int anInt;
    public A() {}
    public A(int anInt) {
        this.anInt = anInt;
    }}
1.2: 得到Class类的几种方式
public class ReflectionTest2 {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一 : 通过对象获得
        Person stu = new Student();
        Class c1 = stu.getClass();
        System.out.println(c1.hashCode());

        //方式二 : 通过forname获得
        Class c2 = Class.forName("注解_反射.reflection.Student");
        System.out.println(c2.hashCode());

        //方式三 : 通过类名 .class 获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

        //方式四 : 基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);   //int
    }
}

class Person{
}

class Student extends Person{  
}
1.3: 所有类型的class
        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;           //void
        Class c9 = Class.class;          //class
1.4: 类加载–内存分析

​ jvm:

在这里插入图片描述

​ 堆:

​ 1.存放new的对象和数组

​ 2.可以被所有的线程共享,不会存放别的对象引用

方法区会在以后逐步移除,采用方法区会在以后逐步移除,采用native memory来实现方法区的规划,好像是因为方法区的回收比较困难,也因此导致过很多严重的bug来实现方法区的规划,好像是因为方法区的回收比较困难,也因此导致过很多严重的bug,常量池 jdk7后存于堆中,节约内存

​ 栈:

​ 1.存放基本变量类型(会包含这个基本类型的具体数值)

​ 2.引用对象的变量(会存放这个引用在堆里面的具体地址)

​ 方法区:

​ 1.可以被所有的线程共享

​ 2.包含了所有的class和static变量

1.5: 获取类的运行时结构
public class ReflectionTest4 {
    public static void main(String[] args) throws Exception {
        Class c1 = User.class;
        //获取类的名字
        System.out.println(c1.getName()); //获得包名+类名
        System.out.println(c1.getSimpleName()); //获得类名
        System.out.println("====================");

        //获得类的属性
        Field[] fields = c1.getFields();  //只能获得public修饰的属性
        System.out.println(Arrays.toString(fields));

        fields = c1.getDeclaredFields();  //获得全部属性
        System.out.println(Arrays.toString(fields));
        //获得指定属性
        Field name = c1.getDeclaredField("name");
        System.out.println(name);
        System.out.println("====================");

        //获取类的方法
        Method[] methods = c1.getMethods();    //获取本类及父类所有public方法
        System.out.println(Arrays.toString(methods));
        methods = c1.getDeclaredMethods();     //获取本类所有方法
        System.out.println(Arrays.toString(methods));
        //获取指定方法  --有参数和无参数
        Method setAge = c1.getDeclaredMethod("setAge", int.class);
        System.out.println(setAge);
        Method getAge = c1.getDeclaredMethod("getAge",null); //null 可传可不传
        System.out.println(getAge);
        System.out.println("====================");

        //获取类的构造器
        Constructor[] constructors = c1.getConstructors();   //只能获取public的构造器
        System.out.println(Arrays.toString(constructors));
        constructors = c1.getDeclaredConstructors();         //获取本类的所有构造器
        System.out.println(Arrays.toString(constructors));
        //获取指定的构造器
        Constructor constructor = c1.getDeclaredConstructor(int.class, String.class);
        System.out.println(constructor);
    }
}

class User{
    public int size;
    private int age;
    private String name;

    public User() {
    }

    public User(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;
    }
}
1.6:动态创建对象执行方法
 public static void main(String[] args) throws Exception {
        Class c1 = User.class;

        //调用newInstance 构造对象.本质是调用了类的无参构造
        User user = (User) c1.newInstance();
        System.out.println(user);

        //当类中没有无参构造时
        Constructor constructor = c1.getDeclaredConstructor(int.class, String.class);
        user = (User) constructor.newInstance(1,"张三");
        System.out.println(user);

        //调用类中方法
        user.setAge(10);
        System.out.println(user);
        //使用反射掉用类中方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke : 激活的意思
        setName.invoke(user, "李四");
        System.out.println(user);

        //通过反射操作属性
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性, 我们需要    打开访问权限   暴力反射
        name.setAccessible(true);
        name.set(user,"王五");
        System.out.println(user.getName());
        
        Method eat = c1.getDeclaredMethod("eat");
        eat.setAccessible(true);
        eat.invoke(user);
    }
1.7:反射获取注解信息
 public static void main(String[] args) throws Exception {
        Class c1 = TableUser.class;
        //获取注解.获得了类上的注解  
        Annotation[] annotations = c1.getAnnotations();
        System.out.println(Arrays.toString(annotations));

        //获得类中字段上的注解
        Field id = c1.getDeclaredField("id");
        Annotation[] annotations1 = id.getAnnotations();
        System.out.println(Arrays.toString(annotations1));
        //获取指定注解中的值
        FieldAnnotation fieldAnnotation = id.getAnnotation(FieldAnnotation.class);
        System.out.println(fieldAnnotation.columnName());
        System.out.println(fieldAnnotation.type());

        //获取指定注解
        Annotation annotation = c1.getAnnotation(TableAnnotation.class);
        System.out.println(annotation);
    }
}

@TableAnnotation("db_user")
@Data
class TableUser{
    @FieldAnnotation(columnName = "id",type = "int")
    private int id;
    @FieldAnnotation(columnName = "name",type = "varchar")
    private String name;
}

//Target表示我们的注解可以用在那些地方
@Target(value = ElementType.TYPE)
//Retention 表示我们的注解在什么地方还有效
@Retention(value = RetentionPolicy.RUNTIME)
@interface TableAnnotation{
    String value();
}

@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface FieldAnnotation{
    String columnName();
    String type();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值