找到java代码中没有被使用的公用方法
2008-07-27 14:10
573 查看
最近,我打算对我们项目的代码进行清理,准备把一些没有被使用到的公用方法清理掉,但是我在网络找了一遍,像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();
}
}
}
无奈之下,只能直接写代码来实现这个功能,具体代码如下:
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();
}
}
}
相关文章推荐
- 百度语音识别REST API使用方法(含JAVA代码)——不需要集成SDK的方法
- 没有模板代码膨胀的STL:二、使用方法与注意事项
- Java压缩文件工具类ZipUtil使用方法代码示例
- 使用java写一个没有main方法的“Hello World”程序(摘自java核心技术.卷I)
- java代码没有main方法也可以运行!
- 在windows开发环境中,java代码中使用linux格式路径的方法需要注意的问题
- java使用Scanner类循环从控制台中获取数据的方法代码。
- Eclipse恢复已删除的文件和代码、svn使用了还原,但本地的没有提交找回没提交代码的方法
- 使用 Protocol Buffer 3 生成 gRPC Java 代码方法
- Myeclipse2015 Jrebel插件的安装、配置、使用(新建.java文件、给类添加新方法、新属性、修改代码等,不用重启tomcat即可更新)
- Java代码使用正则验证和常用工具方法
- 阿里开发的Java代码规约扫描eclipse插件安装和使用方法
- Eclipse恢复已删除的文件和代码、svn使用了还原,但本地的没有提交找回没提交代码的方法
- Java代码优化--尽可能地使用stack(栈)变量(方法内部的局部变量)
- Java使用反射的方法加载类的具体代码
- Java代码优化--尽可能地使用stack(栈)变量(方法内部的局部变量)
- 使用Java代码操作MongoDB(CRUD)方法一
- [Java代码] exe4j的使用方法(java把jar包打成exe) (转载)
- java定时器timer的使用方法代码示例
- 这么详细的分类 Java源代码网站你见过没有? Java中的每一个方法,每一个操作,每一个函数,每一个类.每一个属性,每一个事件都有相应的范例代码