注解和反射(二)

简介: 注解和反射

注解和反射(一)+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新增了ParameterizedGenericArrayTypeTypeVariableWildcardType几种类型来代表不能被归一到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

参考

狂神

目录
相关文章
|
10月前
66.【注解与反射】(四)
66.【注解与反射】
26 0
|
10月前
66.【注解与反射】(二)
66.【注解与反射】
30 0
|
2天前
|
Java 程序员 编译器
注解和反射(一)
注解和反射
11 0
|
10月前
|
Java
66.【注解与反射】(三)
66.【注解与反射】
31 0
|
10月前
66.【注解与反射】(一)
66.【注解与反射】
30 0
|
12月前
|
编译器
反射、注解和泛型相关的坑
泛型 类型擦除 桥接方法
|
12月前
|
编译器
反射、注解和泛型相关的坑
根据反射来获取方法,很多人觉得获取方法传入参数就可以了,但是遇到方法的重载的时候,怎么能够知道此次执行走的是哪个方法呢?
|
Oracle Java 关系型数据库
反射与自定义注解
反射与自定义注解
反射与自定义注解
|
编译器
注解与反射.1什么是注解?
注解与反射.1什么是注解?
|
程序员
注解和反射2.内置注解
注解和反射2.内置注解