Java反射框架Type Class 及相关方法浅析

最近研究Gson源码,对java反射这一块顺便详细了解了下。今天也不说的太深,就分享几个动态获取类型相关的方法。
java中class,method,field的继承体系

先说一下Class与Field相关的一些除了常用的反射一个类的成员和方法之外的几个方法的用法。

一.Class相关

getSuperClass() //返回调用类的超类

getGenericSuperClass() //返回调用类的带泛型类型参数的超类

getGenericInterfaces() //返回调用类直接实现的接口类型

注:由于java中一个类可以实现多个接口,所以getGenericInterfaces()返回一个Type[]数组类型。

见下例:


 public class Person<T> {
 
 }
 
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 
 public class Student extends Person<Student> {
 public static void main(String[] args) {
 Student st=new Student();
 Class clazz=st.getClass();
 //getSuperclass()获得该类的父类
 System.out.println(clazz.getSuperclass());
 //getGenericSuperclass()获得带有泛型的父类
 //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
 Type type=clazz.getGenericSuperclass();
 System.out.println(type);
 //ParameterizedType参数化类型,即泛型
 ParameterizedType p=(ParameterizedType)type;
 //getActualTypeArguments获取参数化类型的数组,泛型可能有多个
 Class c=(Class) p.getActualTypeArguments()[0];
 System.out.println(c);
 }
 }


输出结果:

class com.test.Person
com.test.Person<com.test.Student>
class com.test.Student

import java.lang.reflect.*;

public class ClassDemo {

   public static void main(String []args) {         
          
     ClassDemo d = new ClassDemo();
     Class c = d.getClass();
          
     Type[] t = c.getGenericInterfaces();
     if(t.length != 0) {
        for(Type val : t) {
           System.out.println(val.toString());
        }
     }
     else {
        System.out.println("Interfaces are not implemented...");
     }
   }
} 

输出结果:

Interfaces are not implemented...

二.Field相关

主要的方法:

getType(): 获取属性声明时类型对象(返回class对象)

getGenericType() : 返回属性的泛型类型

getName() : 获取属性声明时名字

getAnnotations() : 获得这个属性上所有的注释

getModifiers() : 获取属性的修饰

isEnumConstant() : 判断这个属性是否是枚举类

isSynthetic() : 判断这个属性是否是 复合类

get(Object obj) : 取得obj对象这个Field上的值

set(Object obj, Object value) : 向obj对象的这个Field设置新值value

见下例:

实体类:

import java.util.List;
 
import javax.persistence.Entity;
import javax.persistence.Table;
 
import test.enu.RoleType;
 
@Entity
@Table(schema = "public")
public class Role extends AbsEntity implements IEntity{
    public String roleName;
     
    public String userId;
 
    public List<User> children;
     
    private RoleType roleType = RoleType.Manager;
     
    private User user;
     
    public Role() {}
     
    private Role(String roleName) {
        this.roleName = roleName;
    }
    public String getRoleName() {
        return roleName;
    }
 
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
 
    public String getUserId() {
        return userId;
    }
 
    public void setUserId(String userId) {
        this.userId = userId;
    }
 
    public String getDisplayString() {
        System.out.println("I am a Role");
        return "Role";
    }
     
}

public enum RoleType{
    Manager,Employee;
}

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
 
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.GenericGenerator;
 
@Entity
@Table(name = "users", schema = "public")
public class User {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid.hex")
    @Column(length = 40)
    @AccessType("property")
    private String id;
     
    private String loginName;
     
    private String password;
     
    private String address;
     
    @ManyToOne
    private Role role;
 
    public String getId() {
        return id;
    }
 
    protected void setId(String id) {
        this.id = id;
    }
 
    public String getLoginName() {
        return loginName;
    }
 
    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
 
    public Role getRole() {
        return role;
    }
 
    public void setRole(Role role) {
        this.role = role;
    }
}


测试类:

 
import static java.lang.System.out;
 
import java.lang.reflect.Field;
 
import javassist.Modifier;
import test.model.Role;
 
public class FieldTest {
    enum Color {
        Blue,
        Red
    }
     
    class Inner {
    }
     
    public static void main(String args[]) {
        Role role = new Role();
        role.setId("role1");
        role.setUserId("user1");
        role.setRoleName("Role 1");
         
        Field idField =  getDeclaredField(role.getClass(), "id");
        Field childrenField =  getDeclaredField(role.getClass(), "children");
        Field roleTypeField =  getDeclaredField(role.getClass(), "roleType");
        Field userField =  getDeclaredField(role.getClass(), "user");
         
        //获取属性声明时类型对象(返回class对象)
        System.out.println(idField.getType());
        //返回属性声的Type类型
        System.out.println(idField.getGenericType());
        //如果属性是一个泛型,从getType只能得到这个属性的接口类型
        System.out.println(childrenField.getType());
        //如果属性是一个参数化类型,从getGenericType还能得到这个泛型的参数类型
        System.out.println(childrenField.getGenericType());
        //获取属性声明时名字
        System.out.println(idField.getName());
        //获得这个属性上所有的注释
        System.out.println(idField.getAnnotations().length);
        //获取属性的修饰
        System.out.println(Modifier.toString(idField.getModifiers()));
         
        //判断这个属性是否是枚举类
        System.out.println(roleTypeField.isEnumConstant());
        //判断这个属性是否是 复合类
        System.out.println(userField.isSynthetic());
        //FieldTest$Color是Color枚举类编译后的名字。
        isSyntheticOrEnumConstant("test.fortest.FieldTest$Color");
        //FieldTest$Inner是Inner类编译后的名字。
        isSyntheticOrEnumConstant("test.fortest.FieldTest$Inner");
        try {
            //取得对象这个Field上的值
            System.out.println(idField.get(role));
            //向对象的这个Field重新设置值
            idField.set(role, "role2");
            System.out.println(idField.get(role));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
         
    }
     
    public static Field getDeclaredField(final Class cla, final String fieldName) {
        for (Class superClass = cla; superClass != null; superClass = superClass.getSuperclass()) {
            try {
                return superClass.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
//              e.printStackTrace();
            }
        }
        return null;
    }
     
    public static void isSyntheticOrEnumConstant (String completePackageName) {
        try {
            Class<?> c = Class.forName(completePackageName);
            Field[] flds = c.getDeclaredFields();
            for (Field f : flds) { 
                out.format("%-8s [ synthetic=%-5b enum_constant=%-5b ]%n",
                        c.getName() + ":" + f.getName(), f.isSynthetic(), f.isEnumConstant()); 
            } 
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

class java.lang.String

class java.lang.String
interface java.util.List
java.util.List<test.model.User>
id
5
public
false
false
test.fortest.FieldTest$Color:Blue [ synthetic= false enum_constant= true  ]
test.fortest.FieldTest$Color:Red [ synthetic= false enum_constant= true  ]
test.fortest.FieldTest$Color:ENUM$VALUES [ synthetic= true  enum_constant= false ]
test.fortest.FieldTest$Inner: this $ 0 [ synthetic= true  enum_constant= false ]
role1
role2e

都很简单,我觉得主要注意的是getType与getGenericType的区别即可。今天就到这吧,这种不太费脑的文章最适合睡前看一下了。各位攻城狮们晚安~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值