毕设学习第五天之Java的注解和反射

注解(Annotation)

Java 注解(Annotation)是一种特殊的语言构造,用于为代码元素(如类、方法、字段等)提供元数据,通常不直接影响程序的逻辑执行。它们可以被编译器、框架或工具解析,用于执行特定操作,如自动化配置、代码生成、验证等。Java 提供了内置的注解(如 @Override@Deprecated)和允许用户自定义注解。注解的处理方式可以在编译时或运行时进行,常用于框架配置、自动化处理和代码文档生成等场景

@注解名 (参数)

注释和注解的区别为注释是给编程人员看的,用于解释代码含义的,而注解是给其他程序看的,用于帮助其他程序读懂该段代码,总结就是注释是帮助人解释代码,注解就是帮助程序解释代码

 

内置注解

内置注解是 Java 提供的预定义注解,它们通常用于编译时检查、代码优化或者提供额外的元数据。Java 标准库中提供了几种常用的内置注解,它们有特定的用途和行为,帮助开发者提高代码的可读性、可维护性并减少错误

Java 的常见内置注解包括 @Override@Deprecated@SuppressWarnings

 以上主要注意@Override 重写注解和@SuppressWarnings 警告镇压注解,而@Deprecated 早已被废弃

元注解

元注解(Meta-Annotation)是用于描述其他注解的注解。它们定义了注解的使用方式和生命周期,通常用于自定义注解时。

  • @Retention:指定注解的保留策略,决定注解在哪个阶段可用。可以是 SOURCE(仅在源码中可见),CLASS(在编译后仍可用,但不会被加载到 JVM 中),RUNTIME(在运行时可用,通常用于反射)。

  • @Target:指定注解可以应用于哪些 Java 元素,如类、方法、字段等。通过 ElementType 枚举进行定义。

  • @Inherited:表示子类可以继承父类的注解,适用于类级别的注解。

  • @Documented:表示注解应包含在 JavaDoc 中,生成的文档会包含该注解的详细信息。

 

package org.example;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 自定义注解,作用于方法和类上,运行时
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    // 注解的参数定义:参数类型 参数名() default 默认值
    String name() default "李华";
    // 默认值 -1 表示不存在
    int age() default -1;
}

反射(Reflection)

 反射是 Java 提供的一种在运行时动态获取类的信息、创建对象、调用方法和访问字段的机制。它通过 Class 类和相关的 API 允许程序在运行时检查和操作类的结构,而无需在编译时明确这些信息。反射广泛应用于框架设计、动态代理和工具开发等领域,但由于性能开销和安全性问题,使用时需要谨慎

动态和静态语言

动态语言是指在运行时可以改变其结构的编程语言,如新增函数、对象或修改已有结构。常见的动态语言有 Python、JavaScript、PHP、C# 等。相比之下,静态语言如 Java、C、C++ 其结构在运行时是不可变的,编译时类型和结构已经确定。然而,Java 也具有一定的动态性,尤其通过反射机制,能够在运行时进行一定的结构调整,具备类似动态语言的一些特性

Java作为一门特殊的静态语言,通过反射能表现出准动态性

Java中万物皆对象,描述Java程序编译生成的Class文件的对象就是Class类对象,因此Class文件,成员变量,成员方法和构造方法的对于的类为Class类,Field类,Method类和Constructor类

类的加载机制:父类对象->子类对象->main方法->静态成员->反射

正常是先定义类,然后通过类去实例化对象,而反射机制允许通过对对象的解析反推出类的结构,而无需一开始定义类的结构

package org.example;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class Student{
    private String name = "李华";
    private int age = 18;

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

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

    public Student() {
    }

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

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Student stu = new Student();
        Class c = null;
        // 常见四种获取class类的方法
        c = stu.getClass();
        // org.example.Student为类的全限定名
        c = Class.forName("org.example.Student");
        c = Student.class;
        // 反射构造方法
        // 获取所有的非私有构造方法
        // getDeclared*,获取所有的包括私有的,如getDeclaredConstructors,获取所有的构造方法
        Constructor[] cs = c.getConstructors();
        for (Constructor ctor : cs) {
            System.out.println(ctor);

        }
        // 无参构造
        Constructor ctor = c.getConstructor();
        // 有参构造
        ctor = c.getConstructor(String.class,int.class);
        // 通过构造方法创建实例
        Student s = (Student) ctor.newInstance("小明",18);
        System.out.println(s.toString());
        // 获取所有成员方法包括父类的,非私有
        Method[] ms = c.getMethods();
        for (Method m : ms) {
            System.out.println(m);
        }
        // 获取指定方法,传入方法名和参数,用于区分不同方法和重载方法
        Method m = c.getMethod("setName", String.class);
        // 执行对应的方法,传入一个对象和方法参数
        m.invoke(s,"李雷");
        System.out.println(s.toString());
        Field[] fs = c.getFields();
        // 获取所有成员变量
        for (Field f : fs) {
            System.out.println(f);
        }
        // 获取指定成员变量
        Field f = c.getDeclaredField("name");
        // 运行操作私有成员变量
        f.setAccessible(true);
        f.set(s,"韩梅梅");
        System.out.println(s.toString());

    }
}
posted @ 2025-01-16 17:39  突破铁皮  阅读(21)  评论(0)    收藏  举报