找到java代碼中沒有被使用的公用方法

來源:互聯網
上載者:User

最近,我打算對我們項目的代碼進行清理,準備把一些沒有被使用到的公用方法清理掉,但是我在網路找了一遍,像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();
  }
 } 
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.