最近,我打算对我们项目的代码进行清理,准备把一些没有被使用到的公用方法清理掉,但是我在网络找了一遍,像PMD,Findbugs等静态工具,都只能找到没有被使用的私有方法。
无奈之下,只能直接写代码来实现这个功能,具体代码如下:
package com;
import java.io.File;
import java.io.FileReader;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
public class FindUnUsedCode {
public static final int TYPE_METHOD = 0; //方法
public static final int TYPE_ATTRIBUTE = 1; //属性
/**
* 类对象
*/
class ClassObject{
public List<String> methods = new ArrayList<String>(); //公用方法集合
public String className; //类名
public List<String> attributes = new ArrayList<String>(); //属性名
}
/**
* 熟悉对象
*/
class MethodObject{
public String methodName; //方法名
}
class UnUsedCode{
public String className; //类名
public String codeName; //方法名或者属性名
public int type; //0:方法名,1:属性名
public String descript; //描述
}
//类集合
private List<ClassObject> classList = new ArrayList<ClassObject>();
//java定义的数据类型
private String[] dataTypes = {"void", "int", "boolean", "long", "char", "float", "double"};
//java定义的访问权限
private String[] callAuths = {"public", "friendly", "protected", "private"};
//java的关键字
private String[] keyWords = {"public", "friendly", "protected", "private", "void", "int", "boolean", "long", "char", "float", "double"
, "{", "}"};
/**
* 检查一个文件名是否java文件
* @param fileName
* @return
*/
private boolean checkIsJava(String fileName)
{
boolean result = false;
if (fileName.lastIndexOf(".java") != -1)
{
result = true;
}
return result;
}
/**
* 分析java文件,返回类对象
* @param fullName
* @return
*/
public ClassObject analyseJavaFile(String path, String fileName) throws Exception
{
//全路径
String fullName = path + "/" + fileName;
//文件对象
File file = new File(fullName);
//创建对象
ClassObject classObject = new ClassObject();
//设置类名
classObject.className = fileName.substring(0, fileName.length()-5);
//得到文件读对象
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
//读取一行数据
String line = "";
do
{
line = randomAccessFile.readLine();
if (line == null)
{
break;
}
else
{
//去掉前后空格
line = line.trim();
}
//System.out.println("line:" + line);
if (line.indexOf(" class ") != -1)
{
//为类定义行,则不处理该行
continue;
}
//判断是否公用对象
if (line.startsWith("public"))
{
//把数据拆分出来
String[] strs = line.split(" ");
//顺序获取数据,从第三个开始读,因为第一个为public,第二个为数据类型,第三个才可能是名字
for (int i = 2; i < strs.length; i++)
{
//判断是否java的关键字
if (isKeyWords(strs[i]))
{
continue;
}
//判断是否以小写字符开始
if (isStartWithLower(strs[i]))
{
//找到是否包含有括号
int loc = strs[i].indexOf("(");
if (loc == -1)
{//不包含扩展
if (strs[i].indexOf(";") == -1)
{//不包含分号
if ((strs.length > (i+1)) && (strs[i+1].indexOf("(") == -1))
{
//下一个数据也不包含括号,那么则是属性
classObject.attributes.add(strs[i]);
break;
}
else
{
//下个数据包含括号,则是方法
classObject.methods.add(strs[i]);
//System.out.println("22222222222222222:" + line);
break;
}
}
else
{
//没有括号,而且已经分号结束了,那么则是属性名
classObject.attributes.add(strs[i].substring(0, strs[i].length() - 1 ));
break;
}
}
else
{
//包含了括号,则是方法
classObject.methods.add(strs[i].substring(0, loc));
//System.out.println("1111111111111111:" + line);
break;
}
}
}
}
}while (line != null);
return classObject;
}
/**
* 判断字符串是否以小写字符开始
* @param str
* @return
*/
public boolean isStartWithLower(String str)
{
return str.startsWith(str.toLowerCase().substring(0, 1));
}
/**
* 判断是否java的关键字
* @param str
* @return
*/
public boolean isKeyWords(String str)
{
return isInculeList(str, keyWords);
}
/**
* 判断是否java的数据类型
* @param str
* @return
*/
public boolean isDataType(String str)
{
return isInculeList(str, dataTypes);
}
/**
* 判断是否java的访问权限类型
* @param str
* @return
*/
public boolean isCallAuth(String str)
{
return isInculeList(str, callAuths);
}
/**
* 判断一个字符串是否在一个数据列表中
* @param str
* @param lists
* @return
*/
public boolean isInculeList(String str, String[] lists)
{
boolean result = false;
//获取java的所有类型
for (int i = 0; i < lists.length; i++)
{
if (lists[i].equals(str))
{
//包含在列表中
result = true;
break;
}
}
return result;
}
/**
* 去类集合
* @param path
* @return
*/
public List<ClassObject> getClassList(String path) throws Exception
{
File file = new File(path);
String[] list = file.list();
//文件名
String fileName = "";
//类对象
ClassObject classObject;
//循环获取数据
for (int i = 0; i < list.length; i++)
{
//得到文件的全路径
fileName = path + "/" + list[i];
//得到文件对象
file = new File(fileName);
//判断是否java文件
if (checkIsJava(list[i]))
{
//得到java数据
classObject = analyseJavaFile(path, list[i]);
if (classObject != null)
{
//增加一个数据
this.classList.add(classObject);
}
}
else if (file.isDirectory())
{//是一个目录
//递归执行
getClassList(fileName);
}
}
return this.classList;
}
/**
* 文件中是否包含某个字符串
* @param fullPath
* @param str
* @return
* @throws Exception
*/
public boolean isIncludeStr(String fullPath, String str) throws Exception
{
List<String> list = new ArrayList<String>();
list.add(str);
return isIncludeStrs(fullPath, list);
}
/**
* 文件中是否包含了知道的字符串
* @param fullPath
* @param strs
* @return
*/
public boolean isIncludeStrs(String fullPath, List<String> strs) throws Exception
{
boolean result = false;
List<String> tempStrs = strs;
//得到文件读对象
RandomAccessFile randomAccessFile = new RandomAccessFile(fullPath, "r");
//读取一行数据
String line = "";
do
{
//读一行
line = randomAccessFile.readLine();
if (line == null)
{
break;
}
else
{
//去掉前后空格
line = line.trim();
}
if ((tempStrs != null) && (!tempStrs.isEmpty()))
{
for (int i = 0; i < tempStrs.size(); i++)
{
//包含改字符串
if (line.indexOf(tempStrs.get(i)) != -1)
{
//去掉该数据
tempStrs.remove(i);
}
}
}
else
{
//已经为空,则表示已经完全匹配了所以字符串,跳出
break;
}
}while (line != null);
if ((tempStrs == null) || (tempStrs.isEmpty()))
{
//完全比配
result = true;
}
return result;
}
/**
* 检查代码是否被使用,0:被使用了,1:没有被使用,2:无法确定
* @param path
* @param className
* @param codeName
* @return
*/
public int checkUsed(String path, String className, String codeName) throws Exception
{
//没有被使用
int result = 1;
File file = new File(path);
//得到列表
String[] list = file.list();
//全路径
String fullPath = "";
List<String> checkList = new ArrayList<String>();
checkList.add(className);
checkList.add(codeName);
if ((list != null) && (list.length > 0))
{
//循环获取数据
for (int i = 0; i < list.length; i++)
{
//如果为同一个类,则不检查
if (list[i].equals(className + ".java"))
{
continue;
}
//得到文件的全路径
fullPath = path + "/" + list[i];
file = new File(fullPath);
//判断是文件还是目录
if (file.isFile())
{
if (isIncludeStrs(fullPath, checkList))
{
//既包含了类名,又包含方法名,则表示该方法,铁定被使用了
return 0;
}
else if (isIncludeStr(fullPath, codeName))
{
//调用了方法,且没有找到类,则无法确定
result = 2;
//继续判断下一个
continue;
}
}
else if (file.isDirectory())
{//是一个目录
//递归执行
checkUsed(fullPath, className, codeName);
}
}
}
return result;
}
/**
* 获取没有被使用的代码
* @param path
* @param className
* @param codeNames
* @param type
* @return
* @throws Exception
*/
public List<UnUsedCode> getUnUsedCode(String path, String className, List<String> codeNames, int type) throws Exception
{
List<UnUsedCode> result = new ArrayList<UnUsedCode>();
UnUsedCode unUsedCode;
if ((codeNames != null) && (!codeNames.isEmpty()))
{
//循环获取属性
for (int j = 0; j < codeNames.size(); j++)
{
String codeName = codeNames.get(j);
//判断是否被使用
int usedType = checkUsed(path, className, codeName);
//没有被使用
if (usedType != 0)
{
//创建对象
unUsedCode = new UnUsedCode();
unUsedCode.className = className; //类名
unUsedCode.codeName = codeName; //属性名
unUsedCode.type = type; //类型为属性
if (usedType == 1)
{
unUsedCode.descript = "没有被使用";
}
else if (usedType == 2)
{
unUsedCode.descript = "无法确定";
}
//增加一条数据
result.add(unUsedCode);
}
}
}
return result;
}
/**
* 得到未使用的代码
* @param path
* @return
*/
public List<UnUsedCode> getUnUsedCode(String path) throws Exception
{
//结果
List<UnUsedCode> result = new ArrayList<UnUsedCode>();
//得到类对象
List<ClassObject> classList = getClassList(path);
ClassObject classObject;
List<UnUsedCode> unUsedAttrList;
List<UnUsedCode> unUsedMethodList;
//数据不为空
if ((classList != null) && (!classList.isEmpty()))
{
//循环获取数据
for (int i = 0; i < classList.size(); i++)
{
//获取一个数据
classObject = classList.get(i);
//得到一个类中没有使用的属性列表
unUsedAttrList = getUnUsedCode(path, classObject.className, classObject.attributes, TYPE_ATTRIBUTE);
if ((unUsedAttrList != null) && (!unUsedAttrList.isEmpty()))
{
//增加数据
result.addAll(unUsedAttrList);
}
//得到一个类中没有使用的属性列表
unUsedMethodList = getUnUsedCode(path, classObject.className, classObject.methods, TYPE_METHOD);
if ((unUsedMethodList != null) && (!unUsedMethodList.isEmpty()))
{
//增加数据
result.addAll(unUsedMethodList);
}
}
}
return result;
}
public static void main(String[] args)
{
FindUnUsedCode findUnUsedCode = new FindUnUsedCode();
try
{
List<UnUsedCode> list = findUnUsedCode.getUnUsedCode("C:/com");
if ((list != null) && (!list.isEmpty()))
{
for (int i = 0; i < list.size(); i++)
{
UnUsedCode unUsedCode = list.get(i);
System.out.println(unUsedCode.className + "." + unUsedCode.codeName
+ " " + (unUsedCode.type==TYPE_METHOD?"方法":"属性") + " " + unUsedCode.descript);
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有