黑马程序员技术交流社区

标题: 对eclipse代码补全功能原理的猜想及实验 [打印本页]

作者: 王海宇    时间: 2012-9-23 18:23
标题: 对eclipse代码补全功能原理的猜想及实验
虽然一直用eclipse,但是从没想过它的工作原理是什么,今天在复习反射的时候,就联想到,eclipse的代码补全功能是否就是通过反射要提示的类来实现的呢?然后就自己写了一个简单的程序,来实验一下,代码如下
  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.lang.reflect.Field;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.Modifier;

  8. public class ReflectTest {
  9.         @SuppressWarnings("rawtypes")
  10.         public static void main(String[] args) throws IOException,
  11.                         ClassNotFoundException {
  12.                 while (true) {
  13.                         System.out.println("请输入要加载的类的完整包名及类名(若要退出程序,请直接按回车):");

  14.                         // 获取用户的输入。例:org.dom4j.Branch
  15.                         String name = new BufferedReader(new InputStreamReader(System.in))
  16.                                         .readLine();
  17.                         System.out.println();

  18.                         // 检查用户是否想继续操作
  19.                         if ("".equals(name)) {
  20.                                 System.out.println("你没有输入任何信息,程序将退出");
  21.                                 return;
  22.                         }

  23.                         // 根据用户输入,生成格式化的class文件路径
  24.                         String filePath = name.replaceAll("\\.", "/") + ".class";
  25.                         File file = new File(filePath);

  26.                         // 检查用户输入的文件是否存在
  27.                         if (!file.exists() || !file.isFile()) {
  28.                                 System.out.println("你输入的文件路径及名称无效,请检查目录 "
  29.                                                 + file.getParentFile().getAbsolutePath() + " 下是否有 "
  30.                                                 + file.getName() + " 这个文件!!\n");
  31.                                 continue;
  32.                         }
  33.                         System.out.println("···现在开始分析位于" + file.getAbsolutePath()
  34.                                         + "的class文件···\n");

  35.                         // 加载用户希望分析的类
  36.                         Class clazz = Class.forName(name);

  37.                         // 获取要分析的类的所有公开字段
  38.                         Field[] fields = clazz.getFields();
  39.                         for (Field field : fields) {
  40.                                 System.out.println("找到字段:"

  41.                                 // 得到字段的修饰符
  42.                                                 + Modifier.toString(field.getModifiers()) + " "

  43.                                                 // 得到字段的名称
  44.                                                 + field.getName());
  45.                         }
  46.                         System.out.println();

  47.                         // 获取要分析的类的所有公开方法
  48.                         Method[] methods = clazz.getMethods();
  49.                         for (Method method : methods) {
  50.                                 System.out.print("找到方法:"

  51.                                 // 得到方法的修饰符
  52.                                                 + Modifier.toString(method.getModifiers()) + " "

  53.                                                 // 得到方法的名称
  54.                                                 + method.getName() + "(");
  55.                                 int i = 1;

  56.                                 // 得到方法中所有的参数类型字节码
  57.                                 Class[] argTypes = method.getParameterTypes();
  58.                                 for (Class clazz2 : argTypes) {

  59.                                         // 获取参数类型名
  60.                                         String argName = clazz2.getName();

  61.                                         // 格式化参数类型名
  62.                                         argName = argName.substring(argName.lastIndexOf(".") + 1);
  63.                                         System.out.print(argName + " " + "arg" + i);
  64.                                         if (i < argTypes.length)
  65.                                                 System.out.print(", ");
  66.                                         i++;
  67.                                 }
  68.                                 System.out.println(")");
  69.                         }
  70.                         System.out.println("\n······文件分析完毕······\n");
  71.                 }
  72.         }

  73. }
复制代码
假设ReflectTest.java位于D盘,要分析的文件位于D:\org\dom4j\io\XMLWriter.class。(org.dom4j.io是完整包名)
编译完毕后,执行java ReflectTest,然后输入
  1. org.dom4j.io.XMLWriter
复制代码
按回车,就可以看到输出结果了。例如:
  1. 请输入要加载的类的完整包名及类名(若要退出程序,请直接按回车):
  2. org.dom4j.io.XMLWriter

  3. ···现在开始分析位于D:\\org\dom4j\io\XMLWriter.class的class文件···


  4. 找到方法:public startDTD(String arg1, String arg2, String arg3)
  5. 找到方法:public endDTD()
  6. 找到方法:public startEntity(String arg1)
  7. 找到方法:public endEntity(String arg1)
  8. 找到方法:public startCDATA()
  9. 找到方法:public endCDATA()
  10. 找到方法:public resolveEntityRefs()
  11. 找到方法:public setWriter(Writer arg1)
  12. 找到方法:public setOutputStream(OutputStream arg1)
  13. 找到方法:public isEscapeText()
  14. 找到方法:public setEscapeText(boolean arg1)
  15. 找到方法:public setIndentLevel(int arg1)
  16. 找到方法:public getMaximumAllowedCharacter()
  17. 找到方法:public setMaximumAllowedCharacter(int arg1)
  18. 找到方法:public writeOpen(Element arg1)
  19. 找到方法:public writeClose(Element arg1)
  20. 找到方法:public setLexicalHandler(LexicalHandler arg1)
  21. 找到方法:public getLexicalHandler()
  22. 找到方法:public setResolveEntityRefs(boolean arg1)
  23. 找到方法:public println()
  24. 找到方法:public setProperty(String arg1, Object arg2)
  25. 找到方法:public getProperty(String arg1)
  26. 找到方法:public write(String arg1)
  27. 找到方法:public write(ProcessingInstruction arg1)
  28. 找到方法:public write(Attribute arg1)
  29. 找到方法:public write(Document arg1)
  30. 找到方法:public write(Node arg1)
  31. 找到方法:public write(Element arg1)
  32. 找到方法:public write(CDATA arg1)
  33. 找到方法:public write(Comment arg1)
  34. 找到方法:public write(DocumentType arg1)
  35. 找到方法:public write(Entity arg1)
  36. 找到方法:public write(Namespace arg1)
  37. 找到方法:public write(Object arg1)
  38. 找到方法:public write(Text arg1)
  39. 找到方法:public close()
  40. 找到方法:public flush()
  41. 找到方法:public parse(InputSource arg1)
  42. 找到方法:public comment([C arg1, int arg2, int arg3)
  43. 找到方法:public characters([C arg1, int arg2, int arg3)
  44. 找到方法:public endDocument()
  45. 找到方法:public endElement(String arg1, String arg2, String arg3)
  46. 找到方法:public endPrefixMapping(String arg1)
  47. 找到方法:public ignorableWhitespace([C arg1, int arg2, int arg3)
  48. 找到方法:public notationDecl(String arg1, String arg2, String arg3)
  49. 找到方法:public processingInstruction(String arg1, String arg2)
  50. 找到方法:public setDocumentLocator(Locator arg1)
  51. 找到方法:public startDocument()
  52. 找到方法:public startElement(String arg1, String arg2, String arg3, Attributes
  53. arg4)
  54. 找到方法:public startPrefixMapping(String arg1, String arg2)
  55. 找到方法:public unparsedEntityDecl(String arg1, String arg2, String arg3, Strin
  56. g arg4)
  57. 找到方法:public getErrorHandler()
  58. 找到方法:public getEntityResolver()
  59. 找到方法:public setContentHandler(ContentHandler arg1)
  60. 找到方法:public getDTDHandler()
  61. 找到方法:public setDTDHandler(DTDHandler arg1)
  62. 找到方法:public getParent()
  63. 找到方法:public setParent(XMLReader arg1)
  64. 找到方法:public fatalError(SAXParseException arg1)
  65. 找到方法:public error(SAXParseException arg1)
  66. 找到方法:public parse(String arg1)
  67. 找到方法:public getContentHandler()
  68. 找到方法:public warning(SAXParseException arg1)
  69. 找到方法:public getFeature(String arg1)
  70. 找到方法:public resolveEntity(String arg1, String arg2)
  71. 找到方法:public setFeature(String arg1, boolean arg2)
  72. 找到方法:public setEntityResolver(EntityResolver arg1)
  73. 找到方法:public setErrorHandler(ErrorHandler arg1)
  74. 找到方法:public skippedEntity(String arg1)
  75. 找到方法:public final wait()
  76. 找到方法:public final wait(long arg1, int arg2)
  77. 找到方法:public final native wait(long arg1)
  78. 找到方法:public native hashCode()
  79. 找到方法:public final native getClass()
  80. 找到方法:public equals(Object arg1)
  81. 找到方法:public toString()
  82. 找到方法:public final native notify()
  83. 找到方法:public final native notifyAll()

  84. ······文件分析完毕······

复制代码
找的例子class文件里面正好没有公开字段,所以只找出了公开的方法。。
从上面的内容可以分析,在使用eclipse的代码补全提示的时候,eclipse应该也是采用反射的方法(这也说明在我们编写代码的时候,eclipse已经将我们用到的各种类的class文件加载到了内存中),获取要使用的类的方法以及字段,然后将它们进行包装以后,就将其显示在了提示列表中。当然这只是我的猜想,eclipse具体是不是这样工作,我也拿不准。。。欢迎大家一起讨论







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2