扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
注解的主要作用:对我们的程序进行标注和解释。
(可以理解成:注释是写给人看的;注解是写给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(){}
}
元注解元注解:就是描述注解的注解。
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
利用反射可以无视修饰符获取类里面所有的属性和方法。
先获取配置文件中的信息,动态获取信息并创建对象和调用方法
一般调用方法和反射调用方法比较一般:1. 创建这个类的对象 2. 用对象调用方法;
反射:1. 利用class对象来创建的 2. 反射方式:创建对象 3. 反射方式:调用方法
对象:
Constructor>[] getConstructors():返回所有公共构造方法对象的数组 Constructor>[] getDeclaredConstructors():返回所有构造方法对象的数组
Constructor getConstructor(Class>... parameterTypes):返回单个公共构造方法对象 Constructor getDeclaredConstructor(Class>… parameterTypes):返回单个构造方法对象
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对象。
Class>aClass = 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)的构造方法,包括私有的。
Constructor>constructor = 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对象。
Class>aClass = Class.forName("com.jifu.test.bean.Person");
//获得参数类型为(String.class,int.class,String.class)的构造方法,包括私有的。
Constructor>constructor = 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对象。
Class>aClass = Class.forName("com.jifu.test.enumTest.TestDame");
// 获得TestDame的无参构造。
Constructor>declaredConstructor = 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元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流