资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

java——注解,反射-创新互联

java —— 注解,反射
  • 注解
    • 什么是注解
    • 常用注解
    • 自定义注解
        • 格式:
        • 例子
            • 定义
            • 使用
    • 元注解
          • @Retention
  • 反射
    • 反射的概述
        • Java反射机制(自审机制)
        • 一般调用方法和反射调用方法比较
    • 反射获取构造方法并使用
      • 获取Class类的对象
        • Class类中用于获取构造方法的方法
        • Constructor类中用于创建对象的方法
        • 练习
      • 小结
    • 反射获取成员变量
        • 步骤
    • 反射获取成员方法并运行
        • 步骤
        • 练习
  • 综合应用(注解+反射)
      • 自定义注解类
      • 要运行的类
      • main方法运行看效果
      • 运行效果

创新互联长期为上千余家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为浠水企业提供专业的网站制作、成都网站设计,浠水网站改版等技术服务。拥有十余年丰富建站经验和众多成功案例,为您定制开发。注解 什么是注解

注解的主要作用:对我们的程序进行标注和解释。
(可以理解成:注释是写给人看的;注解是写给jvm看的)

常用注解

在这里插入图片描述
如:
在这里插入图片描述

自定义注解 格式:
public @interface 注解名称 {public 属性类型 属性名() default 默认值 ;//属性类型可以是:基本数据类型,String,Class,注解,枚举,以上类型的一维数组
 }
例子 定义
@Retention(RetentionPolicy.CLASS)//元注解,运行时注解的作用时间范围。
@Target(ElementType.METHOD)//元注解,类可以在什么上面使用。
public @interface MyTest {String name();
    int code() default 200;
}
使用
public class Main {@MyTest(name = "0",code = 200)//有默认值就可以不写,当你要写code = 200时可以写成@MyTest(name = "0")
    public void annotationTest(){}
}
元注解

元注解:就是描述注解的注解。
在这里插入图片描述

@Retention
  1. @Retention(RetentionPolicy.CLASS)//注释将被编译器记录在类文件中,但不需要在运行时由虚拟机保留。
  2. @Retention(RetentionPolicy.RUNTIME)//注释要记录在类文件由编译器和运行时虚拟机保留的,所以他们可以读沉思。
  3. @Retention(RetentionPolicy.SOURCE)//注释将被编译器丢弃。
    注解一般用在写一个通用的程序框架的场合。它通常和反射结合起来使用;
反射 反射的概述 Java反射机制(自审机制)
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
   对于任意一个对象,都能够调用它的任意属性和方法;
   这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
   利用反射可以无视修饰符获取类里面所有的属性和方法。
   先获取配置文件中的信息,动态获取信息并创建对象和调用方法
一般调用方法和反射调用方法比较

一般:1. 创建这个类的对象 2. 用对象调用方法;
反射:1. 利用class对象来创建的 2. 反射方式:创建对象 3. 反射方式:调用方法

对象:
在这里插入图片描述

反射获取构造方法并使用 获取Class类的对象
  1. Class.forName(“全类名”);
  2. 类名.class
  3. 对象.getClass();
Class类中用于获取构造方法的方法

Constructor[] getConstructors​():返回所有公共构造方法对象的数组 Constructor[] getDeclaredConstructors​():返回所有构造方法对象的数组
Constructor getConstructor​(Class... parameterTypes):返回单个公共构造方法对象 Constructor getDeclaredConstructor​(Class… parameterTypes):返回单个构造方法对象

Constructor类中用于创建对象的方法

T newInstance​(Object… initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查

练习

person实体类(后面将用这个类来演示):

public class Person implements Serializable {private String name;
    private int age;
    private String address;

    public Person() {}

    public Person(String name) {this.name = name;
    }

    private Person(String name, int age, String address) {this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    public String toString() {return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
    private void study(){System.out.println("私有方法执行了-----");
    }
}
public class Main {public static void main(String[] args) {try {// 获取到Person类的class对象。
            ClassaClass = Class.forName("com.jifu.test.bean.Person"); 
            //创建Person对象
            Person person = (Person) aClass.newInstance();
            //获得com.jifu.test.bean.Person这个对象的所有构造方法,包括私有的。
             Constructor[] allConstructors = aClass.getDeclaredConstructors();
            //获得com.jifu.test.bean.Person这个对象的public修饰的构造方法。
            Constructor[] constructors = aClass.getConstructors();
            //获得参数类型为(String.class,int.class,String.class)的构造方法,包括私有的。
             Constructorconstructor = aClass.getDeclaredConstructor(String.class,int.class,String.class);
            //设置为true 表示取消访问检查。
            constructor.setAccessible(true);
            Person person = (Person)constructor.newInstance("小明", 18, "北京");
           
        }catch (ClassNotFoundException | InstantiationException | IllegalAccessException |NoSuchMethodException e) {e.printStackTrace();
        }

    }
}
小结

获取class对象
三种方式 ---- Class.forName(“全类名”)
获取里面的构造方法对象
getConstructor (Class... parameterTypes) getDeclaredConstructor (Class… parameterTypes)
如果是public的,直接创建对象
newInstance(Object… initargs)
如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean)(暴力获取)

反射获取成员变量 步骤

第一步:获得class对象
Class.forName(“全类名”);

第二步:获得Field对象
Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象

第三步:赋值或者获取值
void set(Object obj, Object value):赋值
Object get(Object obj)获取值。

反射获取成员方法并运行 步骤

第一步:获得class对象
Class.forName(“全类名”);

第二步:获得Method对象
Method ] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class... parameterTypes):返回单个公共成员方法对象 Method getDeclaredMethod(String name, Class… parameterTypes):返回单个成员方法对象

练习
public class Main {public static void main(String[] args) {try {// 获取到Person类的class对象。
            ClassaClass = Class.forName("com.jifu.test.bean.Person"); 
            //获得参数类型为(String.class,int.class,String.class)的构造方法,包括私有的。
            Constructorconstructor = aClass.getDeclaredConstructor(String.class,int.class,String.class);
             //设置为true 表示取消访问检查。
            constructor.setAccessible(true);
            //创建Person对象
            Person person = (Person)constructor.newInstance("小明", 18, "北京");
            //获得名为study的Person对象中的方法对象(第一个参数是方法名,后面的参数是方法参数的类型)
            Method study = aClass.getDeclaredMethod("study", null);
             //设置为true 表示取消访问检查。
            study.setAccessible(true);
            //执行方法(第一个参数是调用该方法的对象,后面的参数是方法中要传的参数值)
            study.invoke(person,null);
        }catch (ClassNotFoundException | InstantiationException | IllegalAccessException |NoSuchMethodException e) {e.printStackTrace();
        }

    }
}
综合应用(注解+反射)

需求:一个类里面只要是标注了 @MyTest注解的就自动运行

自定义注解类
package com.jifu.test.enumTest;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //此处必须是RUNTIME才能看到效果
@Target(ElementType.METHOD)
public @interface MyTest {String name();
    int code() default 200;
}
要运行的类
package com.jifu.test.enumTest;

public class TestDame {@MyTest(name = "知识")
    public void TestMethod(){System.out.println("测试方法1");
    }
    @Deprecated
    @MyTest(name = "知识",code = 201)
    private void TestMethod2(){System.out.println("测试方法2");
    }
    public void TestMethod3(){System.out.println("测试方法3");
    }
}
main方法运行看效果
package com.jifu.test.enumTest;

import com.jifu.test.bean.Person;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class Main {public static void main(String ... args){  try {  //获取到"com.jifu.test.enumTest.TestDame"类的class对象。
        ClassaClass = Class.forName("com.jifu.test.enumTest.TestDame");
       // 获得TestDame的无参构造。
         ConstructordeclaredConstructor = aClass.getDeclaredConstructor(null);
         //通过无参构造方法获得TestDame实例对象。
        TestDame testDame = (TestDame)declaredConstructor.newInstance();
        //获得"com.jifu.test.enumTest.TestDame"类的所有方法包括非public的
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {//打印每个方法
          System.out.println(declaredMethod);
          //获得这个方法中的所有注解
          final Annotation[] declaredAnnotations = declaredMethod.getDeclaredAnnotations();
          for (Annotation declaredAnnotation : declaredAnnotations) {  //遍历打印每个注解
            System.out.println(declaredAnnotation);
            //判断注解是不是MyTest.class类型
              if (declaredAnnotation.annotationType()==MyTest.class){  //设置取消方法受检。
            declaredMethod.setAccessible(true);
              //如果注解是MyTest.class类型就运行,需要传入对象的类型
                declaredMethod.invoke(testDame);
              }
          }
          }
        }
      } catch (ClassNotFoundException e) {e.printStackTrace();
      }
    }
}
运行效果
Z:\jdk-11.0.1\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA 2021.1\lib\idea_rt.jar=63709:D:\idea\IntelliJ IDEA 2021.1\bin" -Dfile.encoding=UTF-8 -classpath F:\zhifei\zhifei\test\target\classes com.jifu.test.enumTest.Main

public void com.jifu.test.enumTest.TestDame.TestMethod()     //TestMethod()方法上只有一个@MyTest注解
@com.jifu.test.enumTest.MyTest(code=200, name="知识")		
测试方法1		//方法运行了

private void com.jifu.test.enumTest.TestDame.TestMethod2()     //TestMethod2()方法上有一个@MyTest注解 和 @Deprecated注解
@java.lang.Deprecated(forRemoval=false, since="")
@com.jifu.test.enumTest.MyTest(code=201, name="知识")
测试方法2          //方法运行了

public void com.jifu.test.enumTest.TestDame.TestMethod3()     //TestMethod3()方法上没有t注解  

Process finished with exit code 0

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻名称:java——注解,反射-创新互联
标题链接:http://cdkjz.cn/article/dcdoes.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

业务热线:400-028-6601 / 大客户专线   成都:13518219792   座机:028-86922220