java注解和反射

本文围绕Java注解和反射展开。注解从JDK5.0引入,有内置、自定义和元注解,可对程序作出解释并被其他程序读取。反射则可用于操作对象、泛型和注解。详细介绍了注解的作用、格式、使用场景,以及反射的相关操作案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java注解和反射

1、注解

Annotation是从JDK5.0开始引入的新技术。

• Annotation的作用: – 不是程序本身,可以对程序作出解释。(这一点,跟注释没什么区别) – 可以被其他程序(比如:编译器等)读取。(注解信息处理流程,是注解和注释的重大区别 。如果没有注解信息处理流程,则注解毫无意义)

• Annotation的格式: – 注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如: @SuppressWarnings(value=“unchecked”)。

• Annotation在哪里使用? – 可以附加在package, class, method, field等上面,相当于给它们添加了额外的辅助信 息,我们可以通过反射机制编程实现对这些元数据的访问。

1.1、内置注解

  • @Override
  • – 定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方 法声明打算重写超类中的另一个方法声明。
  • @Deprecated
  • – 定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类 ,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更 好的选择。

@SuppressWarnings

– 定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息 。

– 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参 数值都是已经定义好了的,我们选择性的使用就好了,参数如下:

在这里插入图片描述

– @SuppressWarnings(“unchecked”)

– @SuppressWarnings(value={“unchecked”, “deprecation”})

1.2、自定义注解

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

• 要点:

– @interface用来声明一个注解

• 格式为:

– public @interface 注解名 {定义体} – 其中的每一个方法实际上是声明了一个配置参数。

– 方法的名称就是参数的名称 – 返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)

– 可以通过default来声明参数的默认值。

– 如果只有一个参数成员,一般参数名为value
• 注意:

注解元素必须要有值。我们定义注解元素时,经常使用空字符串、0作为默认值。 也经常使用负数(比如:-1)表示不存在的含义

1.3、元注解

元注解的作用就是负责注解其他注解。 Java定义了4个标准的 meta-annotation类型,它们被用来提供对其它 annotation 类型作说明。

• 这些类型和它们所支持的类在java.lang.annotation包中可以 找到

– @Target

作用: – 用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

在这里插入图片描述

– @Retention

作用: – 表示需要在什么级别保存该注释信息,用于描述注解的生命周期

在这里插入图片描述

– @Documented

注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。

– @Inherited

允许子类继承父类的注解。

类继承关系中@Inherited的作用

类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解

接口继承关系中@Inherited的作用

接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰

类实现接口关系中@Inherited的作用

类实现接口时不会继承任何接口中定义的注解

1.4、案例

//自定义注解
//该注解可以作用在方法、类、接口、注解、枚举类型上
@Target({ElementType.METHOD,ElementType.TYPE})
//该注解的生命周期可以在java程序运行中一直有效,一般自定义注解都是RUNTIME
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface Test01{

    String name() default "aa";
    
    int age() default 1;
    
    String address() default "";
    
    int height() default -1;

}

2、反射

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

1、案例

public class Test01 {

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

        Student student = new Student();

        //通过student实例的getClass()方法获取Class对象
        Class c1 = student.getClass();
        System.out.println(c1.hashCode());

        //通过类的全类名获取Class对象
        Class c2 = Class.forName("AnnotationAndReflex.reflection.Student");
        System.out.println(c2.hashCode());

        //通过具体类的class属性获取Class对象
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

        Class c4 = c1.getSuperclass();
        System.out.println(c4);

        //基本数据类型的包装类可以通过TYPE属性获取Class对象
        Class c5 = Integer.TYPE;
        System.out.println(c5);

    }

}

class Person{

    String name;
    int age;

    public Person() {
    }

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

    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;
    }
}

class Student extends Person{

    public String getPerson(){
        return this.name;
    }

}

在这里插入图片描述

在这里插入图片描述

 public static void main(String[] args) {
        
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器--》扩展类加载器
        ClassLoader loaderParent = systemClassLoader.getParent();
        System.out.println(loaderParent);

        //获取扩展类加载器的父类加载器--》根加载器(C/C++)
        ClassLoader parent = loaderParent.getParent();
        System.out.println(parent);
     
      //查看当前系统的类是由哪个加载器加载的
        ClassLoader classLoader = 	Class.forName("AnnotationAndReflex.reflection.Test03").getClassLoader();
        System.out.println(classLoader);
    }
		Class c = Class.forName("AnnotationAndReflex.reflection.User");
        System.out.println(c.getName());//获取包名加类名
        System.out.println(c.getSimpleName());//获取类名
        Field[] fields = c.getFields();//只能获取本类公共的属性
        for (Field field : fields) {
            System.out.println("正常"+field);
        }
        Field[] declaredFields = c.getDeclaredFields();//可以获取本类私有和公共属性
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        Method[] methods = c.getMethods();//可以获取本类和父类的公共方法
        for (Method method : methods) {
            System.out.println("正常"+method);
        }
        Method[] declaredMethods = c.getDeclaredMethods();//只能获取本类的私有和公共方法
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("正常"+constructor);
        }
        Constructor[] declaredConstructors = c.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        Field age = c.getDeclaredField("age");//获取本类中指定的私有属性
        System.out.println(age);

2、通过反射操作对象

		Class c = Class.forName("AnnotationAndReflex.reflection.User");
        Constructor declaredConstructor = c.getDeclaredConstructor(String.class, int.class);
        //通过反射调用有参构造器
        User user = (User) declaredConstructor.newInstance( "aaa", 10);
        System.out.println(user);
        Method setName = c.getDeclaredMethod("setName", String.class);
        User user1 = new User();
        //通过反射调用对象的公有方法
        setName.invoke(user1, "aaa111");
        System.out.println(user1.getName());

        //通过反射调用对象的私有属性
        Method setName1 = c.getDeclaredMethod("saveName",String.class);
        User user2 = new User();
        //通过反射调用对象的私有方法之前必须关闭安全检测
        setName1.setAccessible(true);
        System.out.println(setName1.invoke(user2, "2121"));

        //通过反射操作对象的私有属性值
        Field name = c.getDeclaredField("name");
        name.setAccessible(true);
        name.set(user2,"gggg");
        System.out.println(user2.getName());

3、通过反射操作泛型

public void test01(Map<User,String> map1, List<String> list){

    }

    public Map<String,User> test02(){
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {

        Method method = Test06.class.getDeclaredMethod("test01", Map.class, List.class);

        //通过反射获取类中方法输入参数的泛型
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            if(genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

        //通过反射获取类中方法返回参数的泛型
        Method method1 = Test06.class.getDeclaredMethod("test02");

        Type genericReturnType = method1.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }

    }

4、通过反射操作注解

public class Test07 {

    public static void main(String[] args) throws NoSuchFieldException {

        Class c = Table1.class;
        Annotation[] annotations = c.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //通过反射获取类注解的值
        TableName annotation = (TableName)c.getAnnotation(TableName.class);
        System.out.println(annotation.value());

        //通过反射获取类中属性注解的值
        Field name = c.getDeclaredField("name");
        ColumnName columnName = name.getAnnotation(ColumnName.class);
        System.out.println(columnName.name());
        System.out.println(columnName.type());
        System.out.println(columnName.length());


    }

}

@TableName("表1")
class Table1{

    @ColumnName(name = "name1",type = "varchar",length = 10)
    private String name;
    @ColumnName(name = "age1",type = "int",length = 10)
    private int age;

    public Table1() {
    }

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

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{

    String value();

}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ColumnName{

    String name();
    String type();
    int    length();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值