注解和反射(一)+https://developer.aliyun.com/article/1556634
4. 案例:反射做通用框架
Student.java
public class Student { private String name; private char sex; private int age; private String className; private String hobby; public Student(){} public Student(String name, char sex, int age, String className, String hobby) { this.name = name; this.sex = sex; this.age = age; this.className = className; this.hobby = hobby; } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } }
Teacher.java
public class Teacher { private String name; private char sex; private double salary; public Teacher() { } public Teacher(String name, char sex, double salary) { this.name = name; this.sex = sex; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } }
MybatisUtil.java
import java.io.FileOutputStream; import java.io.PrintStream; import java.lang.reflect.Field; public class MybatisUtil { public static void save(Object obj) { try( PrintStream ps = new PrintStream(new FileOutputStream("junit-app/src/data.txt", true)); ){ //1. 提取这个对象的全部变量:只有反射可以解决 Class c = obj.getClass(); //c.getSimpleName()获取当前类名 c.getName获取全限名:包名+类名 ps.println("===========" + c.getSimpleName() + "============"); //2. 提取它的全部成员变量 Field[] fields = c.getDeclaredFields(); //3. 获取成员变量的信息 for (Field field : fields) { String name = field.getName(); //提取本成员变量在obj中的值(取值) field.setAccessible(true); String value = field.get(obj) + ""; ps.println(name + "=" + value); } } catch(Exception e){ e.printStackTrace(); } } }
ReflectDemo.java
//目标:提供一个通用框架,支持保存所有对象的具体信息 public class ReflectDemo { public static void main(String[] args) { Student s = new Student(); s.setName("猪八戒"); s.setClassName("西天跑路班"); s.setAge(1000); s.setHobby("吃,睡"); s.setSex('男'); MybatisUtil.save(s); Teacher t = new Teacher(); t.setName("波仔"); t.setSex('男'); t.setSalary(6000); MybatisUtil.save(t); } }
结果生成的data.txt:
5. 使用反射
例2:
package demo03; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test05 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { //获取Class对象 Class c1 = Class.forName("demo03.Student"); //通过构造器创建对象 Constructor constructor = c1.getDeclaredConstructor(String.class, char.class, int.class, String.class, String.class); Student s = (Student) constructor.newInstance("zd", '男', 18, "班级", "爱好"); System.out.println(s); //创建一个对象 Student student= (Student) c1.newInstance(); //调用了类的无参构造器 //通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); //invoke(对象,方法的值) setName.invoke(student, "zad"); System.out.println(student.getName()); //通过反射操作属性 Student s3= (Student) c1.newInstance(); Field name = c1.getDeclaredField("name"); //不能直接操作私有属性,需要设置setAccessible name.setAccessible(true); name.set(s3, "wq"); System.out.println(s3.getName()); } }
demo03.Student@677327b6 zad wq
6. 反射操作泛型
Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的问题,但是,一旦编译完成,所有的泛型有关的类型全部擦除
为了通过反射操作这些类型,Java新增了Parameterized
,GenericArrayType
,TypeVariable
和WildcardType
几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
ParameterizedType
:表示一种参数化类型,比如Collection
GenericArrayType
:表示一种元素类型是参数化类型或者类型变量的数组类型TypeVariable
:是各种类型变量的公共父接口WildcardType
:代表一种通配符类型表达式
package demo04; 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 Test01 { public void test02(Map<String, Student> map, List<Student> list){ System.out.println("test02"); } public Map<String, Student> test03(){ System.out.println("test03"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method = Test01.class.getMethod("test02", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println("#" + genericParameterType); if(genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } } }
#java.util.Map<java.lang.String, demo04.Student> class java.lang.String class demo04.Student #java.util.List<demo04.Student> class demo04.Student
7. 反射获取注解信息
package demo05; import java.lang.annotation.*; import java.lang.reflect.Field; //连续反射操作注解 public class Test01 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("demo05.Student2"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解的value的值 Tablekuang tablekuang = (Tablekuang)c1.getAnnotation(Tablekuang.class); String value = tablekuang.value(); System.out.println(value); //获得类指定的注解 Field f = c1.getDeclaredField("name"); Filedkuang annotation = f.getAnnotation(Filedkuang.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @Tablekuang("db_student") class Student2 { @Filedkuang(columnName="db_id", type="int",length=10) private int id; @Filedkuang(columnName="db_age", type="int",length=10) private int age; @Filedkuang(columnName="db_name", type="varchar",length=3) private String name; public Student2() { } public Student2(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 "Student{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } } //类名的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Tablekuang{ String value(); } //属性的注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Filedkuang{ String columnName(); String type(); int length(); }
@demo05.Tablekuang(value=db_student) db_student db_name varchar 3