首页 > 编程语言 > 详细

JAVA:注解和反射

时间:2021-05-04 23:38:54      阅读:33      评论:0      收藏:0      [点我收藏+]

注解

注解简介

  • Annotation
  • 可以被其他程序读取
  • 格式:@+注稀名
package com.xiaobai.annotation;

public class lesson01 {
    @Override//这个就是注解,说明重写
    public String toString() {
        return super.toString();
    }
}

内置注解

  • @Override:重写
  • @Deprecated:不鼓励使用,通常是因为存在危险或者更好的选择
  • @SuppressWarnings:用来抑制编译时的警告信息
    • @SuppressWarnings("all")
    • @SuppressWarnings("unchecked")
    • @SuppressWarnings("value={"unchecked","deprecation"}")
    • 等等

元注解

  • 元注解的作用就是负责注解其他注解,java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
  • @Target.@Retention.@Documented.@Inherited
    • @Target:用于描述注解的使用范围
    • @Retention:标识需要在什么级别保存该注稀信息,用于描述注解的生命周期
    • @Documented:说明该注解被包含在javadoc中
    • @Inherited:卓明子类可以继承父类中的该注解
package com.xiaobai.annotation;

import java.lang.annotation.*;

public class Test02 {


}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
@Inherited
@interface Myannotation{

}

自定义注解

package com.xiaobai.annotation;

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

public class Test03 {
    @Myannotation2(name = "注解")
    public  void test(){}
    @Myannotation3("注解2")
    public  void test2(){}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Myannotation2{
    //注解参数:参数类型+参数名+()
    String name();
    int age() default 0;//默认为0传参数
    int id() default -1;//如果默认为-1,表示不存在
    String[] schools() default {"冬季","夏季"};
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Myannotation3{
    String value();//单个注解,可以用value表示,使用该注解时,可以不传参数名字
}

反射

反射简介

  • 将java静态语言变为了准动态语言
  • 获取对象信息
  • Reflection
package com.xiaobai.reflection;

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


        Class<?> aClass = Class.forName("com.xiaobai.reflection.Test01");
        System.out.println(aClass.getClass());
        Class<?> c1 = Class.forName("com.xiaobai.reflection.Test01");
        Class<?> c2 = Class.forName("com.xiaobai.reflection.Test01");
        Class<?> c3 = Class.forName("com.xiaobai.reflection.Test01");
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());

    }

}

class  User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name=‘" + name + ‘\‘‘ +
                ", id=" + id +
                ", age=" + age +
                ‘}‘;
    }


}

得到Class类的几种方式

  • 通过对象
  • 通过forname
  • 通过类名
  • 基本内置类型的爆装备都有一个TYPE属性
  • 获得父类类型
package com.xiaobai.reflection;

public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();

        //通过对象获取
        Class c1 = student.getClass();

        //通过forname获取类对象
        Class c2 = Class.forName("com.xiaobai.reflection.Student");

        //通过类名

        Class c3 = Student.class;

        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());

        //基本类型内置类获取
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        //获取父类
        Class c5 = c1.getSuperclass();
        System.out.println(c5);


    }
}


class  Person{
    public String name;
    public int id;
    public int age;

    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name=‘" + name + ‘\‘‘ +
                ", id=" + id +
                ", age=" + age +
                ‘}‘;
    }
}

class Student extends Person{
    public Student(){
        this.name = "学生";
    }
}

所以类型的Class

package com.xiaobai.reflection;

import java.lang.annotation.ElementType;

public class Test03 {
    public static void main(String[] args) {
        Class c1 = Object.class;
        Class c2 = Comparable.class;
        Class c3 = String[].class;
        Class c4 = int[][].class;
        Class c5 = Override.class;
        Class c6 = ElementType.class;
        Class c7 = Integer.class;
        Class c8 = void.class;
        Class c9 = Class.class;
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        int[] a =new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

类加载内存分析

详细讲解见狂神说JAVA视频

技术分享图片
技术分享图片
技术分享图片

类的初始化

  • 类的主动引用:一定会初始化
    • 当虚拟机启动,先初始main方法所在的类
    • new一个类的对象
    • 调用类的静态成员和静态方法
    • 反射调用
    • 初始化一个类,父类没有被初始化,先初始化父类
  • 类的被动引用:不会发生类的初始化
    • 当访问一个静态域时,只有真正声明这个域的类才会被初始化,如,通过子类调用父类的静态常量,子类不会被初始化
    • 通过数组定义类的引用,不会触发此类的初始化
    • 引用常量不会触发此类的初始化
package com.xiaobai.reflection;

public class Test04 {
    static {
        System.out.println("main被加载");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //1.主动引用
        //Son son = new Son();
        //2.反射
        //Class.forName("com.xiaobai.reflection.Son");
        //3.调用静态方法
        //System.out.println(Son.m);
        //不会初始化
        //1.通过子类引用父类静态变量,子类不会加载
        //System.out.println(Son.b);
        //2.引用常量
        //System.out.println(Son.M);
        //3.通过数组定义类引用
        Son[] arry = new Son[5];
    }

}



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

类的加载器

  • 根加载器--无法获取
  • 扩展类加载器
  • 系统类加载器
  • 双亲委派机制:如果在系统类自己写的jar包,在扩展或者根加载器的目录下有相同的jar包,自己写的无效
package com.xiaobai.reflection;

public class Test05 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
        //获取系统类加载器的父类--扩展加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);
        //获取扩展类加载器的父类加载器--根加载器
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);
        //测试当前类的加载器是哪个
        ClassLoader classLoader = Class.forName("com.xiaobai.reflection.Test05").getClassLoader();
        System.out.println(classLoader);
        //测试JDK内置类是哪个加载器加载的
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);
        //获取系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
    }
}

获取类的结构

package com.xiaobai.reflection;

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

public class Test06 {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        User user = new User();
        Class c1 = user.getClass();
        //1.获取类的名字
        String simpleName = c1.getSimpleName();//获取类名
        System.out.println(simpleName);
        String name = c1.getName();//获取包名+类名
        System.out.println(name);
        //2.获取类的属性
        Field[] fields = c1.getFields();//获取类的pbulic的属性
        for (Field field : fields) {
            System.out.println("获取公开属性:"+field);
        }
        Field[] declaredFields = c1.getDeclaredFields();//获取类的全部属性
        for (Field declaredField : declaredFields) {
            System.out.println("获取全部属性:"+declaredField);
        }
        //获取指定属性
        Field sex = c1.getField("sex");
        System.out.println("获取指定公共属性"+sex);
        Field id = c1.getDeclaredField("id");
        System.out.println("获取指定全部属性"+id);
        //3.获取类的方法
        Method[] methods = c1.getMethods();//获取本类及父类全部的public的方法
        for (Method method : methods) {
            System.out.println(method);
        }
        Method[] declaredMethods = c1.getDeclaredMethods();//获取本类全部方法
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        Method setName = c1.getMethod("setName", String.class);//获取指定本类及父类全部方法
        System.out.println(setName);
        Method test001 = c1.getDeclaredMethod("test001",null);//获取指定本类的方法
        System.out.println(test001);

        //获得指定构造器
        Constructor[] constructors = c1.getConstructors();//获取公开构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();//获取全部构造器
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class,int.class);//获取指定构造器
        System.out.println(declaredConstructor);
    }
}

动态创建对象

package com.xiaobai.reflection;

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

public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.xiaobai.reflection.User");
        //构造一个对象
        User user = (User) c1.newInstance();//调用了无参构造器
        System.out.println(user);
        //通过有参构造器构造
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class, int.class);
        User user2 = (User) constructor.newInstance("哈哈", 2, 3, 4);
        System.out.println(user2);
        //通过反射调用方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        User user3 = (User) c1.newInstance();
        //invoke:激活
        //(对象,“方法的值”)
        setName.invoke(user3,"憨憨");
        System.out.println(user3);
        //通过反射操作属性
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //私有属性修改会报错,使用setAccessible方法关闭安全检测
        name.setAccessible(true);
        name.set(user4,"喵喵");
        System.out.println(user4);

    }
}

使用反射创建对象,和普通方式创建对象的性能对比

  • 两者相差50倍左右
  • 关闭安全检测和不关闭相差2倍左右
package com.xiaobai.reflection;

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

public class Test08 {
    //普通方式调用
    public static void test01(){
        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 test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.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 test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.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");
    }

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

获取泛型信息

详见狂神说JAVA

获取注解

package com.xiaobai.reflection;

import java.lang.annotation.*;

public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.xiaobai.reflection.Student2");
        //获得反射注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);

        }
        //获得指定主角的值
        Table annotation = (Table)c1.getAnnotation(Table.class);
        String value = annotation.value();
        System.out.println(value);

        java.lang.reflect.Field name = c1.getDeclaredField("name");
        Field annotation1 = name.getAnnotation(Field.class);
        System.out.println(annotation1);
        System.out.println(annotation1.columnName());
        System.out.println(annotation1.type());
        System.out.println(annotation1.length());
    }

}
@Table("db.student")
class Student2{
    @Field(columnName = "ID",type = "int",length = 10)
    private int id;
    @Field(columnName = "AGE",type = "int",length = 10)
    private int age;
    @Field(columnName = "NAME",type = "varchar",length = 3)
    private String name;

    public Student2() {
    }

    public Student2(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 "Student2{" +
                "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 columnName();
    String type();
    int length();
}

JAVA:注解和反射

原文:https://www.cnblogs.com/novice77/p/14730236.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!