看开源项目源代码或者看项目源码的时候,常常觉得代码看起来比较啰嗦,总觉得有些的应该可以简化的。
比如:
1 过多的getter、setter 这些显然是没技术含量的,但是它夹杂在类的其他代码中,影响了阅读。我的做法是把去掉其getter、setter,然后它直接改为public 变量。——虽然这有违java封装原则,但是我想这却是有利于代码阅读的。。
2 过多的注释,一些开源项目往往就是大版大版的注释,注释多是好是坏姑且不论,但是有时候我们只是想看源码,不想看注释,这个时候它就非常讨嫌了!
3 过多的try catch 等异常扑捉。 这显然也是影响阅读的,试想,如果关键代码就那么一行一个方法20个字符之内,外面却包了3、4个try catch,多烦人啊,最后还有finally。。。 当然,如果想详细了解源码,彻底弄明白其功能,仔细阅读try catch是有必要的,但有时候,我们只想快速的、大致的阅读一下源码,这个时候也有必要简化一下那个类了。
4 日志,一般来说,日志只是处理调试信息、警告信息、异常信息等用的, 去掉它并不影响功能
5 注解 有些annotation并不是必须的,去掉完全不影响阅读,比如:@Override、@SuppressWarnings..等
众所周知,看源码并不是一件简单的事,因为,我们常常没有那个对应的UML图,功能说明啊等。(不知道为什么都这样。。。)
要是能简化代码,那么再来阅读就会轻松多了!本想这么个简单的功能,别人应该已经做出来了的。可是,我网上搜索却总也找不到。——难道大家都没有这方面的考虑吗??
困扰了我很久,今天有点时间,想起这事,于是自己写了一个简单实现:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Stack; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.luobk.po.VarObject; /** * 代码阅读优化器 CodeSimplifier或者也可以称为 CodePurifier吧 * goSimplifyProject 只针对 目录 * 若是 想直接的simplify一个java文件,则用simplifyFile即可 * */ public class CodeSimplifier { // public static String SOURCE_DIR = "D:\\WS\ABC\\src"; public static String SOURCE_DIR = "D:\\WS\\CodeSimplifier\\src"; public static String DEST_DIR = "D:\\WS\\CodeSimplifier\\src3"; public static String SOURCE_FOLDER = "src"; public static String LOGGER_NAME = "log"; public static boolean USE_SOURCE_FOLDER = false; /** * * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub goSimplifyProject(SOURCE_DIR,DEST_DIR); // simplifyFile(new File(SOURCE_DIR), DEST_DIR); // System.out.println("sfasf".matches("[.]+")); // System.out.println("asf " + // "a\" f艾丝凡 f\nasf\nnnbbsa;\"aa".matches("a\"(.|\\s)*;\"aa")); // System.out.println("\n".matches("(\\s+)")); // System.out.println("sfasf".matches(".*asf")); // .+ 。* 是可以自动伸缩的 , 默认的 。。。 非贪婪模式?? // String ss = "System.out. println(\"sfas r asfa fas \");\n" + // "System.out. println(\"sfas + \n asfa fas \");"; // System.out.println("ss . replaceAll : "+ss. // replaceAll("\\s+System\\s*\\.\\s*out\\s*\\.\\s*print(ln)?\\s*\\(\\s*\"(.|\\s)*\"\\s*\\)\\s*;","")); // StringBuffer sb = new StringBuffer("abcdef\nxyz\n>"); // sb.deleteCharAt(sb.length()-1); // System.out.println("matches++ = "+"sfaaf".matches(".{6}"));// + 后面的 {n} 失效 // System.out.println("matches++ = "+"fasf \n}".matches(".+")); // 匹配任何字符包括' ',但是不包括 \n等 // System.out.println("sfaf>s]f[s.".replaceAll("]","A"));// 到底要不要转义 [] 啊!! // sb.reverse 有用的方法!是String 没有提供的! // String filePath = "D:\\iEMPWorkspaces\\CodePurifier\\src\\po\\"; // String projectPath = "D:\\iEMPWorkspaces\\CodePurifier\\src2\\Bootstrap.java"; // String destDir = "D:\\iEMPWorkspaces\\CodePurifier\\src3\\"; // System.out.println("ddasfasf aa\n = asf qwf".replaceAll("\\s{2}", "X")); // System.out.println("ddasfasf aa\n = 2asf qwf".replaceAll("\\s[2]", "X")); // System.out.println(capitalize("asfaf")); // File f = new File("D:\\iEMPWorkspaces\\CodePurifier\\src2\\sdaf.java"); // f.mkdir(); // FileOutputStream fos = new FileOutputStream(f); // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos)); // bw.write(destDir);// if we don't write sth , the file will never be created,just in mem. // bw.close(); // System.out.println("f.length()=="+f.length()+" f.exists();===+"+f.exists()); // System.out.println(" is DIR == "+ f.getCanonicalPath()+"\\"+f.getName()); } public static void goSimplifyProject(String projectPath,String destprojectPath) throws IOException { File destProjectDir = new File(destprojectPath); if(!destProjectDir.exists())destProjectDir.mkdir(); if(!projectPath.endsWith("\\")) projectPath = projectPath + "\\"; if(!destprojectPath.endsWith("\\")) destprojectPath = destprojectPath + "\\"; File sourceDir = null; if(USE_SOURCE_FOLDER)sourceDir = new File(projectPath+SOURCE_FOLDER+"\\"); else sourceDir = new File(projectPath); simplifyProject(sourceDir,destprojectPath,true); } public static void simplifyProject(File fileOrDir,String destDir,boolean isRoot) throws IOException { if(fileOrDir.isDirectory()) { /** 此种过滤行不通! FilenameFilter filter = new FilenameFilter() { private String type = ".java"; @Override public boolean accept(File dir, String name) { //return true; return name.endsWith(type); } };*/ File[] files = fileOrDir.listFiles(); for (int i = 0; i < files.length; i++) { File file = files[i]; if(isRoot) { if(USE_SOURCE_FOLDER)destDir = destDir+SOURCE_FOLDER+"\\"; File destRootDir = new File(destDir); if(!destRootDir.exists())destRootDir.mkdir(); simplifyProject(file,destDir,false); }else { // Build the new directory,othewise we'll got: //"java.io.FileNotFoundException: D:\iEMPWorkspaces\CodePurifier\src2\po\Sdfa.java (系统找不到指定的路径。)" //System.out.println("lastDir=="+lastDir); String lastDir = fileOrDir.getName(); File directory = new File(destDir+lastDir); if(!directory.exists())directory.mkdir(); simplifyProject(file,destDir+lastDir+"\\",false); } } }else if(fileOrDir.isFile()){ if(fileOrDir.getName().endsWith(".java"))simplifyFile(fileOrDir,destDir); } } /** * * FOR JAVA FILE ONLY CURRENTLY * * REMOVE THE COMMENTS AND THE GETTER/SETTER, AND CHANGE THE MODIFIRE OF RALATED ONE TO 'PUBLIC' * * ASSUME THAT THE GETTER/SETTER USES PARAMETER AS THE SAME NAME OF THE VARAIBLE * * THATS ALL * * @param file * @throws IOException */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static void simplifyFile(File file,String destDir) throws IOException { FileInputStream fis = new FileInputStream(file); System.out.println(file.getAbsolutePath()); String outputFile = destDir+file.getName(); //System.out.println("output FIle Path"+outputFile); FileOutputStream fos = new FileOutputStream(new File(outputFile));// assume the outputFile is not the input one BufferedReader br = new BufferedReader(new InputStreamReader(fis)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos)); boolean isComments = false; boolean isEmptyRow = false; String line = ""; String oline = ""; List privateVars = new ArrayList(); StringBuffer sb = new StringBuffer(); while((line=br.readLine())!=null) { oline = line; line = line.trim().replaceAll("\\s+", " "); // white line if("".equals(line)) { continue; } // 去掉注释 //if(isComments&&!(line.endsWith("*/"))&&!line.endsWith("*/ "))continue; //TODO 暂不考虑 行中/*前面还有代码的情况 // 眼考虑 /* */在同一行的情况,—— 如果*/后面还有内容,则不管了 ! if(line.startsWith("/*")&&(line.endsWith("*/")||line.endsWith("*/ "))) { continue; } if(line.startsWith("/*")) { isComments = true; continue; } if(isComments&&!line.endsWith("*/")&&!line.endsWith("*/ ")) {//line.startsWith("*")&& //ifComments = true; continue; } //TODO 暂不考虑 行中*/后面还有代码的情况 if(line.endsWith("*/")||line.endsWith("*/ ")) { //System.out.println("line : "+line); isComments = false; continue; } if(line.startsWith("//")) { continue; } String[] strs = line.replace(';', ' ').trim().split(" "); if(line.startsWith("private ") &&strs.length==3 && line.endsWith(";")) { //line = line.replaceFirst("private", "public"); //oline = oline.replaceFirst("private", "public"); VarObject vo = new VarObject(); vo.setVar(strs[2]); vo.setType(strs[1]); privateVars.add(vo); } String regex = "\\s*[\\}\\)\\]>]\\s*"; if(oline.matches(regex)) { if(isEmptyRow) { sb.deleteCharAt(sb.length()-1); sb.append(line+"\n"); } else sb.append(oline+"\n"); isEmptyRow = true; }else { isEmptyRow = false; sb.append(oline+"\n"); } } br.close(); String ret = sb.toString(); System.out.println("Before:\n" + ret); //ret = ret.replaceAll("\\) ",")").replaceAll("\\s?\\(\\s+\\)\\s?", "()");//.replaceAll("\n", ""); ret = filterGetterSetters(ret, privateVars); ret = filterLogs(ret); ret = filterAnnotations(ret); ret = filterTryCatchs(ret); bw.write(ret); bw.close(); System.out.println("After:\n" + ret); } // 无止境的 CLRF 空字符。。。 \\s* 繁琐。。。 private static String filterAnnotations(String str) { String regex = "((@\\s*Override)|(@\\s*SuppressWarnings\\s*\\(.*\\)))\\s*"; str = str.replaceAll(regex, ""); return str; } private static String filterGetterSetters(String str,List privateVars) { for (Iterator iterator = privateVars.iterator(); iterator.hasNext();) { VarObject vo = (VarObject) iterator.next(); String getterRegEx = "\\s+public\\s+"+vo.getType()+"\\s+get"+capitalize(vo.getVar())+"\\s*\\(\\s*\\)\\s*\\{\\s*return\\s+"+vo.getVar()+"\\s*;\\s*\\}"; String setterRegEx = "\\s+public\\s+void\\s+set"+capitalize(vo.getVar())+"\\(\\s*" +vo.getType()+"\\s+\\w+\\s*\\)\\s*\\{\\s*(this\\.)?"+vo.getVar()+"\\s*=\\s*\\w+;\\s*\\}"; Matcher mgetter = Pattern.compile(setterRegEx).matcher(str); Matcher msetter = Pattern.compile(getterRegEx).matcher(str); if(mgetter.find() && msetter.find()){ str = mgetter.replaceAll(""); str = msetter.replaceAll(""); str = str.replaceFirst("private\\s+"+vo.getType()+"\\s+"+vo.getVar(), "public "+vo.getType()+" "+vo.getVar()); //oline = oline.replaceFirst("private", "public"); } } return str; } // TODO 要考虑 log 里面内容换行的情况 。 // TODO 要考虑 System.out.println 里面内容换行的情况 ,但是 如果 是 System.\n out\n .println的情况就不管了,实在太繁琐。。。。。 private static String filterLogs(String str) { String regexLog = "\\s+((private)|(public))\\s+.+log\\s+=\\s+Logger\\.getLogger.+;"; String regex = LOGGER_NAME+"\\s*\\.\\s*((debug)|(warn)|(error)|(fatal)|(finest)|(finer)|(fine)|(warning)|(severe))\\s*\\(\\s*\".*\"\\s*\\)\\s*;\\s*"; //String regex = "log\\s*\\.\\s*[(fine)|(severe)]"; //String regex4Javalog = "^log\\s*\\.\\s*[(finest)(finer)(fine)(warning)(severe)]\\s*\\(\\s*\".*\"\\s*\\)\\s*;"; str = str.replaceAll(regexLog, "").replaceAll(regex, ""); //if(Pattern.compile(regex).matcher(str).find()) { //} // TODO (.|\\s)*此处引起异常 //str = str.replaceAll("\\s+System\\s*\\.\\s*out\\s*\\.\\s*print(ln)?\\s*\\(\\s*\"(.|\\s)*\"\\s*\\)\\s*;", ""); return str; } // 太复杂, 而且可能影响原功能,所以,只做简单处理。。 这显然是会影响原有功能的!! private static String filterTryCatchs(String str) { // TODO String regexTry = "";//"try\\s*\\{\\s*";// 暂不处理 String regexCatch = "\\}\\s*catch\\s*\\(\\s*\\w+\\s+\\w+\\s*\\)\\s*\\{\\s*.+\\s*"; String regexFinally = "";//"\\s*\\}\\s*finally\\s*\\{\\s*.+\\s*\\}";// 暂不处理 //str = str.replaceAll(regexTry, "").replaceAll(regexCatch, "").replaceAll(regexFinally, ""); // if(Pattern.compile(regexCatch).matcher(str).find()) { str = str.replaceAll(regexCatch, " }catch(Exception e){e.printStackTrace();"); } return str; } // 将 }\n } \n ) \n) ... 的情况合并成 } } ) )... private static String foldEmptyRow(String str) { // TODO return str; } public static String capitalize(String str) { if(str==null)return ""; if(str.length()==1)return str.toUpperCase(); Character firstLetter = str.charAt(0); return Character.toUpperCase(firstLetter)+str.substring(1); } @SuppressWarnings("unchecked") public static boolean checkParetheis(String str) { Matcher matcher = Pattern.compile("[\\(\\{\\[<\\)\\}\\]>\"\']").matcher(str); Pattern p = Pattern.compile("[\\)\\}\\]>\"\']"); Stack stack = new Stack<>(); while(matcher.find()) { String c = matcher.group(); if(p.matcher(c).matches()) { if(stack.size()>0){ char top = ((String) stack.peek()).charAt(0); if(c.charAt(0)==converseChar(top)) { stack.pop(); }else { stack.push(c); } }else { stack.push(c); } }else { stack.push(c); } } System.out.println("stack remains :" +stack.toString()); if(stack.size()>0)return false; return true; } @SuppressWarnings("unchecked") public static boolean checkParetheis(File f) { if(f.exists()) { FileInputStream fis = null; try { fis = new FileInputStream(f); char c = 'a'; int ifEnd = 0; Stack stack = new Stack<>(); while((ifEnd=fis.read())!=-1) {// -1 是可以转换为char的,但是 转换之后 c 已经不再是 -1 !!! c = (char)ifEnd; System.out.print(c); if(c=='('||c=='{'||c=='<'||c=='[')stack.push(c); else if(c==')'||c=='}'||c=='>'||c==']') { char top = (char) stack.peek(); if(c==converseChar(top)) { stack.pop(); }else { stack.push(c); } }else if(c=='"'||c=='\'') { if(stack.size()>0){ char top = (char) stack.peek(); if(c==converseChar(top)) { stack.pop(); }else { stack.push(c); } }else { stack.push(c); } } } System.out.println("ifEnd :"+ifEnd+" c :"+ (char)(-1)); if(stack.size()==0)return true; System.out.println("stack remains :" +stack.toString()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return false; } public static char converseChar(char c) { if(c=='(')return ')'; if(c=='{')return '}'; if(c=='<')return '>'; if(c=='[')return ']'; if(c=='"')return '"'; if(c=='\'')return '\''; return ' '; } }
VarObject是一个简单javaBean:
package com.luobk.po; /** * * @author LBK * */ public class VarObject { public String getVar() { return var; } public void setVar(String var) //dsfs { this.var = var; } public String getType( ) { return type; } public void setType(String v) { type = v; } // var name private String var; // var type private String type; }
写是写出来了,但是还是有很多问题。 比如对try catch块到底如何处理比较好? 对于简单行(单字符行)的处理的处理怎么样才好?而且,程序本身有bug,有些地方只是做了简单处理,复杂情况下则引发bug。而且,没有考虑对其他的类的影响...
相关推荐
基于springboot大学生就业信息管理系统源码数据库文档.zip
基于java的驾校收支管理可视化平台的开题报告
时间序列 原木 间隔5秒钟 20241120
毕业设计&课设_基于 Vue 的电影在线预订与管理系统:后台 Java(SSM)代码,为毕业设计项目.zip
基于springboot课件通中小学教学课件共享平台源码数据库文档.zip
基于java的网上购物商城的开题报告
Delphi人脸检测与识别Demo1fdef-main.zip
基于java的咖啡在线销售系统的开题报告
基于java的自助医疗服务系统的开题报告.docx
内容概要:本文档全面介绍了Visual Basic(VB)编程语言的基础知识和高级应用。首先概述了VB的基本特性和开发环境,随后详细讲述了VB的数据类型、变量、运算符、控制结构、数组、过程与函数、变量作用域等内容。接着介绍了窗体设计、控件使用、菜单与工具栏的设计,文件操作、数据库访问等关键知识点。最后讨论了VB的学习方法、发展历史及其在桌面应用、Web应用、数据库应用、游戏开发和自动化脚本编写等领域的广泛应用前景。 适合人群:初学者和中级程序员,尤其是希望快速掌握Windows桌面应用开发的人群。 使用场景及目标:①掌握VB的基础语法和开发环境;②学会使用VB创建复杂的用户界面和功能完整的应用程序;③理解数据库操作、文件管理和网络编程等高级主题。 其他说明:Visual Basic是一种简单易学且功能强大的编程语言,尤其适合用于开发Windows桌面应用。文中不仅覆盖了基础知识,还包括了大量的实用案例和技术细节,帮助读者快速提升编程技能。
基于java的疫情期间高校防控系统开题报告.docx
基于springboot+vue社区老年人帮扶系统源码数据库文档.zip
基于java的超市商品管理系统的开题报告.docx
基于SpringBoot房屋买卖平台源码数据库文档.zip
xdu限通院23微处理器系统与应用大作业(两只老虎),适应于汇编语言keil软件,
<项目介绍> - 新闻类网站系统,基于SSM(Spring、Spring MVC、MyBatis)+MySQL开发,高分成品毕业设计,附带往届论文 - 不懂运行,下载完可以私聊问,可远程教学 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 --------
基于java的学生网上请假系统的开题报告.docx
社会经济繁荣发展的今天,电子商务得到了飞速发展,网上交易越来越彰显出其独特的优越性,在人们的日常生活中,出现了各种类型的交易网站。其中一个就是车辆易主交易网站,它是一个服务于用户买卖二手车辆的交易网站,为用户提供了平等互利、方便快捷的网上交易平台,通过这一类型的网站,用户可自由出售和购买车辆。 本课题主要根据车辆本身的特性,充分发挥互联网的特点与优势,构建一个以二手车辆为商品、基于互联网平台的车辆易主业务交易管理系统,并根据车辆易主业务交易管理系统的应用需求,进行需求分析,进而对网站系统作规划设计。采用IDEA为运行平台,以SSH为框架,运用HTML语言、JSP技术、MySql数据库、JSP与后台数据库链接等关键技术建设二手车网上交易系统,构建车辆易主交易系统的会员注册与登录,网站首页展示、用户发布商品车辆,用户求购商品车辆,分页浏览、购物系统、用户后台管理、管理员用户后台管理等功能,并使这些功能得以实现并更好为用户服务。网站整体构建完成且测试成功后,用户可以进入网站进行注册、登录,登录后,用户可以在网站上发布自己的闲置车辆或者寻找想要购买的车辆,还可以收藏车辆,管理发布和收藏的车辆,
SQLite3的向量扩展库,windows dll,版本0.1.5
基于C++实现(控制台)商品库存管理系统