(Java学习过程)注解和反射

注解和反射

1、注解

什么是注解?

annotation在哪里使用?

我们可以通过附加在package,class,method,field上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

1.1、内置注解

@Override:定义在 java.lang.Override 中,此注解只适用于修辞方法,表示一个方法声明打算重写超类的另一个方法声明。

@Deprecated:定义在java.lang.Deprecated中,此注解可以用于修辞方法,属性、类,表示不鼓励程序员使用这样的元素,通常是因为他们危险或者有更好的选择

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

与前两个注释不同,你需要添加一个参数才能正常使用,这些参数都是已经定义好的

  • SuppressWarnings(“all”)
  • SuppressWarnings(“unchecked”)
  • SuppressWarnings(value={"unchecked,“deprecation”})

1.2、元注解

  • 元注解的作用就是负责注解其他注解,java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型做说明
  • 这些类型和他们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)
    • @Target:用于描述注解的使用范围(也就是被描述的注解可以用在什么地方)
    • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
      • (SOURCE<CLASS<RUNTIME)
    • @Documented:说明该注释将被包含在javadoc中
    • @Inherited:说明子类可以继承父类中的注解

1.3、自定义注解

  • 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
  • 分析:
    • @interface用来声明一个注释,格式:public @ interface 注解名{定义内容}
    • 参数格式:类型 参数名();
    • 其中的每一个方法实际上是声明了一个配置参数
    • 方法的名称就是参数的名称
    • 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)
    • 可以通过default来声明参数的默认值
    • 如果只有一个参数成员,一般参数名为value
    • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值

2、反射

2.1、动态语言和静态语言

  • 动态语言:

    • 是一类在运行时可以改变其结构的语言:例如新的对象,函数,甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗来说就是在运行时代码可以根据某些条件改变自身结构。
    • 主要动态语言:Object-C,C#,JavaScript,PHP,Python等
  • 静态语言:

    • 运行时结构不可变的就是静态语言,eg :Java,C,C++
    • Java不是动态语言,但是它可以称为准动态语言。也就是Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程的时候更加灵活

2.2、Java Reflection

  • Reflection (反射)是Java被视为动态语言的关键,反射机制允许程序在执行期间借助于 Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
  • 加载完类之后,在内存的方法区中就产生了一个Class类型的对象(一个类只要一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过镜子看到类的结构,所以,我们形象的称之为反射

正常方式: 引入需要的包类名称----->通过new实例化------->取得实例化对象

反射方式:实例化对象 ------->getClass()方法----->取得完整的包类名称
请添加图片描述

2.3、反射机制提供的功能

请添加图片描述

2.4、反射的优缺点

请添加图片描述

2.5、反射相关的API

请添加图片描述

2.6、Class类

请添加图片描述

//一个类在内存中只有一个Class对象
//一个类被加载后,类的整个结构都会被封装在Class对象中在这里插入代码片
//通过反射获得类的class对象
            Class c1 = Class.forName("com.wu.pojo.User");

请添加图片描述

请添加图片描述

请添加图片描述

请添加图片描述

2.7、Java内存分析

请添加图片描述

2.8、类的加载过程

请添加图片描述

2.9、类的加载与ClassLoader的理解

请添加图片描述

请添加图片描述

package com.wu.test;
//测试类加载
public class Test2 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);
    }
    /*
* 1、加载到内存,回产生一个Class对象
* 2、链接,结束后m=0
* 3、初始化<clinit>(){
*       System.out.println("A静态代码块初始话");
        m=300;
*       m = 100;
* }
*       m=100;
* */

}
class A{
    static {
        System.out.println("A静态代码块初始话");
        m=300;
    }
    static int m = 100;
    public A(){
        System.out.println("A无参构造初始化");
    }
}

2.10、分析类初始化

请添加图片描述

package com.wu.test;
//测试类什么时候初始化
public class Test3 {
    static {
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //1 主动引用会发生类的初始化
        //Son son = new Son();
        // 反射 也会产生类的初始化
        //Class aClass = Class.forName("com.wu.test.Son");

        //2 被动引用
        //System.out.println(Son.b); // 子类调用父类的静态变量时,子类不会被加载
        //Son[] arr = new Son[3]; // 数组不会触发类的初始化,之后加载Main
        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;
}

2.11、类加载器的作用

请添加图片描述

请添加图片描述

2.12、创建运行时类的对象

请添加图片描述

package com.wu.test;

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

public class Test5 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class<?> c1 = Class.forName("com.wu.pojo.User");
        //Class的方法
        //获得类名
        System.out.println(c1.getName());    //全类名  包名+类名
        System.out.println(c1.getSimpleName()); //简单名   类名

        //获得类属性
        System.out.println("==================================");
        Field[] fields = c1.getFields();   //只能找到public属性
        for (Field field : fields) {
            System.out.println(field);    //没有打印出来
        }
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);    //找到全部的属性
        }
        System.out.println("========================");
        System.out.println(c1.getDeclaredField("id"));
        System.out.println("================");
        //获得类方法
        for (Method method : c1.getMethods()) {
            System.out.println("正常的:"+method);  //获得本类和父类的所有public方法
        }
        System.out.println("============================");
        for (Method declaredMethod : c1.getDeclaredMethods()) {
            System.out.println("其他的:"+declaredMethod);   //获得本类的所有方法(包括私有方法)
        }

        //获得指定方法
        System.out.println(c1.getMethod("getName",null));
        System.out.println(c1.getMethod("setName", String.class));

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

        //获得类构造器
        for (Constructor<?> constructor : c1.getConstructors()) {
            System.out.println(constructor);
        }
        //获得指定构造器
        System.out.println(c1.getConstructor(String.class, int.class, int.class));
        System.out.println(c1.getConstructor(null));


    }
}

2.13、动态创建对象执行方法

请添加图片描述

请添加图片描述

请添加图片描述

请添加图片描述

package com.wu.test;

import com.wu.pojo.User;

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

public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class<?> c1 = Class.forName("com.wu.pojo.User");
        //User user = (User) c1.newInstance();  //本质上调用了无参构造器

        //通过构造器创建对象
        Constructor<?> constructor = c1.getConstructor(String.class, int.class, int.class);
        User user = (User) constructor.newInstance("吴佳俊", 1, 21);
        System.out.println(user);
        System.out.println("========================");
        //通过反射调用方法
        User user1 = (User) c1.newInstance();
        //通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user1,"wujiajun");  //激活方法(对象,方法的参数)
        System.out.println(user1.getName());
        System.out.println("===========================");
        //通过反射操作属性
        //不能直接操作私有属性            我们需要关闭安全检测:  方法/属性.setAccessible(true)
        User user2 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name"); // 权限不够
        name.setAccessible(true); // 关闭方法或者属性的权限访问
        name.set(user2,"吴佳俊2");
        System.out.println(user2.getName());
    }
}

2.14、反射和普通的性能分析

package com.wu.test;

import com.wu.pojo.User;

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

//分析反射和普通性能
public class Test7 {
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test1();
        test2();
        test3();
    }
    //普通方式调用
    public static void test1(){
        User user = new User();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("普通方式执行10亿次耗时:"+(endTime-startTime)+"ms");
    }

    //反射方式调用
    public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class<User> userClass = User.class;
        Method getName = userClass.getDeclaredMethod("getName", null);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式执行10亿次"+(endTime-startTime)+"ms");
    }

    //反射方式调用(关闭安全权限检查)
    public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class<User> userClass = User.class;
        Method getName = userClass.getDeclaredMethod("getName", null);
        getName.setAccessible(true);//关闭检查
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式调用(关闭安全权限检查)执行10亿次"+(endTime-startTime)+"ms");
    }
}

请添加图片描述

2.15、获得泛型信息【难】

请添加图片描述

2.16、反射获取注解信息

  • getAnnotations
  • getAnnotation

请添加图片描述

package com.wu.test;

import java.lang.annotation.*;

//反射操作注解
public class Test9 {
    public static void main(String[] args) throws NoSuchFieldException {
        Class<Student2> c1 = Student2.class;
        //通过反射获取注解
        for (Annotation annotation : c1.getAnnotations()) {
            System.out.println(annotation);
        }
        //获得注解value的值
        tableKuang annotation = c1.getAnnotation(tableKuang.class);
        System.out.println(annotation.value());

        //获得类指定的注解
        java.lang.reflect.Field field = c1.getDeclaredField("id");
        Field fieldAnnotation = field.getAnnotation(Field.class);
        System.out.println(fieldAnnotation.columnName());
        System.out.println(fieldAnnotation.type());
        System.out.println(fieldAnnotation.length());
    }
}
@tableKuang("db_student")
class Student2{
    @Field(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Field(columnName = "db_age",type = "int",length = 10)
    private int age;
    @Field(columnName = "db_name",type = "String",length = 10)
    private String name;

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

    public Student2() {
    }

    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 tableKuang{
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
    String columnName();
    String type();
    int length();
}

请添加图片描述



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值