码迷,mamicode.com
首页 > 编程语言 > 详细

Java获取指定类的内部结构

时间:2021-01-18 10:39:30      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:成员   package   lse   返回值   array   types   参数   length   一个   

Java获取指定类的内部结构

1、通过反射机制实现自定义类的反编译实现。反编译就是将class文件内容通过反射获取所有的内容后写入到一个java源代码文件中。

package homework;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.Arrays;

public class Work {

	public static void main(String[] args) throws Exception {
		// 获取类文件
		Class c = Class.forName("java.lang.String");
//		getConstructor(c);
//		System.out.println(getFields(c));
//		System.out.println(getMethods(c));
		StringBuffer sb = new StringBuffer();
		//将包名拼接
		sb.append(getPackage(c));
		//将修饰符拼接
		sb.append(Modifier.toString(c.getModifiers()) + " class ");
		//将类名拼接
		sb.append(c.getSimpleName() + " ");
		//将接口进行拼接
		sb.append(getInterface(c));
		sb.append("{\n");
		//将属性,构造方法和方法全部拼接
		sb.append(getFields(c)).append(getConstructor(c)).append(getMethods(c));

		sb.append("}");
		
		System.out.println(sb);
		//生成的目标文件
		File f = new File("target.java");
		FileWriter fw = new FileWriter(f);
		//将所有字符写出
		fw.write(sb.toString());

		//fw.flush();
		 fw.close();

	}

	/**
	 * 
	 * @Description: 获取指定类的所有构造方法
	 * @author LYL
	 * @date 2021-01-16 15:16:13
	 */
	public static String getConstructor(Class c) {
		// 拿到所有构造方法组成的数组
		Constructor[] ct3 = c.getConstructors();
		// 创建一个字符串缓冲池
		StringBuffer sb = new StringBuffer();
		// 循环遍历所有构造方法
		for (Constructor cc : ct3) {
			// 将构造方法修饰符拼接进入sb
			sb.append(Modifier.toString(cc.getModifiers())).append(" ");
			// 将构造方法名拼接进入sb
			sb.append(cc.getName().substring(cc.getName().lastIndexOf(".") + 1));
			// 将构造方法的左括号拼接进入sb
			sb.append("(");
			// 拿到当前构造方法的所有参数
			Parameter[] pt = cc.getParameters();
			// 如果当前构造方法有参数
			if (pt.length > 0) {
				// 遍历当前构造方法的参数
				for (Parameter par : pt) {
					// 将当前构造方法的参数类型名拼接
					sb.append(par.getType().getSimpleName()).append(" ");
					// 将当前参数类型对应的参数名进行拼接
					sb.append(par.getName()).append(",");
				}
				// 删除最后拼接进去的逗号
				sb.deleteCharAt(sb.length() - 1);
			}
			// 将右括号进行拼接
			sb.append(")");
			// 将左大括号拼接并换行再拼接右大括号,最后再换行
			sb.append(" {").append("\n}\n");
		}
		// 在构造方法最下方换行以和其它方法分开
		sb.append("\n");
		// 将拼好的构造方法字符串返回
		return sb.toString();
	}

	/**
	 * 
	 * @Description: 获取指定类的所有属性
	 * @author LYL
	 * @date 2021-01-16 15:16:41
	 */
	public static String getFields(Class c) {
		// 拿到属性数组
		Field[] fields = c.getDeclaredFields();
		StringBuffer sb = new StringBuffer();
		// 循环遍历所有的属性
		for (Field f : fields) {
			// 拼接属性的修饰符,如: public final static
			sb.append(Modifier.toString(f.getModifiers())).append(" ");
			// 拼接属性的类型名,如:String
			sb.append(f.getType().getSimpleName()).append(" ");
			// 拼接属性名,如:String name中的name
			sb.append(f.getName()).append(";");

			sb.append("\n");
		}
		// 属性拼接完以后多加两个换行,以和其它的方法隔出一段距离
		sb.append("\n");
		sb.append("\n");
		return sb.toString();
	}

	/**
	 * 
	 * @Description: 获取指定类所有的方法
	 * @author LYL
	 * @date 2021-01-16 15:21:24
	 */
	public static String getMethods(Class c) {
		StringBuffer sb = new StringBuffer();
		// 拿到该类的所有方法
		Method[] methods = c.getMethods();
		// 遍历所有的方法
		for (Method md : methods) {
			// 拼接权限修饰符
			sb.append(Modifier.toString(md.getModifiers())).append(" ");
			// 添加返回值类型
			sb.append(md.getReturnType().getSimpleName()).append(" ");
			// 添加方法名
			sb.append(md.getName()).append(" ");

			sb.append("(");
			// 拿到方法的所有参数列表
			Parameter[] pt = md.getParameters();
			// 如果该方法有参数
			if (pt.length > 0) {
				// 循环遍历所有参数
				for (Parameter par : pt) {
					// 参数类型名,如:String
					sb.append(par.getType().getSimpleName()).append(" ");
					// 拼接参数名
					sb.append(par.getName()).append(",");
				}
				// 此时在括号里的最后有一个逗号,此步骤为删去最后的那个逗号
				sb.deleteCharAt(sb.length() - 1);
			}

			sb.append(") ");
			// 拿到异常的数组
			Class[] exceptionTypes = md.getExceptionTypes();
			// 如果有抛出异常
			if (exceptionTypes.length > 0) {
				// 拼接throws
				sb.append("throws ");
				// 遍历所有异常类型
				for (int i = 0; i < exceptionTypes.length; i++) {
					// 拼接异常名
					sb.append(exceptionTypes[i].getSimpleName());
				}
			}
			sb.append(" {\n");
			sb.append("}");
			// 每一个方法后换一行
			sb.append("\n");
		}
		// 所有方法拿到以后在方法的最后加入两个换行符,以和其它部分分隔开
		sb.append("\n");
		sb.append("\n");
		return sb.toString();
	}

	/**
	 * 
	 * @Description: 获取指定类的包名
	 * @author LYL
	 * @date 2021-01-16 15:26:37
	 */
	public static String getPackage(Class c) {
		StringBuffer sb = new StringBuffer();
		// 拿到包名
		sb.append(c.getPackage().toString().substring(0, 17));
		// 区分包名部分和其它成员部分
		sb.append("\n");
		sb.append("\n");
		return sb.toString();
	}

	/**
	 * 
	 * @Description: 拿到指定类的接口
	 * @author LYL
	 * @date 2021-01-16 15:27:48
	 */
	public static String getInterface(Class c) {
		StringBuffer sb = new StringBuffer();
		// 拿到指定类的所有接口
		Class[] cc = c.getInterfaces();
		// str用来装接口名
		String str = null;
		// 如果有接口
		if (cc.length > 0) {
			sb.append("implements ");
			// i计算循环到第几次
			int i = 0;
			// 循环遍历所有接口
			for (Class ccs : cc) {
				// 将接口装入str
				str = ccs.toString();
				// 拿到简化后的接口名
				String temp = str.substring(str.lastIndexOf(".") + 1, str.length());
				// 如果是最后一个接口
				if (i == cc.length - 1) {
					// 不在接口名后加“,” 
					sb.append(temp);
					// 如果不是最后一个接口
				} else {
					// 在接口名后方加上一个“,”
					sb.append(temp).append(", ");
				}
				// 计算此次为第几次循环
				i++;
			}
			// 如果没有接口
		} else {
			// 不往其中添加字符串
			sb.append("");
		}

		return sb.toString();
	}

}

Java获取指定类的内部结构

标签:成员   package   lse   返回值   array   types   参数   length   一个   

原文地址:https://www.cnblogs.com/aluna/p/14286176.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!