JAVA類體系圖生成器
layout: post
title: JAVA類體系圖生成器
categories: Java
description: JAVA類體系圖生成器
keywords:
url: https://lichao890427.github.io/ https://github.com/lichao890427/
簡介
由於是java新手,知道的東西較少,有時候要用到某個功能,而該功能在某個特定類裡,而這個類你不一定清楚是什麼,該用哪個類一般需要在網上現查,這個工具就是用來快速列舉類的所有派生類超類的,與java的反射機制剛好相反,反射機制讓你能找到他的父類或父介面。舉個例子:現在要讀取檔案而且分行讀取,假設你只記得一些常識性的東西,例如讀取檔案要用基於InputStream的類,但是檢視InputStream的說明後你會發現該類只能按byte[]讀,而分行讀這種高階功能一定是派生於InputStream的某個類,但是就是想不起來,因為繼承於BufferedReader的有:
- ByteArrayInputStream
- FileInputStream
- BufferedInputStream
- DataInputStream
等等很多,真相見圖:
該工具用於檢視所有類及介面的繼承關係,介面可以看成一種特殊的類,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中,十分方便。
Coding
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 static Queue<String> myqueue = null;
private JTextField toSearch = null;
private JList<String> result = null;
private JTree tree = null;
public HashTreeNode root = null;
public HashTreeNode exception = 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 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 synchronized void AddNodeByString(String[] allpath) {
HashTreeNode node = root;
for (int i = 1; i < allpath.length; i++) {
node = node.AddChild(allpath[i].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 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();
}
public class HashTreeNode {
public String nodename;
public LinkedList<HashTreeNode> children;
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;
}
}
}
Config.txt樣例部分
[JAVAHOME]
[JAVAHOME, java.applet.AppletContext]
[JAVAHOME, java.applet.AppletContext, java.beans.BeansAppletContext]
[JAVAHOME, java.applet.AppletStub]
[JAVAHOME, java.applet.AppletStub, java.beans.BeansAppletStub]
[JAVAHOME, java.applet.AudioClip]
[JAVAHOME, java.awt.ActiveEvent]
[JAVAHOME, java.awt.ActiveEvent, java.awt.SentEvent]
[JAVAHOME, java.awt.ActiveEvent, java.awt.SequencedEvent]
[JAVAHOME, java.awt.ActiveEvent, java.awt.event.InvocationEvent]
[JAVAHOME, java.awt.Adjustable]
[JAVAHOME, java.awt.Adjustable, java.awt.ScrollPaneAdjustable]
[JAVAHOME, java.awt.Adjustable, java.awt.Scrollbar]
[JAVAHOME, java.awt.Adjustable, javax.swing.JScrollBar]
[JAVAHOME, java.awt.Composite]
[JAVAHOME, java.awt.Composite, java.awt.AlphaComposite]
相關文章
- java知識體系結構圖Java
- 圖書管理系統類圖
- 圖解計算機結構與體系分類!!圖解計算機
- 地圖POI類別標籤體系建設實踐地圖
- java 圖片水印處理類Java
- Email圖示生成器AI
- 圖書管理系統設計類圖
- JAVA_系統常用類Java
- Android所需的Java基礎知識體系圖AndroidJava
- 前端體系圖前端
- iOS 圖示&啟動圖生成器(二)iOS
- iOS 圖示&啟動圖生成器(一)iOS
- mybatis_plus程式碼生成器類MyBatis
- Photoshop類圖片處理軟體
- Java的類和物件 圓柱體類求底面積和體積Java物件
- jCharts:Java圖表類庫使用介紹Java
- JFreeChart:多功能Java圖表類庫Java
- (轉載) java實體類的作用Java
- Java之Throwable體系Java
- java異常體系Java
- 從 Java 程式碼逆向工程生成 UML 類圖和序列圖Java
- 網店分類圖片生成軟體
- 尋找Java程式碼生成器Java
- 基於SWT的Java圖表類庫SWTChartJava
- Java中常見的集合容器類關係圖Java
- 使用java繪圖類Graphics繪製圓圈Java繪圖
- Solr體系架構圖Solr架構
- Oracle 體系結構圖Oracle
- nested exception is java.lang.NoSuchMethodException: 實體類.()ExceptionJava
- Java體系化學習路線圖總結,帶走不謝!Java
- LOOK 直播活動地圖生成器方案地圖
- Java異常體系概述Java
- java 程式碼生成器設計方案Java
- 用IntelliJ IDEA ULTIMATE版看Java類圖IntelliJIdeaJava
- Java智慧圖表類庫JChartLib使用介紹Java
- web前端知識體系圖Web前端
- 【學習圖片】14.網站生成器、框架和內容管理系統網站框架
- 程式碼生成器專案架構圖架構