元始天尊 发表于 2014-1-31 00:36:05

年后第一弹:JAVA类体系图生成器

年后第一弹:JAVA类体系图生成器    自己DIY的又一JAVA强力工具:类体系关系图
    制作背景:由于是java新手,知道的东西较少,有时候要用到某个功能,而该功能在某个特定类里,而这个类你不一定清楚是什么,该用哪个类一般需要在网上现查,这个工具就是用来快速枚举类的所有派生类超类的,与java的反射机制刚好相反,反射机制让你能找到他的父类或父接口。举个例子:现在要读取文件而且分行读取,假设你只记得一些常识性的东西,例如读取文件要用基于InputStream的类,但是查看InputStream的说明后你会发现该类只能按byte[]读,而分行读这种高级功能一定是派生于InputStream的某个类,但是就是想不起来,因为继承于BufferedReader的有:ByteArrayInputStream    FileInputStream BufferedInputStream DataInputStream 等等很多,真相见图:

但是没有这个工具之前你压根不知道InputStream有这些派生类!只能靠经验,别人写过这个代码,然后你上网去找罢了。这个工具的诞生是我在看到了java反射机制这个强大特性以后突发奇想想到的,目前网上肯定还没有这种东西。不过对我来说初学java理清类还是很重要的,java反射机制其实我只用了低阶的,该工具通过递归查看类信息实现,其实反射还可以动态更改已有类属性和方法,十分强大。该工具用于查看所有类及接口的继承关系,接口可以看成一种特殊的类,java不支持多重继承也就是只能由一个父类,但是可以继承于多个接口,接口是只有成员函数而无成员变量的类而已,所以在这个角度说,也可以看成java是多重继承的,事实上在程序中我已经这么做了,因为查看父接口也是很重要的,不过这样就导致生成树会有重复部分。这个工具最后做了2分,第一份是包括jdk带的所有运行时库,%JAVA_HOME%\jre\lib 和%JAVA_HOME%\jre\lib\ext 下的所有jar文件解压出来以后不重复的class文件有4W个之多,大家知道一个class对应一个类,现在知道java有多庞大了吧。最后花了20分钟吧所有类解析出来继承关系并生成类树,4M的config.txt是根据这些信息生成的,用于下次启动直接加载不用再次解析,不过由于庞大的数量,完全加载也花了快10分钟。最后由于太多,显然java的JTree出了问题,因为很多都没显示出来了。第二份是rt.jar里的java和javax文件夹,就目前情况而言导入基本上用的都是这里的东西。导入不到半分钟,生成的config.txt有1W行,很快就见到JTree在跳动了。。。如果有第三方库要导入类图,需要解压jar到相应位置,程序启动以后会先从config.txt导入数据,然后遍历指定目录文件加入生成树,每个文件都是一个类,对每个类都要迭代其父类直到父类为null停止,这样就构成了树。对于不支持查看类信息的类生成排除列表。此工具还可在类图形成后进行关键字搜索,搜到的词放到一个JList里,选择后可以直接定位到JTree中,十分方便。          代码只有450行:

package test;

import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Queue;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class classtree extends JFrame
{
        /**
          *
          */
        private static final long serialVersionUID = 1L;
        private JTextField toSearch=null;
        private JList<String> result=null;
        private JTree tree=null;
        public HashTreeNode root=null;
        public HashTreeNode exception=null;
        private static Queue<String> myqueue=null;
        private String folderpath="C:/Users/Administrator/Desktop/rt";
        private boolean datachanged=false;//增加了文件目录时
        private String tofind=null;
        private LinkedList<Integer> select=null;
        private LinkedList<String> excluded=null;
        JScrollPane scrollPane=null;
        DefaultMutableTreeNode uiroot=null;
       
        public class HashTreeNode
        {
                public HashTreeNode(String name)
                {
                        nodename=name;
                        children=new LinkedList<HashTreeNode>();
                }
               
                public synchronized HashTreeNode AddChild(String name)
                {
                        HashTreeNode newnode=null;
                        for(int i=0;i<children.size();i++)
                        {
                                if(name.equals(children.get(i).nodename))
                                {
                                        return children.get(i);
                                }
                                else if(name.compareTo(children.get(i).nodename) < 0)//name < node
                                {
                                        newnode=new HashTreeNode(name);
                                        children.add(i,newnode);
                                        return newnode;
                                }
                        }
                        newnode=new HashTreeNode(name);
                        children.add(newnode);
                        return newnode;
                }
               
                public String nodename;
                public LinkedList<HashTreeNode> children;
        }
       
        public synchronized void AddNodeByString(String[] allpath)
        {
                HashTreeNode node=root;
                for(int i=1;i<allpath.length;i++)
                {
                        node=node.AddChild(allpath.trim());
                }
        }
       
        public synchronized LinkedList<HashTreeNode> AddOneNode(String classpath)//加入节点
        {//递归找到父节点
                LinkedList<HashTreeNode> result=new LinkedList<HashTreeNode>();
               
                try
                {
                //System.out.println(classpath);

                        for(String exc:excluded)
                        {
                                if(classpath.contains(exc))
                                {
                                        result.add(exception.AddChild(classpath));
                                        return result;       
                                }
                        }

                        //接口看做父类
                        java.lang.reflect.Type curtype=Class.forName(classpath).getGenericSuperclass();
                        LinkedList<java.lang.reflect.Type> type=new LinkedList<java.lang.reflect.Type>();
                        if(curtype != null)
                                type.add(curtype);
                        else
                                result.add(root.AddChild(classpath));
                        for(java.lang.reflect.Type curtype1:Class.forName(classpath).getGenericInterfaces())
                        {
                                type.add(curtype1);
                        }

                        for(java.lang.reflect.Type curtype2:type)
                        {
                                String classstr=curtype2.toString();
                                if(classstr.contains("interface") || classstr.contains("class"))
                                        classstr=classstr.substring(classstr.indexOf(' ')+1);
                                if(classstr.indexOf('<') > -1)
                                        classstr=classstr.substring(0,classstr.indexOf('<'));
                                for(HashTreeNode node1:AddOneNode(classstr))
                                {
                                        result.add(node1.AddChild(classpath));
                                }
                        }
                        return result;       
                }
                catch(Exception e)
                {
                        System.out.println("error:"+classpath);
                        result.add(exception.AddChild(classpath));
                        return result;
                }
        }
       
        public static void FindClassInfo(String dir,String classpath)
        {
                try
                {
                        File file=new File(dir);
                        if(file.isFile())
                        {
                                if(classpath.indexOf('$') < 0 && classpath.indexOf(".class") > -1)
                                {
                                        String obj=classpath.replace(".class","");
                                        myqueue.add(obj);
                                        System.out.println(obj);
                                }
                        }
                        else if(file.isDirectory())
                        {
                                for(String dirstr:file.list())
                                {
                                        String newclasspath=classpath.equals("")?dirstr:(classpath+"."+dirstr);
                                        FindClassInfo(dir+"/"+dirstr,newclasspath);
                                }
                        }
                }
                catch(Exception e)
                {
                        System.out.println("error");
                }
        }
       
        public void FindAllMatchClass(HashTreeNode node)
        {
                try
                {
                        String dest=tofind.substring(tofind.lastIndexOf('.')+1);
                        if(node.nodename.contains(dest))
                        {
                                ((DefaultListModel<String>)result.getModel()).addElement(node.nodename);
                        }
                        for(HashTreeNode cur:node.children)
                        {
                                FindAllMatchClass(cur);
                        }
                }
                catch(Exception e)
                {
                        System.out.println("error");
                }
        }
       
        public void AddUItree(HashTreeNode curnode,DefaultMutableTreeNode uinode)
        {
                try
                {
                        for(int i=0;i<curnode.children.size();i++)
                        {
                                HashTreeNode cur=curnode.children.get(i);
                                DefaultMutableTreeNode newnode=new DefaultMutableTreeNode(cur.nodename);
                                uinode.add(newnode);
                                AddUItree(cur,newnode);
                        }
                }
                catch(Exception e)
                {
                        System.out.println("error");
                }
        }
       
        public classtree()
        {
                super("");
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                getContentPane().setLayout(null);
               
                toSearch = new JTextField();
                toSearch.setBounds(107, 630, 247, 21);
                getContentPane().add(toSearch);
                toSearch.setColumns(10);
               
                JLabel label = new JLabel("\u8981\u641C\u7D22\u7684\u76EE\u6807\uFF1A");
                label.setBounds(10, 633, 87, 15);
                getContentPane().add(label);
               
                JButton search = new JButton("\u641C");
                search.setBounds(364, 629, 100, 23);
                getContentPane().add(search);
               
                scrollPane = new JScrollPane();
                scrollPane.setBounds(0, 0, 584, 496);
                getContentPane().add(scrollPane);
               
                tree = new JTree();
                tree.setScrollsOnExpand(true);
                tree.setFocusable(true);
                tree.setAutoscrolls(true);
                tree.setModel(new DefaultTreeModel(uiroot=new DefaultMutableTreeNode("JAVAHOME")));
                scrollPane.setViewportView(tree);
               
                JScrollPane scrollPane_1 = new JScrollPane();
                scrollPane_1.setBounds(0, 497, 584, 123);
                getContentPane().add(scrollPane_1);
               
                result = new JList<String>();
                scrollPane_1.setViewportView(result);
               
                JButton outputfile = new JButton("\u751F\u6210\u6587\u4EF6");
                outputfile.setBounds(474, 629, 100, 23);
                getContentPane().add(outputfile);
               
                setSize(600,700);
                setVisible(true);
               
                root=new HashTreeNode("根节点");
                exception=root.AddChild("异常");
                myqueue=new LinkedList<String>();
                select=new LinkedList<Integer>();
                excluded=new LinkedList<String>();
                excluded.add("com.sun.management.OperatingSystem");
                excluded.add("com.sun.org.apache.xml.internal.serialize.HTMLdtd");
                excluded.add("sun.awt.windows.WBufferStrategy");
                excluded.add("sun.font.FreetypeFontScaler");
                excluded.add("sun.java2d.cmm.lcms.LCMS");
                excluded.add("sun.jdbc.odbc.JdbcOdbcPlatform");
                excluded.add("sun.org.mozilla.javascript.internal.SecureCaller");
                excluded.add("sun.plugin.extension.ExtensionUtils");
                excluded.add("sun.plugin2.main.client.WDonatePrivilege");
                excluded.add("sun.plugin2.main.server.IExplorerPlugin");
                excluded.add("sun.plugin2.main.server.MozillaPlugin");
                excluded.add("sun.plugin2.os.windows.Windows");
                excluded.add("sun.plugin2.main.server.ProxySupport");
                excluded.add("sun.reflect.misc.Trampoline");
                excluded.add("sun.security.krb5.SCDynamicStoreConfig");
                excluded.add("oracle.jrockit.jfr.Process");
                excluded.add("oracle.jrockit.jfr.Timing");
                excluded.add("com.sun.deploy.uitoolkit.impl.awt.AWTClientPrintHelper");
                excluded.add("com.sun.glass.ui.mac");
                excluded.add("com.sun.glass.ui.x11.X11Timer");
                excluded.add("com.sun.javafx.logging.LoggingSupport");
               
                try
                {
                        if(new File("config.txt").exists())
                        {
                                FileReader fr=new FileReader("config.txt");
                                BufferedReader br=new BufferedReader(fr);
                                FileInputStream fis=new FileInputStream("config.txt");
                                String line="";
                                while((line=br.readLine()) != null)
                                {
//                                                                                                                                                                        System.out.println(line);
                                        AddNodeByString(line.substring(1,line.length()-1).split(","));
                                }                                                               
                                br.close();
                                fr.close();
                        }
                }
                catch(Exception e)
                {
                        e.printStackTrace();
                }
               
                result.addListSelectionListener(new ListSelectionListener()
                {
                        public void valueChanged(ListSelectionEvent e)
                        {
                                for(int i=0;i < tree.getRowCount();i++)
                                {
                                        tree.expandRow(i);
                                }
                                int i=select.get(result.getSelectedIndex());
                                tree.setSelectionRow(i);
                                Rectangle rect=tree.getRowBounds(i);
                                tree.scrollRectToVisible(rect);
                        }
                });
               
                search.addMouseListener(new MouseAdapter()
                {
                        Thread searchthread=null;
                        @Override
                        public void mouseClicked(MouseEvent e)
                        {
                                searchthread=new Thread()
                                {//开始枚举文件线程
                                        @Override
                                        public void run()
                                        {
                                                try
                                                {
                                                        result.setModel(new DefaultListModel<String>());
                                                        tofind=toSearch.getText();
                                                        for(int i=0;i<tree.getRowCount();i++)
                                                        {
                                                                tree.expandRow(i);
                                                        }
                                                        select=new LinkedList<Integer>();
                                                        for(int i=0;i<tree.getRowCount();i++)
                                                        {
                                                                String obj=tree.getPathForRow(i).toString();
                                                                if(obj.contains(tofind))
                                                                {
                                                                        ((DefaultListModel<String>)result.getModel()).addElement(obj);
                                                                        select.add(i);
                                                                }
                                                        }
                                                }
                                                catch(Exception e)
                                                {
                                                        e.printStackTrace();
                                                }
                                        }
                                };
                               
                                try
                                {
                                        searchthread.start();
                                        searchthread.join();                                                                                                                                               
                                }
                                catch(Exception exc)
                                {
                                        exc.printStackTrace();
                                }
                        }
                });
               
                final Thread filethread=new Thread()
                {//开始枚举文件线程
                        @Override
                        public void run()
                        {
                                FindClassInfo(folderpath,"");
                                datachanged=true;
                        }
                };
                filethread.start();
               
                new Thread()
                {//开始处理队列线程
                        @Override
                        public void run()
                        {
                                try
                                {
                                        filethread.join();
                                        while(true)
                                        {
                                                if(myqueue.isEmpty())
                                                {
                                                        Thread.sleep(500);
                                                        if(datachanged)
                                                        {
                                                                uiroot=new DefaultMutableTreeNode("JAVAHOME");
                                                                tree.setModel(new DefaultTreeModel(uiroot));
                                                                AddUItree(root,uiroot);
                                                                datachanged=false;
                                                        }
                                                        else
                                                        {
                                                                for(int i=0;i<tree.getRowCount();i++)
                                                                {
                                                                        tree.expandRow(i);
                                                                }
                                                        }
                                                }
                                                else
                                                {
                                                        if(filethread.isAlive())
                                                                filethread.join();
                                                        AddOneNode(myqueue.poll());
                                                }
                                        }
                                }
                                catch(Exception e)
                                {
                                        e.printStackTrace();
                                }                       
                        }
                }.start();
               
                outputfile.addMouseListener(new MouseAdapter()
                {
                        @Override
                        public void mouseClicked(MouseEvent e)
                        {
                                OutputFile();
                        }
                });
               
                addWindowListener(new WindowAdapter()
                {//关闭时保存数据到文件
                        @Override
                        public void windowClosing(WindowEvent e)
                        {
                                OutputFile();
                        }
                });
        }
       
        public void OutputFile()
        {
                try
                {                                                                                                                                       
                        for(int i=0;i < tree.getRowCount();i++)
                        {
                                tree.expandRow(i);
                        }
                        FileOutputStream fos=new FileOutputStream("config.txt");
                        for(int i=0;i<tree.getRowCount();i++)
                        {
                                String obj=tree.getPathForRow(i).toString()+"\n";
                                fos.write(obj.getBytes());
                        }
                        fos.close();
                }
                catch(Exception e)
                {
                        e.printStackTrace();
                }
        }
       
        public static void main(String[] args) throws FileNotFoundException
        {
                //System.setOut(new PrintStream("abcd.txt"));
                new classtree();
        }
}
Config.txt样例部分:
















工程文件:
页: [1]
查看完整版本: 年后第一弹:JAVA类体系图生成器