庖丁解牛——Java反射解析一个类
来源:互联网 发布:国际数据是什么 编辑:程序博客网 时间:2024/04/30 03:26
认识反射:使用反射实现toString的功能
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;}@Overridepublic 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.UserString name = c.getName();//com.gos.java.standard.UserString simpleName = c.getSimpleName();//UserSystem.out.println(Modifier.toString(c.getModifiers()));//public final 也就是对应的类的声明中class关键字之前的关键字System.out.println(c.getPackage());//package com.gos.java.standardSystem.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
- 庖丁解牛——Java反射解析一个类
- 庖丁解牛TLD(四)——Tracking解析
- 庖丁解牛TLD(四)——Tracking解析 .
- 庖丁解牛TLD(四)——Tracking解析
- java反射机制——解析
- Java反射解析目标类
- java反射读取一个类
- 庖丁解牛TLD(一)——开篇
- 庖丁解牛TLD(一)——开篇 .
- 庖丁解牛——代码段分析
- 庖丁解牛TLD(一)——开篇
- 庖丁解牛TLD(一)——开篇
- java反射机制——解析(2)
- JAVA 反射机制解析
- java反射机制解析
- Java反射机制解析
- Java的反射解析
- java反射机制解析
- 并行程序设计听课笔记
- 看懂这些例子,一天之内学会python2
- Tomcat启动分析
- ServletConfig与ServletContext对象详解
- tcp/ip协议学习笔记
- 庖丁解牛——Java反射解析一个类
- 打勾显示输入的密码(EditText与setTransformationMethod)
- python学习(3)函数式编程
- Occupancy
- iOS 防止UITableViewCell快速重复点击多次响应事件
- LaTeX soul包
- 个人部署maven项目
- ExtJS之Progressbar进度条的手动模式和自动模式。
- eclipse+sdk+adk安卓开发环境部署(全程详解,适合小白)