注解和反射笔记

1 篇文章 0 订阅
1 篇文章 0 订阅

一、注解

1.1 注解入门

Annonation(jdk5开始引入)的作用:不是程序本身,可以对程序作出解释,可以被其它程序读取,并且可以起到检查和约束的作用。
格式:@xxx 可以添加参数 value=xxx

元注解:负责注解其它注解。
4个标准的meta-annonation类型:@Target、@Retention、@Documented、@Inherited

@Target:表示我们的注解可以用在哪些地方
@Retention:表示我们的注解在什么地方还有效(RUNTIME>CLASS>SOURCES)
@Documented:表示是否将我们的注解生成在javadoc中
@Inherited:子类可以继承父类的注解

自定义注解:@interface,自动继承了java.lang.annotation.Annotation接口

格式:public @interface 注解名{定义内容}

注解的参数:参数类型 + 参数名 + ()

如果只有一个值的话,可以命名为value(),这样上面调用到注解的时候可以不用写参数名

//自定义注解
public class Test01 {

    @MyAnnotation(name = "你好",schools = "北大")
    public void test02(){

    }

}

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{

    String name() default "";

    int age() default 0;

    int id() default -1;

    String[] schools();
}

二、反射

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

Class c = Class.forName("java.lang.String");

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Class类

在这里插入图片描述

Class类常用方法

在这里插入图片描述

public class Test01 extends Object {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //通过反射来获取类的class对象
        Class c1 = Class.forName("com.java.reflection.User");
        Method m1 = c1.getMethod("getAge");
        System.out.println(c1);//class com.java.reflection.User
        System.out.println(m1);//public int com.java.reflection.User.getAge()

        //一个类在内存中只有一个class对象,其hashCode相同
        //一个类被加载后,类的整个结构都会被封装在class对象中
        Class c2 = Class.forName("com.java.reflection.User");
        Class c3 = Class.forName("com.java.reflection.User");
        System.out.println(c2.hashCode());//21685669
        System.out.println(c3.hashCode());//21685669
    }
}

//实体类
class User{
    private int id;
    private String name;
    private int age;

    public User() {

    }

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

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);//A类静态代码块初始化    A类的无参构造初始化  100

        /*
            1.加载到内存,会产生一个类对应class对象
            2.链接,链接结束后 m=0
            3.初始化(static代码会被合并)
                <clinit>(){
                    System.out.println("A类静态代码块初始化");
                    m = 300;
                    m = 100;
                }
         */
    }

}

class A{

    static{
        System.out.println("A类静态代码块初始化");
        m = 300;
    }
    static int m = 100;

    public A() {
        System.out.println("A类的无参构造初始化");

    }
}

类加载内存分析

在这里插入图片描述

类的加载过程

在这里插入图片描述

类的加载与ClassLoader的理解

在这里插入图片描述

什么时候发生类的初始化

在这里插入图片描述

package com.java.reflection;

public class Test05 {
    static {
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //1.主动引用
        Son son = new Son();
        //2.反射也会产生主动引用
        Class.forName("com.java.reflection.Son");
        /*
        Class c1 = Son.class;
         */
        //不会产生类的引用的方法
        System.out.println(Son.b);//调用父类中的值,没有引起子类的初始化
        Son[] array = new Son[5];//数组定义类引用不会引起类的初始化
        System.out.println(Son.M);//常量在链接阶段就存入了调用类的常量池中了
    }
}

class Father{
    static int b = 2;

    static{
        System.out.println("父类被加载");
    }
}

class Son extends Father{
    static{
        System.out.println("子类被加载");
        m = 300;
    }
    static int m = 100;

    static final int M = 1;
}

类加载器的作用

在这里插入图片描述
在这里插入图片描述

package com.java.reflection;

public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException {

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

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

        //获取扩展类的父类加载器-->根加载器(c++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);//null

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("com.java.reflection.Test06").getClassLoader();
        System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

        //测试jdk内部类是哪个加载器加载的
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);//null 
    }
}

Class对象之后

在这里插入图片描述

调用指定方法所需注意

在这里插入图片描述

setAccessible()

在这里插入图片描述

public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得class对象
        Class c1 = Class.forName("com.java.reflection.User");

        //构造一个对象
        User user = (User)c1.newInstance();
        System.out.println(user);

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User)constructor.newInstance("张三", 1, 18);
        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        //通过反射获取一个方法
        Method setName = c1.getMethod("setName", String.class);

        //invoke : 激活的意思
        //(对象,“方法的值")
        setName.invoke(user3,"SchParis");
        System.out.println(user3.getName());

        //通过反射操作属性
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true)
        name.setAccessible(true);
        name.set(user4, "小李子");
        System.out.println(user4.getName());
    }
}

反射操作泛型

在这里插入图片描述

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

    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 static void main(String[] args) throws NoSuchMethodException {
        Method method01 = Test10.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method01.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);
                }
            }
        }

        System.out.println("============================");

        Method method02 = Test10.class.getMethod("test02", null);
        Type genericReturnType = method02.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}

通过反射操作注解

package com.java.reflection;

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

//通过反射操作注解
public class Test11 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.java.reflection.Student2");

        //通过反射获取注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);//@com.java.reflection.TableTest(value=db_student)
        }

        //获得注解的value的值
        TableTest tableTest = (TableTest)c1.getAnnotation(TableTest.class);
        String value = tableTest.value();
        System.out.println(value);//db_student

        //获得类指定的注解
        Field id = c1.getDeclaredField("id");
        FieldTest annotation = id.getAnnotation(FieldTest.class);
        System.out.println(annotation.columnName());//db_id
        System.out.println(annotation.type());//int
        System.out.println(annotation.length());//10
    }

}

@TableTest("db_student")
class Student2{
    @FieldTest(columnName = "db_id", type = "int", length = 10)
    private int id;
    @FieldTest(columnName = "db_age", type = "int", length = 10)
    private int age;
    @FieldTest(columnName = "db_name", type = "varchar", length = 10)
    private String name;

    public Student2() {
    }

    public Student2(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 "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

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

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

(文章通过狂神说视频总结。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值