首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >找到java代码中没有被使用的公用方法

找到java代码中没有被使用的公用方法

作者头像
源哥
发布2018-08-28 11:03:37
1.6K0
发布2018-08-28 11:03:37
举报
文章被收录于专栏:源哥的专栏源哥的专栏

最近,我打算对我们项目的代码进行清理,准备把一些没有被使用到的公用方法清理掉,但是我在网络找了一遍,像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();
  }
 } 
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2008年07月27日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档