Java注解和反射

注解

  • Annotation的作用:
    • 不是程序本身,可以对程序作出解释(这一点和注释(comment)没什么区别)
    • 可以被其他程序(例如:编译器等)读取
  • Annotation的格式
    • @注释名,还可以添加一些(参数值)
  • Annotation在哪里使用
    • 我们可以在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

内置注解

  • @Override
  • @Deprecated 不推荐程序员使用,或者存在更好的方式
  • @SuppressWarnings(“all”)

元注解

  • 元注解(meta-annotation)的作用就是负责注解其他注解
    • @Target
    • @Retention(SOURCE<CLASS<RUNTIME)
    • @Documented
    • @Inherited
@MyAnnotation
public class Demo2 {
    
    @MyAnnotation
    public void test(){
        
    }
}
//@Target 表示我们的注解可以用在哪些地方
//@Retention 表示我们的注解在什么地方还有效
//@Documented 表示是否将我们的注解生成在Javadoc中
//@Inherited 子类可以继承父类的注解
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation{
    
}

自定义注解

  • public @interface 注解名{定义内容}
  • 其中的每一个方法实际上声明了一个配置参数
  • 方法的名称实际上就是参数的名称
  • 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value
  • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值
//自定义注解
public class Demo3 {
    //注解可以显示赋值,如果没有默认值,必须赋值
    @MyAnno(name = "szx",schools = {"hd","hlg"},age = 18)
    public void test(){
        
    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno{
    //注解的参数:参数类型 参数名();
    String name() default "";
    int age() default 0;
    int id() default -1;//如果默认值-1代表不存在
    String[] schools();
}

反射机制

  • Reflection是Java被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
  • 正常方式:引入需要的“包类”名称–>通过new实例化–>取得实例化对象
  • 反射方式:实例化对象–>getClass()方法–>得到完整的“包类”名称
  • 优点:
    • 可以实现动态创建对象和编译,体现出很大灵活性
  • 缺点:
    • 对性能有影响

Class类

  • Class本身也是一个类
  • Class对象只能由系统建立对象
  • 一个加载的类在JVM中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个Class实例所生成
  • 通过Class可以完整得到一个类中的所有被加载的结构
  • Class类是Reeflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class类
  • 获取Class类实例:
    • 通过调用类.class
    • 利用对象调用getClass()方法获取该对象的Class实例
    • 使用Class类的静态方法forName(),用类的名字获取一个Class实例(static Class forName(String className) ),这种方式灵活性最高,根据类的字符串全名即可获取Class实例,可以动态加载类,框架设计经常用到
public class Demo5 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是:"+person.name);

        Class<? extends Person> c1 = person.getClass();
        Class<?> c2 = Class.forName("com.annotation.Student");
        Class<Student> c3 = Student.class;
        //获得父类类型
        Class<?> superclass = c1.getSuperclass();
        System.out.println(superclass);
    }
}
public class Demo7 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class<?> c1 = Class.forName("com.annotation.User");

        //获得类的名字
        System.out.println(c1.getName());
        System.out.println(c1.getSimpleName());
        //获得类的属性
        Field[] fields1 = c1.getFields();//只能找到public属性
        Field[] fields = c1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);
        System.out.println("--------------------------------------------------");
        //获得类的方法
        Method[] declaredMethods = c1.getDeclaredMethods();//获得本类的所有方法
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("--------------------------------------------------");
        declaredMethods = c1.getMethods();//获得本类及父类的所有public方法
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(setName);
    }
}
  • 通过反射,动态的创建对象
  • Method Constructor,Field都有setAccessible()方法
    • 作用是启动(false)和禁止(true)访问安全检测的开关
    • 默认 false
    • 安全检测会降低效率
  • 普通方式效率比反射快
public class Demo8 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得class对象
        Class<?> c1 = Class.forName("com.annotation.User");
        //构造一个对象
        //User user = (User) c1.newInstance();//本质调用了类的无参构造器
        //System.out.println(user);

        //通过构造器创建对象
//        Constructor<?> constructor = c1.getConstructor(String.class, int.class, int.class);
//        Object user2 = constructor.newInstance("su", 111, 18);
//        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke 激活 (对象,方法值)
        setName.invoke(user3,"szx");
        System.out.println(user3.getName());

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

反射操作泛型

public class Demo9 {

    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 method = Demo9.class.getMethod("test01", Map.class, List.class);
        Type[] gpt = method.getGenericParameterTypes();
        for (Type type : gpt) {
            System.out.println(type);
            if (type instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("真实"+actualTypeArgument);
                }
            }
        }
        Method method1 = Demo9.class.getMethod("test02", null);
        Type type = method1.getGenericReturnType();
        if (type instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}

反射操作注解

//练习反射操作注解
public class Demo10 {
    public static void main(String[] args) throws Exception {
        Class<?> c1 = Class.forName("com.annotation.Stu");
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获得注解value值
        Table table = (Table) c1.getAnnotation(Table.class);
        System.out.println(table.value());
        //获得类指定的注解
        java.lang.reflect.Field f = c1.getDeclaredField("name");
        Field annotation = f.getAnnotation(Field.class);
        System.out.println(annotation.columName());
        System.out.println(annotation.length());
        System.out.println(annotation.type());
    }
}

@Table("db-stu")
class Stu{
    @Field(columName = "id",type = "int",length = 10)
    private int id;
    @Field(columName = "age",type = "int",length = 10)
    private int age;
    @Field(columName = "name",type = "varchar",length = 3)
    private String name;

    public Stu() {
    }

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

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

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
    String columName();
    String type();
    int length();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值