Java項目實戰(zhàn)開發(fā)Day18 2020-04-14

命令行參數(shù)項目

看完老師寫的,我發(fā)現(xiàn)我的代碼真的還是弱爆了。多說無益腕扶,下面我吸取了一些經(jīng)驗,來記錄一下吨掌。

一.缺點

1.無架構(gòu)意識

目前來說半抱,我自己寫的時候都是想起什么寫什么,根本沒有架構(gòu)的意識膜宋。所謂架構(gòu)意識窿侈,通俗一點就是:
自己先畫一個圖,把程序的結(jié)構(gòu)理清楚史简。再去一個一個地填充。

實現(xiàn)命令行工具UML.png

上圖是老師對這個程序的架構(gòu)枢贿。

2.基本沒有用接口的意識

①其實可以用接口先規(guī)定一個框架萨咕,也就是都有什么方法聪建,具體實現(xiàn)的話,再創(chuàng)建一個實現(xiàn)類來實現(xiàn)即可挥下。但是我在寫的時候根本沒有這個意識现斋。
②除了規(guī)定框架迷雪,接口還可以保存各種各樣的常量倦西,別忘了接口默認(rèn)是被public static final修飾的。
③在寫實現(xiàn)類時,可以先提供一個方法的空殼,而不是說寫出一個方法倡缠,就必須要把它的所有執(zhí)行內(nèi)容寫出來载荔。

3.想的情況不全面丘损,寫的代碼不高級

①所謂“想的情況不全面”
就是有些情況我根本沒有想到肢娘。比如輸入ls沙廉,之后緊跟著要判斷一下總的參數(shù)的個數(shù),如果是1,那就對了垢夹,因為ls就是1個參數(shù)而晒,如果你輸入 ls 然后又手誤,又連帶了一個a,那么這個時候就應(yīng)該提示一下,輸入?yún)?shù)有誤,請重新輸入俏拱。這只是一個簡單的例子。
②所謂“寫的代碼不高級”
一個是使用的類不靈活吼句,比如我可能只會想到用String,但是可能用StringBuilder更方便一些况毅,也更高級一些尔许,但是我想不起來用這個柠新。還有一個是代碼結(jié)構(gòu)不高級,所謂高級净蚤,并不是說結(jié)構(gòu)亂套難懂钥组,而是應(yīng)該盡可能減少代碼之間的關(guān)聯(lián)度,使用一些操作使程序效率更高等等橘荠。比如老師用到了數(shù)據(jù)回調(diào)(后面還會講)作烟,但是我數(shù)據(jù)回調(diào)還沒有完全理解,今天花了半個小時查閱了很多資料才大概懂了砾医。所以最后還要復(fù)習(xí)一下自己所有的Java博客,復(fù)習(xí)一下基礎(chǔ)知識衣厘。

4.掌握的類的方法太少

有些類的方法是很常見也很實用的如蚜,但是我就是想不起來用,可能還是寫的代碼太少影暴。比如Arrays.asList()可以把Array類型轉(zhuǎn)換為List類型错邦,StringBuilder可以在后面追加字符串,也可以刪除字符串型宙,還可以找到指定字符串的索引值等等撬呢,這些方法,我都沒有掌握妆兑。

5.無自定義異常類的意識

之所以沒這個意識魂拦,我認(rèn)為還是操作不熟練毛仪。比如自定義異常類要進(jìn)行一系列拋出并捕獲,還要super(s)芯勘,這些雖然學(xué)過箱靴,但是我基本沒用過,所以很快就忘了荷愕。

二.具體代碼

①ICmd接口

用來保存常量

package interfaces;

//定義指令
public interface ICmd {
   //接口里面的變量默認(rèn)被public static final修飾 
   String LS = "ls";          //列出當(dāng)前目錄的所有內(nèi)容
   String MKDIR = "mkdir";    //創(chuàng)建目錄
   String COPY = "copy";      //拷貝
   String RM = "rm";          //刪除
   String CD = "cd";          //進(jìn)入一個目錄
   String CDP = "cd..";       //進(jìn)入上一層目錄
   
   String[] COMMONDS = new String[] {LS,MKDIR,COPY,RM,CD,CDP};
}

②ICommond接口

用來定義方法框架

package interfaces;

//規(guī)劃一下執(zhí)行的操作
public interface ICommond {
   //默認(rèn) public abstract修飾
    boolean list();               //列出當(dāng)前目錄的所有內(nèi)容 名字+size
    
    boolean mkdir(String path);              //創(chuàng)建一個目錄
    
    boolean copy(String src,String des);     //將src的文件復(fù)制到des位置
    
    boolean remove(String path);             //刪除文件
    
    boolean cd_to_child(String path);        //切換當(dāng)前目錄到子目錄/進(jìn)入子目錄
    
    boolean cd_to_parent();                  //切換當(dāng)前目錄到上一層目錄
}

③MyClass類

程序入口

package Main;

import Tool.CommondTool;

public class MyClass {
     public static void main(String[] args) {
         
         CommondTool tool = new CommondTool();
         
         tool.start();
     }
}

④CommondOperation類

用來執(zhí)行某些外包操作與回調(diào)

package Tool;

import java.util.*;

import interfaces.*;

//接收用戶輸入和解析輸入類型
public class CommondOperation {
   //回調(diào)對象
   private ICommond listener;
   //保存所有指令
   private List<String> commonds;
   //獲取輸入信息
   private Scanner mScanner;
   public CommondOperation() {
       mScanner = new Scanner(System.in);
       //將普通的Array類型轉(zhuǎn)化為List
       commonds = Arrays.asList(ICmd.COMMONDS);
   }
   
   
   
   //接收用戶輸入的指令
   public void readCommond(ICommond listener)throws PXDException.CommondNotExistException,PXDException.CommondArgumentErrorException  {
        this.listener = listener;
        
        //接收指令
        String commond = mScanner.nextLine();//記住這里用nextLine()
    
        //解析指令
        parseCommond(commond);
    }
   
    //解析指令
    public void parseCommond(String commond)throws PXDException.CommondNotExistException,PXDException.CommondArgumentErrorException {
        //將指令以空格為分割符 分開
        String[] componts = commond.split(" ");//這也是當(dāng)時焦頭爛額的地方
        
        //獲取用戶指令
        String cmd = componts[0];
            
        //判斷指令是否存在
        if(!commonds.contains(cmd)) {
            //輸入指令不存在
            //需要拋出異常
            throw new PXDException.CommondNotExistException("指令不存在");
        }
        //存在就解析是哪種指令
        switch(cmd) {
        case ICmd.CD:
            //進(jìn)入某一個子目錄
            if(componts.length != 2) {
                //參數(shù)不正確衡怀,應(yīng)該只有兩個
                throw new PXDException.CommondArgumentErrorException("cd 參數(shù)不正確");
            }
            listener.cd_to_child(componts[1]);
            break;
        case ICmd.CDP:
            //進(jìn)入父目錄
            if(componts.length != 1) {
                //參數(shù)不正確,應(yīng)該只有兩個
                throw new PXDException.CommondArgumentErrorException("cd.. 參數(shù)不正確安疗,它不需要參數(shù)");
            }
            listener.cd_to_parent();
            break;
        case ICmd.MKDIR:
            //創(chuàng)建目錄
            if(componts.length != 2) {
                //參數(shù)不正確
                throw new PXDException.CommondArgumentErrorException("mkdir 參數(shù)不正確");
            }
            listener.mkdir(componts[1]);
            break;
        case ICmd.RM:
            //刪除
            if(componts.length != 2) {
                //參數(shù)不正確
                throw new PXDException.CommondArgumentErrorException("rm 參數(shù)不正確");
            }
            listener.remove(componts[1]);
            break;
        case ICmd.LS:
            //列
            if(componts.length != 1) {
                //參數(shù)不正確
                throw new PXDException.CommondArgumentErrorException("ls不需要參數(shù)");
            }
            listener.list();
            break;
        case ICmd.COPY:
            if(componts.length != 3) {
                //參數(shù)不正確
                throw new PXDException.CommondArgumentErrorException("copy參數(shù)不正確");
            }
            listener.copy(componts[1], componts[2]);
            break;
        }
    }

}

⑤CommondTool類

繼承框架接口抛杨,并執(zhí)行具體操作

package Tool;

import java.io.File;

import Tool.PXDException.CommondNotExistException;
import interfaces.*;

//接收用戶的指令 和 處理指令
public class CommondTool implements ICommond{
    //默認(rèn)啟動起來操作的目錄
    private static final String DESKTOP_PATH = "C:\\Users\\劉金豪\\Desktop";//桌面
    
    //記錄當(dāng)前操作的目錄路徑
    private StringBuilder currentDirPath;
    
    //構(gòu)造方法
    public CommondTool() {
        currentDirPath = new StringBuilder(DESKTOP_PATH);
    }
    
    //啟動命令行工具
    public void start() {
        //創(chuàng)建讀取指令的類的對象
        CommondOperation operation = new CommondOperation();
        //歡迎界面
        System.out.println("歡迎用戶使用命令行工具!荐类!");
        while(true) {
            //顯示當(dāng)前路徑(只需要提示當(dāng)前路徑的最后部分)
            showParent();
            
            //輸入指令
            try {
                operation.readCommond(this);
            } catch (Exception e) {
                System.out.println(e.getMessage());//熟悉一下getMessage方法的使用
            }
        }
        
    }

    private void showParent() {
        //獲取最后一個\\的index
        int start = currentDirPath.lastIndexOf("\\");
        //獲取最后的內(nèi)容
        String parent = currentDirPath.substring(start);//獲取子字符串
        //輸出提示內(nèi)容
        System.out.print(parent+"#");
    }
    
    @Override
    public boolean list() {
        File[]files = FileManager.getInstance().list(currentDirPath.toString());//注意轉(zhuǎn)化成字符串類型
        for(File file:files) {
            //獲取文件名
            String name = file.getName();
            //獲取文件長度
            long size = file.length();
            long kb = size/1024;
            long by = size%1024;
            System.out.print(name +" " );
            for(int i = 0;i < 40 - name.length();i++) {
                System.out.print(" ");
            }
            System.out.println(kb + "." + by + "kb");
            
         }
         return false;  
}  
        
    

    @Override
    public boolean mkdir(String path) {
        //拼接完整路徑
        String dirPath = currentDirPath.toString() + "\\" + path;
        FileManager.getInstance().mkdir(dirPath);
        return false;
    }

    @Override
    public boolean copy(String src, String des) {
        //拼接完整路徑
        String srcPath = currentDirPath.toString() + "\\" + src;
        String desPath = currentDirPath.toString() + "\\" + des;
        
        FileManager.getInstance().copy(srcPath, desPath);
        return false;
    }

    @Override
    public boolean remove(String path) {
        //拼接完整路徑
        String dirPath = currentDirPath.toString() + "\\" + path;
        FileManager.getInstance().remove(dirPath);
        return false;
    }

    @Override
    public boolean cd_to_child(String path) {
        currentDirPath.append("\\" + path);
        System.out.println("進(jìn)入子目錄:"+path);
        return false;
    }

    @Override
    public boolean cd_to_parent() {
        //先轉(zhuǎn)換成字符串
        int start = currentDirPath.toString().lastIndexOf("\\");
        int end = currentDirPath.length();//復(fù)習(xí)一下怖现,這個end到底刪不刪除
        currentDirPath.delete(start, end);
        return false;
    }
}

⑥FileManager類

用來執(zhí)行更具體的操作,因為此程序基本所有操作都是涉及文件的掉冶,所以專門用一個類來封裝操作真竖。

package Tool;

import java.io.*;

public class FileManager {
    //單例模式
   private static FileManager manager;
   private FileManager() {
       
   }
    
   public static FileManager getInstance() {
        if(manager == null) {
            synchronized(FileManager.class) {
                if(manager == null) {
                    manager = new FileManager();
                }
            }
        }
        return manager;
    }
   
   //創(chuàng)建目錄
   public boolean mkdir(String path) {
       File file = new File(path);
       if(file.exists()) {
           return false;
       }
       return file.mkdir();//mkdir返回值就是boolean類型
       //mkdir要求路徑中的目錄都存在
       //mkdirs如果路徑中的目錄不存在,也會自動創(chuàng)建
   }
   
   //刪除文件或目錄
   public boolean remove(String path) {
       File file = new File(path);
       if(!file.exists()) {
           return false;
       }
       
       return file.delete();
   }
   
   //列出所有文件信息
   public File[] list(String path){
       File file = new File(path);
       if(!file.exists()) {
           return null;
       }
       return file.listFiles(new FilenameFilter() {
        
           //名字是點開頭的都是隱藏文件厌小,這些文件我不想要恢共。就篩選一下
           public boolean accept(File file, String s) {
            if(s.startsWith(".")) {
                return false;
            }
            return true;
        }
           
       });
   }
   
   //文件或者目錄的拷貝
   public boolean copy(String src,String des) {
       File srcFile = new File(src);
       File desFile = new File(des);
       
       //判斷文件是否存在
       if(!srcFile.exists() || desFile.exists()) {//注意這里的細(xì)節(jié)
           return false;
       }
       
       //如果是文件
       if(srcFile.isFile()) {
           //直接拷貝文件
           copyFile(src,des);
       }else {
           //是目錄
           //創(chuàng)建當(dāng)前的目錄
           desFile.mkdir();
           
           //需要將源目錄的所有內(nèi)容拷貝到des目錄
           for(File file:srcFile.listFiles()) {
               copy(file.getAbsolutePath(),des + "\\" + file.getName());//注意這里是一個高級的地方,用到了嵌套
               //因為目錄里面可能還有目錄璧亚。
           }
       }
       
       return true;
   }
   
   private void copyFile(String src,String des) {
        
    try (FileInputStream fis = new FileInputStream(src);
        BufferedInputStream bis = new BufferedInputStream(fis);
        
        //創(chuàng)建輸出流
        FileOutputStream fos = new FileOutputStream(des);
        BufferedOutputStream bos = new BufferedOutputStream(fos);){
        
        //創(chuàng)建buffer
        byte[] buffer = new byte[1024];
        int len = 0;
        while((len = bis.read()) != -1) {
                bos.write(buffer);
        }
        bos.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }
    //也可以使用finally關(guān)閉讨韭,那么先關(guān)閉后面創(chuàng)建的,再關(guān)閉前面創(chuàng)建的
    
       
   }
}

⑦PXDException類

自定義異常類

package Tool;

//自定義異常
public class PXDException {
    //指令不存在
    static class CommondNotExistException extends Exception{
        public CommondNotExistException(String s) {
            super(s);
        }
    }
    //參數(shù)不正確
    static class CommondArgumentErrorException extends Exception{
        public CommondArgumentErrorException(String s) {
            super(s);
        }
    }
}

三.知識漏洞

1.自定義異常類使用不熟練

具體講解在:http://www.reibang.com/p/818ea803a092
主要是注意拋出和捕獲癣蟋,以及super()方法的使用透硝。

2.回調(diào)機(jī)制沒理解

關(guān)于回調(diào)機(jī)制,網(wǎng)上有一篇非常形象的文章:https://www.cnblogs.com/heshuchao/p/5376298.html
就是A繼承了接口I疯搅,然后A調(diào)用B類的一個方法濒生,把自己這個對象this傳過去,然后B類用I類型接收幔欧,再用I點的方式罪治,回調(diào)A的方法(因為A實現(xiàn)了I,調(diào)用I的那個方法礁蔗,就是調(diào)用A的相應(yīng)方法)觉义,并把執(zhí)行結(jié)果作為參數(shù)傳遞給A的那個方法,這就是我現(xiàn)在理解的數(shù)據(jù)回調(diào)浴井。
我也是查了好久晒骇,才懂了個大概,我盡量去理解,不過也可能礙于現(xiàn)在寫的代碼太少洪囤,可能理解深還是說不上徒坡。

3.文件篩選函數(shù)不會使用

具體講解在:http://www.reibang.com/p/ceb25797c109
主要是要new FilenameFilte這個r接口,并實現(xiàn)相應(yīng)方法箍鼓,這一步操作我不熟悉

4.字符串類型方法沒掌握

當(dāng)時講課的時候介紹了大量的方法崭参,還是沒有完全掌握。比如StringBuilder如何轉(zhuǎn)換為String類型啊款咖,或者是在StringBuilder類型后面追加字符串呀何暮,怎么樣獲取索引值等等等等,如何把普通數(shù)組類型轉(zhuǎn)換為List類型等等(當(dāng)然這個不屬于字符串)

四.總結(jié)

雖然看到自己還有非常多的不足铐殃,但是發(fā)現(xiàn)的不足多海洼,進(jìn)步才能多嘛!畢竟現(xiàn)在寫的項目還是太少富腊。我要吸取這次的經(jīng)驗坏逢,爭取下一次項目都不再犯同樣失誤。加油吧W副弧J钦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末民假,一起剝皮案震驚了整個濱河市浮入,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羊异,老刑警劉巖事秀,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異野舶,居然都是意外死亡易迹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門平道,熙熙樓的掌柜王于貴愁眉苦臉地迎上來睹欲,“玉大人,你說我怎么就攤上這事一屋【酱” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵陆淀,是天一觀的道長。 經(jīng)常有香客問我先嬉,道長轧苫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮含懊,結(jié)果婚禮上身冬,老公的妹妹穿的比我還像新娘。我一直安慰自己岔乔,他們只是感情好酥筝,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雏门,像睡著了一般嘿歌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茁影,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天宙帝,我揣著相機(jī)與錄音,去河邊找鬼募闲。 笑死步脓,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的浩螺。 我是一名探鬼主播靴患,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼要出!你這毒婦竟也來了鸳君?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤厨幻,失蹤者是張志新(化名)和其女友劉穎相嵌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體况脆,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡饭宾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了格了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片看铆。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖盛末,靈堂內(nèi)的尸體忽然破棺而出弹惦,到底是詐尸還是另有隱情,我是刑警寧澤悄但,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布棠隐,位于F島的核電站,受9級特大地震影響檐嚣,放射性物質(zhì)發(fā)生泄漏助泽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嗡贺。 院中可真熱鬧隐解,春花似錦、人聲如沸诫睬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摄凡。三九已至续徽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間架谎,已是汗流浹背炸宵。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留谷扣,地道東北人土全。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像会涎,于是被迫代替她去往敵國和親裹匙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354