1.main方法中的测试代码
Set<Fruit> s = new HashSet<Fruit>(); s.add(new Peach()); User user = (User) c.getDeclaredConstructor(Integer.class , String.class , boolean.class , Set.class , long.class , String.class , boolean.class , String.class , boolean.class) .newInstance(11 , "XIAOMING" , false , s , 123456789 , "XM" , true , "很高-->像姚明一样高" , true); System.out.println(user.toString()); //调用方法,在反射中实现toString方法功能 Field[] fs = c.getDeclaredFields(); StringBuilder sb = new StringBuilder(); sb.append(c.getSimpleName()).append(" ["); for(int i = 0 ; i < fs.length ; i++){ Method m= getMethod(fs[i] , c); if(m != null){ sb.append(fs[i].getName()).append("="); sb.append(m.invoke(user)); sb = (i == fs.length -1 )?sb.append("]"):sb.append(", "); } } System.out.println(sb.toString().equals(user.toString()));//true
2.生成get方法
public static Method getMethod(Field f , Class<?> c) throws NoSuchMethodException, SecurityException{ String fName = f.getName(); String methodName = "get"; Type type = f.getGenericType(); if(type == boolean.class || type == Boolean.class){ fName = fName.startsWith("is")?fName.replaceFirst("is", ""):fName; fName = fName.length()==0?"is":fName; methodName = "is"; } methodName += fName.substring(0, 1).toUpperCase() + fName.substring(1); System.out.println(methodName); Method m = null; try{ m = c.getDeclaredMethod(methodName); }catch(Exception e){ if((type == boolean.class || type == Boolean.class)){ methodName = "get" + methodName.substring(2); m = c.getDeclaredMethod(methodName); } } return m; }
3.生成set方法
public static Method setMethod(Field f , Class<?> c) throws NoSuchMethodException, SecurityException{ String fName = f.getName(); String methodName = "set"; methodName += fName.substring(0, 1).toUpperCase() + fName.substring(1); Method m = c.getDeclaredMethod(methodName); return m; }从上面的小例子可以看出,利用反射,在程序的运行过程中,完成了对一个类的结构分析,通过获得类的域、调用类的方法等操作,模拟出了toString方法的功能。
反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵Java代码的程序。能够分析类能力的程序称为反射(reflective)。
反射机制的功能极其强大,在下面可以看到,反射机制可以用来:
在运行中查看对象
在运行中分析类的能力
实现通用的数组操作代码
利用Method对象
反射是一种功能强大且复杂的机制。使用它的主要人员是工具构造者,而不是应用程序员。
在java.lang.reflect包中有三个类Field、Method、Constructor和接口Annotation分别用于描述类的域、方法、构造器和类注解。Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。所以在Field、Method、Constructor三个类中都有getAnnotation方法。
检查类的结构主要使用的Field、Method和Constructor这三个类,三者都有一个叫做getName的方法,用来返回对应的名称。Field类有一个getType方法,用来返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用情况。另外还可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifiers返回的整型数值。
Class类中的getFields、getMethods、getConstructors方法分别返回类提供的public域、方法和构造器,其中包括超类的公有成员。Class类的getDeclareFields、getDeclareMethods、getDeclareConstructors方法分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。
1.User.java
package com.gos.java.standard; import java.io.Serializable; import java.util.Set; import javax.persistence.Entity; @Entity(name="user") public final class User extends Person implements Serializable{ private static final long serialVersionUID = 1L; private Integer userId; private String cname; private boolean sex; private Set<Fruit> loveFruits; private long idNo; private String phoneticize; private boolean isMarr; private String isTall; private boolean is; public boolean getIs() { return is; } public void setIs(boolean is) { this.is = is; } public String getIsTall() { return isTall; } public void setIsTall(String isTall) { this.isTall = isTall; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public boolean isSex() { return sex; } public void setSex(boolean sex) { this.sex = sex; } public Set<Fruit> getLoveFruits() { return loveFruits; } public void setLoveFruits(Set<Fruit> loveFruits) { this.loveFruits = loveFruits; } public long getIdNo() { return idNo; } public void setIdNo(long idNo) { this.idNo = idNo; } public String getPhoneticize() { return phoneticize; } public void setPhoneticize(String phoneticize) { this.phoneticize = phoneticize; } @Override public String toString() { return "User [userId=" + userId + ", cname=" + cname + ", sex=" + sex + ", loveFruits=" + loveFruits + ", idNo=" + idNo + ", phoneticize=" + phoneticize + ", isMarr=" + isMarr + ", isTall=" + isTall + ", is=" + is + "]"; } public User(Integer userId, String cname, boolean sex, Set<Fruit> loveFruits, long idNo, String phoneticize) { super(); this.userId = userId; this.cname = cname; this.sex = sex; this.loveFruits = loveFruits; this.idNo = idNo; this.phoneticize = phoneticize; } public User() { super(); } public User(Integer userId, String cname) { super(); this.userId = userId; this.cname = cname; } public void run(){ if(cname != null) System.out.println(this.cname + " is running!"); } public boolean isMarr() { return isMarr; } public void setMarr(boolean isMarr) { this.isMarr = isMarr; } public User(Integer userId, String cname, boolean sex, Set<Fruit> loveFruits, long idNo, String phoneticize, boolean isMarr, String isTall, boolean is) { super(); this.userId = userId; this.cname = cname; this.sex = sex; this.loveFruits = loveFruits; this.idNo = idNo; this.phoneticize = phoneticize; this.isMarr = isMarr; this.isTall = isTall; this.is = is; } }
2.Test.java#main
//Class常用方法及与常用类的方法 /** * 1.获取名称、类信息 * 2.获取属性信息 * 3.获取方法信息 * 4.生成类实例 * 5.类型判断 * 6.调用方法 * 7.读取注释的信息 */ //获取名称及类的相关信息 Class c = User.class; String canonicalName = c.getCanonicalName();//com.gos.java.standard.User String name = c.getName();//com.gos.java.standard.User String simpleName = c.getSimpleName();//User System.out.println(Modifier.toString(c.getModifiers()));//public final 也就是对应的类的声明中class关键字之前的关键字 System.out.println(c.getPackage());//package com.gos.java.standard System.out.println(c.getSuperclass());//class com.gos.java.standard.Person //获取注解及信息 Entity anno = (Entity) c.getAnnotation(Entity.class); System.out.println(anno.name());//user //获取属性信息 Field[] fields = c.getDeclaredFields(); for(Field f:fields){ String fName = f.getName();//获得每个属性的名称 Type type = f.getType();//获取每个属性的类型 //……接下来的代码可能就是根据不同数据类型进行不同的处理流程 } //获取具体的某个属性 System.out.println(c.getDeclaredField("sex"));//private boolean com.gos.java.standard.User.sex //获取方法信息 Method[] methods = c.getDeclaredMethods(); for(Method m : methods){ System.out.println(m.getName());//获得每个方法的名称 } //获得某个具体的方法 System.out.println(c.getDeclaredMethod("isSex"));//public void com.gos.java.standard.User.setSex(boolean) //生成实例 //User user = (User)c.newInstance();//生成一个空的实例,在User中需要提供午餐构造器,或是不提供任何构造器(此时默认无参构造器)
Class:http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/Class.html
Field:http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/reflect/Field.html
Method:http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/reflect/Method.html
Constructor:http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/reflect/Constructor.html
Annotation:http://tool.oschina.net/uploads/apidocs/jdk-zh/java/lang/annotation/Annotation.html