栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

注解和反射的作用(注解和反射的关系)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

注解和反射的作用(注解和反射的关系)

注解和反射 注解 Annotation
    JDK5.0开始引入的新技术作用:不是程序本身,可以对程序做出解释,可以被其他程序(编译器)读取格式:@注释名附加在package、class、method、field上面

@Override 适用于修辞方法,表示一个方法声明打算重写父类的另一个方法的声明
@Deprecated 可以用于修辞方法,不鼓励使用这样的元素
@SuppressWarnings() 用来抑制编译时的警告信息,需要添加一个参数才能使用
@SuppressWarnings(“all”)
@SuppressWarnings(“unchecked”)
@SuppressWarnings(value={“unchecked”,“deprecation”})

元注解

作用:负责注解其他注解 4个标准的meta-annotation类型,被用来提供对其他annotation类型做说明
meta-annotation:
@Target:用于描述注解的使用范围
@Retention:表示需要在什么级别保存该注释信息,用于描述注解的声明周期(RUNTIME>CLASS>SOURCE)
@document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的注解

@MyAnnotation
public class demo {
    @MyAnnotation
    public void test(){
    }
}
//Target该注解只能在类、接口、枚举 以及方法上使用
@Target(value = {ElementType.TYPE,ElementType.METHOD})
//Retention该注解在RUNTIME、在CLASS文件、在SOURCE使用
@Retention(value = RetentionPolicy.RUNTIME)
//documented是否将注解声称在javadoc中
@documented
//Inherited 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{
}
自定义注解

使用@interface就可以自定义注解

    @interface用来声明一个注解,格式为public @interface 注解名{}其中的每一个方法实际上是声明了一个参数配置方法的名称就是参数名称返回值类型就是参数类型,返回值只能是基本类型,class、String、enum可以通过default来声明参数的默认值如果只有一个参数成员,一般参数名为value注解元素必须要有值,定义注解元素时,经常使用空字符串,0为默认值
public class demo {
    //注解可以显示赋值,如果没有默认值,必须给注解赋值
    @MyAnnotation(age=18)
    public void test(){
    }
    //参数名为value,可以直接赋值,不用写参数名
    @MyAnnotation2("zzz")
    public void test2() {
    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    //注解的参数:参数类型+参数名+();
    String name() default "";
    int age();
    int id() default -1;//默认值为-1,表示不存在
    String[] hobbies() default {"羽毛球","乒乓球"};
}

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
//如果注解只有一个参数,可以用value命名,这样在使用注解时,参数名可以不写
@interface MyAnnotation2{
    String value();
}
反射机制
    动态语言
    运行时可以改变结构的语言,如新的函数、对象、代码可以被引进,已有的函数可以被删除或者其他结构上的变化,即在运行时代码可以根据某些条件改变自身结构。
    主要动态语言:Object-C、C#、Javascript、PHP、Python静态语言
    运行时不可变的语言,如Java、C、C++
    但是Java可以利用反射机制获得类似动态语言的特性。

Java Reflection,反射机制允许程序在执行期间借助于Reflection API取得任何类的内部消息,并能直接操作任意对象的内部属性及方法
Class c = Class.forName(“java.lang.String”)
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象,这个对象就包含了完整类的结构信息,我们可以通过这个对象看到类的结构。对象就像一面镜子,通过这个镜子可以看到类的结构,所以为反射。

正常方式:引入需要的包类名称——>new进行实例化——>取得实例化对象
反射方式:实例化对象——>getClass()方法——>取得完整的包类名称

反射优缺点
优点: 可以实现动态创建对象和编译,体现出很大的灵活性
缺点: 对性能有影响,使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作。
主要API:
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器

补充:
java四种访问权限
private:只能允许该类的对象访问,其子类不能访问,更不允许跨包访问
default:允许该类的对象访问,其子类也可访问,当时不允许跨包访问
protected:允许该类的对象访问,其子类也可访问,即使其子类不在同一个包也可访问
public:

权限类内同包不同包子类不同包非子类
private×××
default××
protected×
public

常用方法

方法说明
static ClassforName(String name)返回指定类名name的Class对象
Object new Instance()调用缺省构造函数,返回Class对象的一个实例
getName()返回此Class对象所表示的实体(类、接口、数组类或void的名称)
Class getSuperClass()返回当前Class对象的父类的Class对象
Class[] getinterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Constructor[] getConstructors()返回一个包含某些Constructor对象的数组
Method getMothed(String name,Class…T)返回一个Method对象,此对象的形参类型为paramType
Field[] getDeclaredFields()返回Field对象的一个数组
public class demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是"+person.name);
        //方法一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //方法二:通过forName
        Class c2 = Class.forName("test.Student");
        System.out.println(c2.hashCode());
        //方式三:直接通过类名
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        //方式四:基本内置类型的包装类都有一个TYPE属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}

class Person{
    String name;

    public Person() {
    }
    public Person(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                '}';
    }
}

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

class Teacher extends Person{
    public Teacher(){
        this.name = "老师";
    }
}

		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 = Class.class; //Class
        Class c8 = void.class;  // void
        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);
        //只要数据类型与维度是一样的,同属于一个Class
        int[] a =new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());

类的加载
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的Class对象
链接:将Java类的二进制代码合并到JVM的运行状态中的过程

验证:确保加载的类信息符合JVM规范,没有安全方面的问题准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配解析:虚拟机常量池内的符号引用(常量名)替代为直接引用(地址)的过程

初始化:

执行类构造器()方法的过程,类构造器是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)当初始化一个类的时候,如果发现其父类还没有进行初始化,则先触发其父类的初始化虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步

类的初始化

    类的主动引用(一定会发生类的初始化)

当虚拟机启动,先初始化main方法所在的类new一个类的对象调用类的静态成员(除了final常量)和静态方法使用java.lang.reflect包的方 法对类进行反射调用.当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类

    类的被动引用(不会发生类的初始化)

当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化通过数组定义类引用,不会触发此类的初始化引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了

package test;

public class demo4 {
    static{
        System.out.println("main被加载");
    }
    public static void main(String[] args) throws ClassNotFoundException {
           //1. 主动引用
         Son son = new Son();  //main被加载,父类被加载,子类被加载
        // 反射也会产生主动引用
        Class c1 = Class.forName("test.Son"); //main被加载,父类被加载,子类被加载
        //2. 被动引用
        System.out.println(Son.b);//不会引用子类,只有父类被加载
        Son[] sons = new Son[5]; //只有main被加载
        System.out.println(Son.M); //只有main被加载

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

类加载的作用:
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
类缓存:
标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象

package test;

public class demo5 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统的类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
        //获取系统类加载器的父类-》扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);
        //获取扩展类加载器的父类->根加载器(C/C++编写) 根加载器用来装载核心类库,无法直接获取
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);
        //测试当前类是那个加载器加载的  系统类加载器
        ClassLoader classLoader = Class.forName("test.demo5").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 test;

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

public class demo6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("test.User");
        //获得类的名字
        System.out.println(c1.getName()); //包名+类名
        System.out.println(c1.getSimpleName()); //类名
        //获得属性
//        Field[] fields = c1.getFields(); 只能找到public属性
        Field[] fields = c1.getDeclaredFields();//可以找到全部属性
        for (Field field : fields) {
            System.out.println(field);
        }
        //获得指定的属性
        System.out.println(c1.getDeclaredField("username"));
        System.out.println("-------------------------------------------");
        //获得类的方法
        Method[] methods = c1.getMethods();//获得本类及父类的全部public方法
        for (Method method : methods) {
            System.out.println("正常的"+method);
        }
        Method[] Methods = c1.getDeclaredMethods();//本类的所有方法
        for (Method method : Methods) {
            System.out.println(method);
        }
        //获得指定的方法
        System.out.println(c1.getMethod("getUsername",null));
        System.out.println(c1.getMethod("setUsername", String.class));
        //获得构造器
        System.out.println("=======================");
        Constructor[] constructors = c1.getConstructors();//获得public构造方法
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();//获得全部的构造方法
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
    }
}

test.User
User
private java.lang.String test.User.username
private int test.User.age
private int test.User.id
private java.lang.String test.User.username
正常的public java.lang.String test.User.toString()
正常的public int test.User.getId()
正常的public void test.User.setId(int)
正常的public int test.User.getAge()
正常的public void test.User.setAge(int)
正常的public java.lang.String test.User.getUsername()
正常的public void test.User.setUsername(java.lang.String)
正常的public final void java.lang.Object.wait() throws java.lang.InterruptedException
正常的public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
正常的public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
正常的public boolean java.lang.Object.equals(java.lang.Object)
正常的public native int java.lang.Object.hashCode()
正常的public final native java.lang.Class java.lang.Object.getClass()
正常的public final native void java.lang.Object.notify()
正常的public final native void java.lang.Object.notifyAll()
public java.lang.String test.User.toString()
public int test.User.getId()
public void test.User.setId(int)
public int test.User.getAge()
public void test.User.setAge(int)
public java.lang.String test.User.getUsername()
public void test.User.setUsername(java.lang.String)
public java.lang.String test.User.getUsername()
public void test.User.setUsername(java.lang.String)
public test.User()
public test.User(java.lang.String,int,int)
public test.User()
public test.User(java.lang.String,int,int)
动态创建对象执行方法

package test;

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

public class demo7 {
    public static void main(String[] args) throws Exception {
        //获得class对象
        Class c1 = Class.forName("test.User");
        //1. 构造一个对象
//        User user = (User)c1.newInstance();//实际上调用了一个无参构造器
//        System.out.println(user);
        //2. 通过构造器创建对象
//        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
//        User user1= (User)constructor.newInstance("小明", 001, 18);
//        System.out.println(user1);
        //3. 通过反射调用方法
//        User user = (User)c1.newInstance();
//        Method setUsername = c1.getDeclaredMethod("setUsername", String.class);
//        //invoke 激活 (对象,"方法的值")
//        setUsername.invoke(user,"张三");
//        System.out.println(user.getUsername());
        //4. 通过反射调用属性
        User user = (User)c1.newInstance();
        Field username = c1.getDeclaredField("username");
        //不能直接操作私有属性,需要关闭安全检测
        username.setAccessible(true);
        username.set(user,"小明");
        System.out.println(user.getUsername());


    }
}
package test;

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

public class demo8 {
    public static void test1(){
        User user = new User();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getUsername();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("正常方式"+(endTime-startTime)+"毫秒");
    }
    public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getUsername = c1.getDeclaredMethod("getUsername");
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getUsername.invoke(user);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式"+(endTime-startTime)+"毫秒");
    }

    public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getUsername = c1.getDeclaredMethod("getUsername");
        getUsername.setAccessible(true);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getUsername.invoke(user);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("关闭检查"+(endTime-startTime)+"毫秒");
    }


    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test1();
        test2();
        test3();

    }
}

获取泛型
package test;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class demo6 {
    public void test1(Map map, List list){
        System.out.println("test1");
    }
    public Map test2(){
        System.out.println("test2");
        return null;
    }
    public static void main(String[] args) throws Exception {
        Method test1 = demo6.class.getMethod("test1", Map.class, List.class);
        Type[] genericParameterTypes = test1.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            if(genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
        Method test2 = demo6.class.getMethod("test2");
        Type genericReturnType = test2.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}

获取注解信息
package test;

import javafx.scene.control.Tab;

import java.lang.annotation.*;
import java.lang.reflect.Field;

public class demo7 {
    public static void main(String[] args) throws Exception {
        Class c1  = Class.forName("test.Student1");
        //获取注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获取注解的value值
        Tablezzz tablezzz = (Tablezzz)c1.getAnnotation(Tablezzz.class);
        System.out.println(tablezzz.value());
        //获取指定的注解值
        Field name = c1.getDeclaredField("name");
        Fieldzzz annotation = (Fieldzzz) name.getAnnotation(Fieldzzz.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());

    }
}
@Tablezzz("db_student")
class Student1{
    @Fieldzzz(columnName = "db_id",type = "int",length = 10)
    private  int id;
    @Fieldzzz(columnName = "db_name",type = "varchar",length = 3)
    private String name;
    @Fieldzzz(columnName = "db_age",type = "int",length = 1)
    private int age;

    public Student1() {
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

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

    @Override
    public String toString() {
        String s = "Student1{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", age=" + age +
                '}';
        return s;
    }
}

//类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablezzz{
    String value();
}

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/773730.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号