zoukankan      html  css  js  c++  java
  • 注解和反射基础知识和使用方法

    注解

    注解(Annotation)不是程序本身,可以对程序做出解释(这和注释comment没什么区别)。

    注解可以被其他程序读取。

    内置注解

    @Override  //重写的注解
    public String toString(){
        return super.toString();
    }
    
    @Deprecated  //不推荐程序员使用,或者存在更好的方式,但是可以使用。
    public void test(){
        System.out.println("这段代码不推荐使用");
    }
    
    @SuppressWarnings()  //镇压警告,需要参数
    

    元注解

    元注解(meta-annotation)负责注解其他注解的注解,Java中定义了4个标准的元注解类型,用来提供对其他注解类型作说明。

    @Target  //描述注解的使用范围
    
    @Retention  //表示需要在什么级别保存该注释信息,描述注解的生命周期(SOURCE<CLASS<RUNTIME)
    
    @Documented  //说明该注解将被包含在javadoc中
    
    @Inherited  //说明子类可以继承父类中的该注解
    

    自定义注解

    使用@interface自定义注解,自动继承java.lang.annotation.Annotation接口。

    1. @interface用来声明一个注解,格式:public @interface 注解名{定义内容}

    2. 其中的每一个方法实际上是声明了一个配置参数

    3. 方法的名称就是参数的名称

    4. 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)

    5. 可以通过default声明参数的默认值

    6. 如果只有一个参数成员,一般参数名为value

    7. 注解元素必须要有值,定义注解元素时,经常使用空字符串0作为默认值

    //自定义一个注解格式
    @Target(value = ElementType.METHOD)//在方法中生效
    @Retention(value = RetentionPolicy.RUNTIME)//表示在运行时也生效(任何时生效)
    @Documented
    @Inherited
    public @interface MyFirstAnnotation{
        //注解的参数 : 参数类型 + 参数名();
        String name() default "";
        int age() default 0;
        int id() default -1;//默认-1,代表不存在
    }
    
    //使用时必须需要提供无默认值的参数
    @MyFirstAnnotation(name = "lee",age = 18,id = 10086)
    public void test1(){}
    

    反射

    反射(Reflection)使Java有一定的动态性,可以利用反射机制获得类似动态语言的特性,使程序更灵活。

    反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。使用反射提高程序的通用性。

    通过统一的语法创建对象获取对象。

    反射

    类加载

    Class:在JVM(虚拟机)加载完,Class文件以后,会给每个类生成唯一的一个Class对象。该Class对象是该类所有实例(对象)共享的一个对象,Class对象包含了与类有关的信息,在Class对象中会把属性以及方法都单独封装成一个对象。

    三个步骤:

    1. 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。

    2. 链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。

      验证:确保加载的类信息符合JVM规范,没有安全问题。

      准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。

      解析:虚拟机常量池内的符合引用(常量名)替换为直接引用(地址)的过程。

    3. 初始化:到了此阶段,才真正开始执行类中定义的java程序代码,用于执行该类的静态初始器和静态初始块,如果该类有父类,优先对其父类进行初始化。

    使用步骤

    1. 获取class对象

      一个类在内存中只有一个Class对象。

      一个类被加载后,类的整个结构都会被封装在class对象中。

      //通过类的对象获取
      Animal animal = new Animal();
      Class animalClass1 = animal.getClass();
      //通过类名.class获取
      Class animalClass2 = Animal.class;
      //通过forName限定性类名获取
      String className = "包名.类名"
      Class animalClass3 = Class.forName(className);
      //通过反射创建一个类的实例
      object obj = animalClass3.newInstance;
      
    2. 操作对象里面的属性

      Field[] fs1 = animalClass3.getFields();//获取所有的公共属性
      Field[] fs2 = animalClass3.gerDeclaredFields();//获取所有属性
      
    3. 根据属性名称获取属性

      Field[] ageField = animalClass3.gerDeclaredFields("age");
      ageField.setAccessible(true);//取消安全检查,允许获取私有的属性值
      ageField.setInt(obj,999);
      int age = ageField.getInd(obj);//获取
      System.out.println(age);
      
    4. 操作对象里面的方法

      Method[] ms = animalClass3.getMethods();//获取所有的公共方法
      Method[] ms = animalClass3.getDeclaredMethods();//获取所有方法
      Method eatMethod = animalClass3.getMethod("eat",int.class,String.class);
      eatMethod.invoke(obj,20,"lee");
      Class<?>[] pcType = eatMethod.getParameterTypes();
      

    实例

    /*反射实例*/
    public void r1(){
        String personStr = "com.example.bean.Person";//对象类型属性
        try {
            Class personClass = Class.forName(personStr);
            Object obj = personClass.newInstance();
            String parKey = "name";
            String parValue = "张三";
            
    		//通过字符串拼接创建set方法
            String setParKey = "set"+parKey.substring(0,1).toUpperCase()+parKey.substring(1);
            Method setNameMethod = personClass.getMethod(setParKey,parValue.getClass());
    
            setNameMethod.invoke(obj,parValue);
    
            //通过字符串拼接创建get方法
            String getParKey = "get"+parKey.substring(0,1).toUpperCase()+parKey.substring(1);
            Method getNameMethod = personClass.getMethod(setParKey,parValue.getClass());
    
            Object result = getNameMethod.invoke(obj);
    
            System.out.println(result);
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • 相关阅读:
    潜移默化学会WPF绘图 学习(一)
    MovablePlane issue
    ogre Fix bug in HLSL with 3×4 matrix arrays
    如何加强角色渲染的真实感(self shadow + subsurface scattering + rim lighting)
    The DirectX SDK (February 2010) release is now live on Microsoft downloads.
    Color Spaces
    游戏主循环
    实时动态云 perlin noise + 光照 + 太阳光遮挡
    这几个礼拜做的事情
    ogre无法读取中文路径的解决办法
  • 原文地址:https://www.cnblogs.com/hermitlee/p/15195003.html
Copyright © 2011-2022 走看看