java中的注解和反射

1什么是注解

  (1)定义:Annotation是从Jdk5.0开始后才引入的,不是程序本身,可以对程序作出解释。可以被其他程序读取

  (2)注解的使用:可以在package,class,method,field上面使用,相当于可以获得辅助的功能

2java中常用的内置注解

public class testAnnoaction extends Object {

    //重写的注解
    @Override
    public String toString() {
        return super.toString();
    }
    //加了这个注解,表示这个方法不推荐使用
    @Deprecated
    public void test(){

    }
    //镇压警告的功能,加上这个注解,可以将镇压警告进行消除
    @SuppressWarnings("all")
    public void testTwo(){
        ArrayList<Object> list = new ArrayList<>();

    }

}

3元注解

  (1)作用:负责注解其他注解,java中定义了4个标准的注解,他们给用来给其他的注解annotation做说明

  (2)@Target,@Rtention,@Documented,@inherited

  (3)Target:用来描述注解的使用范围。Retention:表示在什么级别保存该注解的信息,用于描述注解的生命周期(SOURCE<CLASS<RUNTIME)。Documented:说明注解将被包含在doc中。inherited:说明子类可以继承父类的注解

  (4)测试元注解

public class TestOther {

    @Myannotation
    public void method(){

    }
}
//定义注解可以使用在方法上面 Target:表示注解可以用在哪些地方
@Target(value = ElementType.METHOD)
//定义注解表示在什么阶段有效   RetentionPolicy:RUNTIME>CLASS>SOURCE
@Retention(value = RetentionPolicy.RUNTIME)
//表示是否将我们的注解生成在javaDoc中
@Documented
//表示子类可以继承父类的注解
@Inherited
@interface Myannotation{
    
}

4自定义注解

public class SelfAnnotation {
    /*
     * 1:注解可以显示赋值,如果没有默认值,我们必须要给赋值
     * 2:注解的参数顺序没有关系
     */
    @MySelfAnnotation()
    @MySelfOtherAnnotation("value")
    public void testMethod(){

    }

}

//表示注解可以在方法和类上面定义
@Target({ElementType.METHOD,ElementType.TYPE})
//表示注解在运行时有效
@Retention(RetentionPolicy.RUNTIME)
@interface MySelfAnnotation{

    //定义注解的参数:参数类型+参数名()
    String name() default "";

    int age() default 0;

    int id() default -1;

    String[] schools() default{"重庆大学,清华大学"};

}
//表示注解可以在方法和类上面定义
@Target({ElementType.METHOD,ElementType.TYPE})
//表示注解在运行时有效
@Retention(RetentionPolicy.RUNTIME)
@interface  MySelfOtherAnnotation{
    //如果注解中只有一个值,在使用注解的时候,参数可以不加名称
    String value();


}

java中的反射(将java不是动态语言可以变成动态语言,但是不安全)

1认识动态语言和静态语言

  (1)动态语言:在运行的时候可以改变其结构的语言

  (2)静态语言:与动态语言相比,运行时结构不可变的

2Reflection(缺点:极大地消耗性能)

  (1)反射是java被视为动态语言的关键,反射机制可以允许程序在执行期间借助ReflectionApi获得类中的任何信息

  (2)反射的原理1比较

  (3)获得反射的对象

    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象,一个类被加载后,整个类的结构都会在class中
        Class aClass = Class.forName("reflection.User");
        System.out.println(aClass);
    }

  (4)获取class对象的几种方式

        //1:通过对象获得
        Class<? extends Person> c1 = person.getClass();
        //2:用forName获得
        Class<?> c2 = Class.forName("reflection.Student");
        //3:通过类名获得(比较高效的使用)
        Class<Student> c3 = Student.class;
        System.out.println(c1.hashCode());//21685669
        System.out.println(c2.hashCode());//21685669
        System.out.println(c3.hashCode());//21685669
        //4:基本内置类型的包装类都有一个type属性(不常用)
        Class<Integer> c4 = Integer.TYPE;
        //获取父类的类型
        Class<?> superclass = c1.getSuperclass();

   (5)哪些类有自己的class对象

  (6)获取类的运行时的一些结构

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

        Class aClass = Class.forName("annotation.User");
        //获取类的名字
        String className = aClass.getName();
        System.out.println(className);
        System.out.println("=================================");
        //获得类的属性
        Field[] fields = aClass.getFields();//只能找到public的属性
        Field name = aClass.getDeclaredField("name");
        Field[] declaredFields = aClass.getDeclaredFields();//获取全部属性包括私有的
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("===================================");
        //获取类的方法
        Method[] methods = aClass.getMethods();//获取本类和父类的所有方法
        for (Method method : methods) {
            System.out.println("正常的"+method);
        }
        Method[] declaredMethods = aClass.getDeclaredMethods();//获取本类的所有方法(包括private)
        for (Field field : declaredFields) {
            System.out.println("declare"+field);
        }
        //获取指定的方法
        Method getName = aClass.getMethod("getName", null);
        System.out.println(getName);
        
    }

    (7)运用获取的属性和方法执行

public class User {

    private String name;
    public String userName;

    public void getName(String params,String params1) {
        System.out.println("我执行了这个方法"+params+","+params1);
    }
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> aClass = Class.forName("annotation.User");
        //通过反射创建一个对象
        User user =(User) aClass.newInstance();
        //通过反射调用普通方法
        Method getName = aClass.getDeclaredMethod("getName", String.class,String.class);
        //调用了getName这个方法(第一个参数是对象,第二个参数是方法中的参数)
        getName.invoke(user,"xst","xxx");
    }
}

 

    (8)比较普通创建对象和用反射创建对象的性能问题

public class TestTime{
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Student.test01();
        Student.test02();
        Student.test03();


    }


}


class Student{

    public String name;

    public  void getName(){
    }

    //通过对象的方法调用
    public static void test01(){
        Student student = new Student();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            student.getName();
        }
        long  endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+"毫秒");//2毫秒
    }
    //反射的方式调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //通过对象的方法调用
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();
        Method getName = aClass.getDeclaredMethod("getName");
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(student,null);
        }
        long  endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+"毫秒");//909毫秒
    }
    //关闭检测(可以提高速度 但是不安全 关闭检测后可以访问到私有的方法)
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //通过对象的方法调用
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();
        Method getName = aClass.getDeclaredMethod("getName");
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.setAccessible(true);
            getName.invoke(student,null);
//            student.getName();
        }
        long  endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+"毫秒");//493毫秒
    }
}
posted @ 2022-08-23 10:23  程序员XiaoXie  阅读(148)  评论(0)    收藏  举报