注解与反射
自定义注解
@Target 描述的注解可以用在什么地方
@Retention 表示被它所注解的注解在什么地方还有效
@Documented 是否将我们的注解生成在javaDoc
文档中
@Inherited 说明子类可以继承父类中的该注解
/**
* @program: 注解和反射
* @description: 自定义注解
* @author: wangj
* @create: 2021/08/14 20:42
*/
public class Test03 {
// 注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
@MyAnnotation2(name="名字",schools={"朝阳小学","朝阳中学"})
@MyAnnotation3("这这这这")
public void test(){
}
}
// 定义一个注解
@Target({ElementType.METHOD,ElementType.TYPE}) //描述的注解可以用在什么地方
@Retention(RetentionPolicy.RUNTIME) //表示被它所注解的注解在什么地方还有效
@Documented // 是否将我们的注解生成在javaDoc文档中
@Inherited // 说明子类可以继承父类中的该注解
@interface MyAnnotation{
String name() default "";
int age() default 0;
String[] schools();
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
String value(); // 注解如果只有一个参数,用value(),使用是 value可以省略
}
获得反射对象
一个类在内存中只有一个Class对象
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获取类的class对象
Class c1 = Class.forName("com.example.reflection.User");
Class c2 = Class.forName("com.example.reflection.User");
Class c3 = Class.forName("com.example.reflection.User");
Class c4 = Class.forName("com.example.reflection.User");
System.out.println(c1);
// 一个类在内存中只有一个Class对象
// 一个类被加载后,类的整个结构都会被封装在Class对象中
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
// 实体类entity,pojo
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;
}
public String getName() {
return name;
}
public void setName(String name) {
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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}
得到Class类的几种方式
通过对象获得
对象.getClass
forName
获得
Class.forName()
通过类名.class 获得
类名.class
基本内置对象的包装类都有一个Type属性
Class
c4 = Integer.TYPE
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Person person = new Student();
System.out.println("这个人是:" + person.name);
//方式一: 通过对象获得
Class c1 = person.getClass();
System.out.println("通过<对象.getClass>获得Student Class对象: " + c1.hashCode());
// 方式二: forName获得
Class c2 = Class.forName("com.example.reflection.Student");
System.out.println("通过获得Student Class对象: " + c2.hashCode());
//方式三: 通过类名.class 获得
Class c3 = Student.class;
System.out.println("通过 <类名.class> 获得Student Class对象: " + c3.hashCode());
// 方式四: 基本内置对象的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println("通过<包装类的Type属性>,获取Class对象: " + c4);
// 获取父类类型
Class c5 = c1.getSuperclass();
System.out.println("通过获取父类类型: " +c5);
Teacher teacher = test(Teacher.class);
System.out.println(teacher);
}
public static T test(Class claZZ) throws InstantiationException, IllegalAccessException {
return claZZ.newInstance();
}
}
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="老师";
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
}
获得类的信息
获得类的名字:
getName()
获得包名 + 类名
getSimpleName()
获得类名获得类的属性:
getFields()
只能找到public属性
getDeclaredFields()
找到所有属性获得类的方法:
getMethods()
// 获得本类及其父类的全部方法
getDeclaredMethods()
// 获得本类的全部方法获得指定的方法:
getMethod("setName", String.class);
// 获得名称为setName
,参数为String
的方法获得指定的构造器:
getConstructors()
// 获得public 构造方法
getDeclaredConstructors()
// 获得全部 构造方法获得指定构造器:
getDeclaredConstructor(String.class, Integer.TYPE,int.class)
获得参数为(String ,int,int)的构造方法
public class Test05 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.example.reflection.User");
// 获得类的名字
System.out.println(c1.getName()); // 获得包名 + 类名
System.out.println(c1.getSimpleName()); // 获得类名
// 获得类的属性
// Field[] fields = c1.getFields(); //只能找到public属性
// for (Field field : fields) {
// System.out.println(field);
// }
Field[] fields = c1.getDeclaredFields(); // 找到所有属性
for (Field field : fields) {
System.out.println(field);
}
Field name = c1.getDeclaredField("name");
System.out.println(name);
// 获得类的方法
Method[] methods = c1.getMethods(); // 获得本类及其父类的全部方法
for (Method method : methods) {
System.out.println(" getMethods ==>" + method);
}
methods = c1.getDeclaredMethods(); // 获得本类的全部方法
for (Method method : methods) {
System.out.println("getDeclaredMethods ==> " + method);
}
// 获得指定的方法
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
// 获得指定的构造器
System.out.println("============================================");
Constructor[] constructors = c1.getConstructors(); // 获得public 构造方法
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors(); // 获得全部 构造方法
for (Constructor constructor : constructors) {
System.out.println(" ### " + constructor);
}
// 获得指定构造器
Constructor constructor = c1.getDeclaredConstructor(String.class, Integer.TYPE,int.class);
System.out.println(constructor);
}
}
动态创建对象执行方法
Class.newInstance()
调用了类的无参构造器构造一个对象
Constructor.newInstance(Object... var1)
通过构造器创建对象
Method.invokeinvoke(Object var1, Object... var2)
通过反射调用普通方法能直接操作私有属性,需要关闭程序的安全检测,属性或方法的
setAccessible
方法
Field.setAccessible(true)
关闭java
访问安全检查
Field.set(Object var1, Object var2)
通过反射操作属性
public class Test06 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
// 获得class对象
Class c1 = Class.forName("com.example.reflection.User");
// 构造一个对象
User user = (User)c1.newInstance(); // 本质上调用了类的无参构造器
System.out.println(user);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class,int.class);
User user2 = (User)constructor.newInstance("无伤", 1, 18);
System.out.println(user2);
// 通过反射调用普通方法
User user3 = (User)c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
// 调用(对象,"方法的参数")==> 调用 对象的方法
setName.invoke(user3,"无敌");
System.out.println(user3);
// 通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
// 不能直接操作私有属性,需要关闭程序的安全检测,属性或方法的 setAccessible 方法
name.setAccessible(true); //关闭java访问安全检查
name.set(user4,"无名");
System.out.println(user4);
}
}
获取泛型信息
method.getGenericParameterTypes()
获得泛型参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments()
获取实际参数类型
Type genericReturnType = method.getGenericReturnType()
获得返回泛型类型
public class Test08 {
public void test01(Map map, List list){
System.out.println("test01");
}
public Map test02(){
System.out.println("test01");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
System.out.println("==============参数泛型=================");
Method method= Test08.class.getMethod("test01", Map.class, List.class);
// 获得泛型参数类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(" # " + genericParameterType);
// 获取实际参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("--" + actualTypeArgument);
}
}
// 获得返回泛型类型
System.out.println("=============返回值泛型==================");
method = Test08.class.getMethod("test02", null);
Type genericReturnType = method.getGenericReturnType();
System.out.println(genericReturnType);
// 获取实际参数类型
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("--" + actualTypeArgument);
}
}
}
反射操作注解
通过反射获得注解
class.getAnnotations()
获得指定注解
MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);
获得注解的属性值
String value = myTable.value();
public class Test09 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.example.reflection.Stu");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获得注解的value的值
MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);
String value = myTable.value();
System.out.println(value);
// 获得类指定属性的注解
Field name = c1.getDeclaredField("name");
MyField myField = name.getAnnotation(MyField.class);
System.out.println(myField.column());
System.out.println(myField.type());
System.out.println(myField.length());
}
}
@MyTable("db_stu")
class Stu{
@MyField(column = "db_id",type = "int",length = 10)
private int id;
@MyField(column = "db_age",type = "int",length = 10)
private int age;
@MyField(column = "db_name",type = "varchar",length = 10)
private String name;
public Stu() {
}
public Stu(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 "Stu{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTable{
String value();
}
// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyField{
String column();
String type();
int length();
}