中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

java代碼重構(gòu)大作業(yè) java大作業(yè)總結(jié)

java源代碼編輯器 設(shè)計(jì)用于編寫Java源代碼的編輯器,基本要求:可以完成源程序的文件打開,編輯和文件保存

一. 高亮的內(nèi)容:

主要從事網(wǎng)頁設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、響應(yīng)式網(wǎng)站建設(shè)、程序開發(fā)、微網(wǎng)站、小程序設(shè)計(jì)等,憑借多年來在互聯(lián)網(wǎng)的打拼,我們?cè)诨ヂ?lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了豐富的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、網(wǎng)絡(luò)營銷經(jīng)驗(yàn),集策劃、開發(fā)、設(shè)計(jì)、營銷、管理等多方位專業(yè)化運(yùn)作于一體,具備承接不同規(guī)模與類型的建設(shè)項(xiàng)目的能力。

需要高亮的內(nèi)容有:

1. 關(guān)鍵字, 如 public, int, true 等.

2. 運(yùn)算符, 如 +, -, *, /等

3. 數(shù)字

4. 高亮字符串, 如 "example of string"

5. 高亮單行注釋

6. 高亮多行注釋

二. 實(shí)現(xiàn)高亮的核心方法:

StyledDocument.setCharacterAttributes(int offset, int length, AttributeSet s, boolean replace)

三. 文本編輯器選擇.

Java中提供的多行文本編輯器有: JTextComponent, JTextArea, JTextPane, JEditorPane等, 都可以使用. 但是因?yàn)檎Z法著色中文本要使用多種風(fēng)格的樣式, 所以這些文本編輯器的document要使用StyledDocument.

JTextArea使用的是PlainDocument, 此document不能進(jìn)行多種格式的著色.

JTextPane, JEditorPane使用的是StyledDocument, 默認(rèn)就可以使用.

為了實(shí)現(xiàn)語法著色, 可以繼承自DefaultStyledDocument, 設(shè)置其為這些文本編輯器的documet, 或者也可以直接使用JTextPane, JEditorPane來做. 為了方便, 這里就直接使用JTextPane了.

四. 何時(shí)進(jìn)行著色.

當(dāng)文本編輯器中有字符被插入或者刪除時(shí), 文本的內(nèi)容就發(fā)生了變化, 這時(shí)檢查, 進(jìn)行著色.

為了監(jiān)視到文本的內(nèi)容發(fā)生了變化, 要給document添加一個(gè)DocumentListener監(jiān)聽器, 在他的removeUpdate和insertUpdate中進(jìn)行著色處理.

而changedUpdate方法在文本的屬性例如前景色, 背景色, 字體等風(fēng)格改變時(shí)才會(huì)被調(diào)用.

@Override

public void changedUpdate(DocumentEvent e) {

}

@Override

public void insertUpdate(DocumentEvent e) {

try {

colouring((StyledDocument) e.getDocument(), e.getOffset(), e.getLength());

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}

@Override

public void removeUpdate(DocumentEvent e) {

try {

// 因?yàn)閯h除后光標(biāo)緊接著影響的單詞兩邊, 所以長(zhǎng)度就不需要了

colouring((StyledDocument) e.getDocument(), e.getOffset(), 0);

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}

五. 著色范圍:

pos: 指變化前光標(biāo)的位置.

len: 指變化的字符數(shù).

例如有關(guān)鍵字public, int

單詞"publicint", 在"public"和"int"中插入一個(gè)空格后變成"public int", 一個(gè)單詞變成了兩個(gè), 這時(shí)對(duì)"public" 和 "int"進(jìn)行著色.

著色范圍是public中p的位置和int中t的位置加1, 即是pos前面單詞開始的下標(biāo)和pos+len開始單詞結(jié)束的下標(biāo). 所以上例中要著色的范圍是"public int".

提供了方法indexOfWordStart來取得pos前單詞開始的下標(biāo), 方法indexOfWordEnd來取得pos后單詞結(jié)束的下標(biāo).

public int indexOfWordStart(Document doc, int pos) throws BadLocationException {

// 從pos開始向前找到第一個(gè)非單詞字符.

for (; pos 0 isWordCharacter(doc, pos - 1); --pos);

return pos;

}

public int indexOfWordEnd(Document doc, int pos) throws BadLocationException {

// 從pos開始向前找到第一個(gè)非單詞字符.

for (; isWordCharacter(doc, pos); ++pos);

return pos;

}

一個(gè)字符是單詞的有效字符: 是字母, 數(shù)字, 下劃線.

public boolean isWordCharacter(Document doc, int pos) throws BadLocationException {

char ch = getCharAt(doc, pos); // 取得在文檔中pos位置處的字符

if (Character.isLetter(ch) || Character.isDigit(ch) || ch == '_') { return true; }

return false;

}

所以著色的范圍是[start, end] :

int start = indexOfWordStart(doc, pos);

int end = indexOfWordEnd(doc, pos + len);

六. 關(guān)鍵字著色.

從著色范圍的開始下標(biāo)起進(jìn)行判斷, 如果是以字母開或者下劃線開頭, 則說明是單詞, 那么先取得這個(gè)單詞, 如果這個(gè)單詞是關(guān)鍵字, 就進(jìn)行關(guān)鍵字著色, 如果不是, 就進(jìn)行普通的著色. 著色完這個(gè)單詞后, 繼續(xù)后面的著色處理. 已經(jīng)著色過的字符, 就不再進(jìn)行著色了.

public void colouring(StyledDocument doc, int pos, int len) throws BadLocationException {

// 取得插入或者刪除后影響到的單詞.

// 例如"public"在b后插入一個(gè)空格, 就變成了:"pub lic", 這時(shí)就有兩個(gè)單詞要處理:"pub"和"lic"

// 這時(shí)要取得的范圍是pub中p前面的位置和lic中c后面的位置

int start = indexOfWordStart(doc, pos);

int end = indexOfWordEnd(doc, pos + len);

char ch;

while (start end) {

ch = getCharAt(doc, start);

if (Character.isLetter(ch) || ch == '_') {

// 如果是以字母或者下劃線開頭, 說明是單詞

// pos為處理后的最后一個(gè)下標(biāo)

start = colouringWord(doc, start);

} else {

//SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, normalStyle));

++start;

}

}

}

public int colouringWord(StyledDocument doc, int pos) throws BadLocationException {

int wordEnd = indexOfWordEnd(doc, pos);

String word = doc.getText(pos, wordEnd - pos); // 要進(jìn)行著色的單詞

if (keywords.contains(word)) {

// 如果是關(guān)鍵字, 就進(jìn)行關(guān)鍵字的著色, 否則使用普通的著色.

// 這里有一點(diǎn)要注意, 在insertUpdate和removeUpdate的方法調(diào)用的過程中, 不能修改doc的屬性.

// 但我們又要達(dá)到能夠修改doc的屬性, 所以把此任務(wù)放到這個(gè)方法的外面去執(zhí)行.

// 實(shí)現(xiàn)這一目的, 可以使用新線程, 但放到swing的事件隊(duì)列里去處理更輕便一點(diǎn).

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, keywordStyle));

} else {

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, normalStyle));

}

return wordEnd;

}

因?yàn)樵趇nsertUpdate和removeUpdate方法中不能修改document的屬性, 所以著色的任務(wù)放到這兩個(gè)方法外面, 所以使用了SwingUtilities.invokeLater來實(shí)現(xiàn).

private class ColouringTask implements Runnable {

private StyledDocument doc;

private Style style;

private int pos;

private int len;

public ColouringTask(StyledDocument doc, int pos, int len, Style style) {

this.doc = doc;

this.pos = pos;

this.len = len;

this.style = style;

}

public void run() {

try {

// 這里就是對(duì)字符進(jìn)行著色

doc.setCharacterAttributes(pos, len, style, true);

} catch (Exception e) {}

}

}

七: 源碼

關(guān)鍵字著色的完成代碼如下, 可以直接編譯運(yùn)行. 對(duì)于數(shù)字, 運(yùn)算符, 字符串等的著色處理在以后的教程中會(huì)繼續(xù)進(jìn)行詳解.

import java.awt.Color;

import java.util.HashSet;

import java.util.Set;

import javax.swing.JFrame;

import javax.swing.JTextPane;

import javax.swing.SwingUtilities;

import javax.swing.event.DocumentEvent;

import javax.swing.event.DocumentListener;

import javax.swing.text.BadLocationException;

import javax.swing.text.Document;

import javax.swing.text.Style;

import javax.swing.text.StyleConstants;

import javax.swing.text.StyledDocument;

public class HighlightKeywordsDemo {

public static void main(String[] args) {

JFrame frame = new JFrame();

JTextPane editor = new JTextPane();

editor.getDocument().addDocumentListener(new SyntaxHighlighter(editor));

frame.getContentPane().add(editor);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(500, 500);

frame.setVisible(true);

}

}

/**

* 當(dāng)文本輸入?yún)^(qū)的有字符插入或者刪除時(shí), 進(jìn)行高亮.

*

* 要進(jìn)行語法高亮, 文本輸入組件的document要是styled document才行. 所以不要用JTextArea. 可以使用JTextPane.

*

* @author Biao

*

*/

class SyntaxHighlighter implements DocumentListener {

private SetString keywords;

private Style keywordStyle;

private Style normalStyle;

public SyntaxHighlighter(JTextPane editor) {

// 準(zhǔn)備著色使用的樣式

keywordStyle = ((StyledDocument) editor.getDocument()).addStyle("Keyword_Style", null);

normalStyle = ((StyledDocument) editor.getDocument()).addStyle("Keyword_Style", null);

StyleConstants.setForeground(keywordStyle, Color.RED);

StyleConstants.setForeground(normalStyle, Color.BLACK);

// 準(zhǔn)備關(guān)鍵字

keywords = new HashSetString();

keywords.add("public");

keywords.add("protected");

keywords.add("private");

keywords.add("_int9");

keywords.add("float");

keywords.add("double");

}

public void colouring(StyledDocument doc, int pos, int len) throws BadLocationException {

// 取得插入或者刪除后影響到的單詞.

// 例如"public"在b后插入一個(gè)空格, 就變成了:"pub lic", 這時(shí)就有兩個(gè)單詞要處理:"pub"和"lic"

// 這時(shí)要取得的范圍是pub中p前面的位置和lic中c后面的位置

int start = indexOfWordStart(doc, pos);

int end = indexOfWordEnd(doc, pos + len);

char ch;

while (start end) {

ch = getCharAt(doc, start);

if (Character.isLetter(ch) || ch == '_') {

// 如果是以字母或者下劃線開頭, 說明是單詞

// pos為處理后的最后一個(gè)下標(biāo)

start = colouringWord(doc, start);

} else {

SwingUtilities.invokeLater(new ColouringTask(doc, start, 1, normalStyle));

++start;

}

}

}

/**

* 對(duì)單詞進(jìn)行著色, 并返回單詞結(jié)束的下標(biāo).

*

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public int colouringWord(StyledDocument doc, int pos) throws BadLocationException {

int wordEnd = indexOfWordEnd(doc, pos);

String word = doc.getText(pos, wordEnd - pos);

if (keywords.contains(word)) {

// 如果是關(guān)鍵字, 就進(jìn)行關(guān)鍵字的著色, 否則使用普通的著色.

// 這里有一點(diǎn)要注意, 在insertUpdate和removeUpdate的方法調(diào)用的過程中, 不能修改doc的屬性.

// 但我們又要達(dá)到能夠修改doc的屬性, 所以把此任務(wù)放到這個(gè)方法的外面去執(zhí)行.

// 實(shí)現(xiàn)這一目的, 可以使用新線程, 但放到swing的事件隊(duì)列里去處理更輕便一點(diǎn).

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, keywordStyle));

} else {

SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd - pos, normalStyle));

}

return wordEnd;

}

/**

* 取得在文檔中下標(biāo)在pos處的字符.

*

* 如果pos為doc.getLength(), 返回的是一個(gè)文檔的結(jié)束符, 不會(huì)拋出異常. 如果pos0, 則會(huì)拋出異常.

* 所以pos的有效值是[0, doc.getLength()]

*

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public char getCharAt(Document doc, int pos) throws BadLocationException {

return doc.getText(pos, 1).charAt(0);

}

/**

* 取得下標(biāo)為pos時(shí), 它所在的單詞開始的下標(biāo). ?±wor^d?± (^表示pos, ?±表示開始或結(jié)束的下標(biāo))

*

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public int indexOfWordStart(Document doc, int pos) throws BadLocationException {

// 從pos開始向前找到第一個(gè)非單詞字符.

for (; pos 0 isWordCharacter(doc, pos - 1); --pos);

return pos;

}

/**

* 取得下標(biāo)為pos時(shí), 它所在的單詞結(jié)束的下標(biāo). ?±wor^d?± (^表示pos, ?±表示開始或結(jié)束的下標(biāo))

*

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public int indexOfWordEnd(Document doc, int pos) throws BadLocationException {

// 從pos開始向前找到第一個(gè)非單詞字符.

for (; isWordCharacter(doc, pos); ++pos);

return pos;

}

/**

* 如果一個(gè)字符是字母, 數(shù)字, 下劃線, 則返回true.

*

* @param doc

* @param pos

* @return

* @throws BadLocationException

*/

public boolean isWordCharacter(Document doc, int pos) throws BadLocationException {

char ch = getCharAt(doc, pos);

if (Character.isLetter(ch) || Character.isDigit(ch) || ch == '_') { return true; }

return false;

}

@Override

public void changedUpdate(DocumentEvent e) {

}

@Override

public void insertUpdate(DocumentEvent e) {

try {

colouring((StyledDocument) e.getDocument(), e.getOffset(), e.getLength());

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}

@Override

public void removeUpdate(DocumentEvent e) {

try {

// 因?yàn)閯h除后光標(biāo)緊接著影響的單詞兩邊, 所以長(zhǎng)度就不需要了

colouring((StyledDocument) e.getDocument(), e.getOffset(), 0);

} catch (BadLocationException e1) {

e1.printStackTrace();

}

}

/**

* 完成著色任務(wù)

*

* @author Biao

*

*/

private class ColouringTask implements Runnable {

private StyledDocument doc;

private Style style;

private int pos;

private int len;

public ColouringTask(StyledDocument doc, int pos, int len, Style style) {

this.doc = doc;

this.pos = pos;

this.len = len;

this.style = style;

}

public void run() {

try {

// 這里就是對(duì)字符進(jìn)行著色

doc.setCharacterAttributes(pos, len, style, true);

} catch (Exception e) {}

}

}

}

java中什么是代碼重構(gòu),什么時(shí)候需要代碼重構(gòu)

代碼重構(gòu)(英語:Code refactoring)重構(gòu)就是在不改變軟件系統(tǒng)外部行為的前提下,改善它的內(nèi)部結(jié)構(gòu)。

軟件重構(gòu)需要借助工具完成,重構(gòu)工具能夠修改代碼同時(shí)修改所有引用該代碼的地方。在極限編程的方法學(xué)中,重構(gòu)需要單元測(cè)試來支持。

java重構(gòu):指程序員對(duì)已有程序在盡量不改變接口的前提下,進(jìn)行重新編寫代碼的工作,一般有以下幾方面:

1、去除已知bug。

2、提高程序運(yùn)行效率。

3、增加新的功能。

重構(gòu)舉例:(簡(jiǎn)化代碼、提升效率)

重構(gòu)前:

if(list != null list.size() 0){

for(int i = 0; i list.size(); i++){

//skip...

}

}

重構(gòu)后

if(list != null){

for(int i = 0, len = list.size(); i len; i++){

//skip...

}

}

何時(shí)著手重構(gòu)(Refactoring)

新官上任三把火,開始一個(gè)全新??、腳不停蹄、加班加點(diǎn),一支聲勢(shì)浩大的千軍萬"碼"夾裹著程序員激情和扣擊鍵盤的鳴金奮力前行,勢(shì)如破竹,攻城掠地,直指"黃龍府"。

開發(fā)經(jīng)理是這支浩浩湯湯代碼隊(duì)伍的統(tǒng)帥,他負(fù)責(zé)這支隊(duì)伍的命運(yùn),當(dāng)齊桓公站在山頂上看到管仲訓(xùn)練的隊(duì)伍整齊劃一地前進(jìn)時(shí),他感嘆說"我有這樣一支軍隊(duì)哪里還怕沒有勝利呢?"。但很遺憾,你手中的這支隊(duì)伍原本只是散兵游勇,在前進(jìn)中招兵買馬,不斷壯大,所以隊(duì)伍變形在所難免。當(dāng)開發(fā)經(jīng)理發(fā)覺隊(duì)伍變形時(shí),也許就是克制住攻克前方山頭的誘惑,停下腳步整頓隊(duì)伍的時(shí)候了。

Kent Beck提出了"代碼壞味道"的說法,和我們所提出的"隊(duì)伍變形"是同樣的意思,隊(duì)伍變形的信號(hào)是什么呢?以下列述的代碼癥狀就是"隊(duì)伍變形"的強(qiáng)烈信號(hào):

·代碼中存在重復(fù)的代碼

中國有118 家整車生產(chǎn)企業(yè),數(shù)量幾乎等于美、日、歐所有汽車廠家數(shù)之和,但是全國的年產(chǎn)量卻不及一個(gè)外國大汽車公司的產(chǎn)量。重復(fù)建設(shè)只會(huì)導(dǎo)致效率的低效和資源的浪費(fèi)。

程序代碼更是不能搞重復(fù)建設(shè),如果同一個(gè)類中有相同的代碼塊,請(qǐng)把它提煉成類的一個(gè)獨(dú)立方法,如果不同類中具有相同的代碼,請(qǐng)把它提煉成一個(gè)新類,永遠(yuǎn)不要重復(fù)代碼。

·過大的類和過長(zhǎng)的方法

過大的類往往是類抽象不合理的結(jié)果,類抽象不合理將降低了代碼的復(fù)用率。方法是類王國中的諸侯國,諸侯國太大勢(shì)必動(dòng)搖中央集權(quán)。過長(zhǎng)的方法由于包含的邏輯過于復(fù)雜,錯(cuò)誤機(jī)率將直線上升,而可讀性則直線下降,類的健壯性很容易被打破。當(dāng)看到一個(gè)過長(zhǎng)的方法時(shí),需要想辦法將其劃分為多個(gè)小方法,以便于分而治之。

·牽一毛而需要?jiǎng)尤淼男薷?/p>

當(dāng)你發(fā)現(xiàn)修改一個(gè)小功能,或增加一個(gè)小功能時(shí),就引發(fā)一次代碼地震,也許是你的設(shè)計(jì)抽象度不夠理想,功能代碼太過分散所引起的。

·類之間需要過多的通訊

A類需要調(diào)用B類的過多方法訪問B的內(nèi)部數(shù)據(jù),在關(guān)系上這兩個(gè)類顯得有點(diǎn)狎昵,可能這兩個(gè)類本應(yīng)該在一起,而不應(yīng)該分家。

·過度耦合的信息鏈

"計(jì)算機(jī)是這樣一門科學(xué),它相信可以通過添加一個(gè)中間層解決任何問題",所以往往中間層會(huì)被過多地追加到程序中。如果你在代碼中看到需要獲取一個(gè)信息,需要一個(gè)類的方法調(diào)用另一個(gè)類的方法,層層掛接,就象輸油管一樣節(jié)節(jié)相連。這往往是因?yàn)殂暯訉犹嘣斐傻模枰榭淳头裼锌梢瞥闹虚g層,或是否可以提供更直接的調(diào)用方法。

·各立山頭干革命

如果你發(fā)現(xiàn)有兩個(gè)類或兩個(gè)方法雖然命名不同但卻擁有相似或相同的功能,你會(huì)發(fā)現(xiàn)往往是因?yàn)殚_發(fā)團(tuán)隊(duì)協(xié)調(diào)不夠造成的。筆者曾經(jīng)寫了一個(gè)頗好用的字符串處理類,但因?yàn)闆]有及時(shí)通告團(tuán)隊(duì)其他人員,后來發(fā)現(xiàn)項(xiàng)目中居然有三個(gè)字符串處理類。革命資源是珍貴的,我們不應(yīng)各立山頭干革命。

·不完美的設(shè)計(jì)

在筆者剛完成的一個(gè)比對(duì)報(bào)警項(xiàng)目中,曾安排阿朱開發(fā)報(bào)警模塊,即通過Socket向指定的短信平臺(tái)、語音平臺(tái)及客戶端報(bào)警器插件發(fā)送報(bào)警報(bào)文信息,阿朱出色地完成了這項(xiàng)任務(wù)。后來用戶又提出了實(shí)時(shí)比對(duì)的需求,即要求第三方系統(tǒng)以報(bào)文形式向比對(duì)報(bào)警系統(tǒng)發(fā)送請(qǐng)求,比對(duì)報(bào)警系統(tǒng)接收并響應(yīng)這個(gè)請(qǐng)求。這又需要用到Socket報(bào)文通訊,由于原來的設(shè)計(jì)沒有將報(bào)文通訊模塊獨(dú)立出來,所以無法復(fù)用阿朱開發(fā)的代碼。后來我及時(shí)調(diào)整了這個(gè)設(shè)計(jì),新增了一個(gè)報(bào)文收發(fā)模塊,使系統(tǒng)所有的對(duì)外通訊都復(fù)用這個(gè)模塊,系統(tǒng)的整體設(shè)計(jì)也顯得更加合理。

每個(gè)系統(tǒng)都或多或少存在不完美的設(shè)計(jì),剛開始可能注意不到,到后來才會(huì)慢慢凸顯出來,此時(shí)唯有勇于更改才是最好的出路。

·缺少必要的注釋

雖然許多軟件工程的書籍常提醒程序員需要防止過多注釋,但這個(gè)擔(dān)心好象并沒有什么必要。往往程序員更感興趣的是功能實(shí)現(xiàn)而非代碼注釋,因?yàn)榍罢吒軒沓删透校源a注釋往往不是過多而是過少,過于簡(jiǎn)單。人的記憶曲線下降的坡度是陡得嚇人的,當(dāng)過了一段時(shí)間后再回頭補(bǔ)注釋時(shí),很容易發(fā)生"提筆忘字,愈言且止"的情形。

曾在網(wǎng)上看到過微軟的代碼注釋,其詳盡程度讓人嘆為觀止,也從中體悟到了微軟成功的一個(gè)經(jīng)驗(yàn)。

常見代碼重構(gòu)技巧(非常實(shí)用)

1_代碼重構(gòu)漫畫.jpeg

項(xiàng)目在不斷演進(jìn)過程中,代碼不停地在堆砌。如果沒有人為代碼的質(zhì)量負(fù)責(zé),代碼總是會(huì)往越來越混亂的方向演進(jìn)。當(dāng)混亂到一定程度之后,量變引起質(zhì)變,項(xiàng)目的維護(hù)成本已經(jīng)高過重新開發(fā)一套新代碼的成本,想要再去重構(gòu),已經(jīng)沒有人能做到了。

造成這樣的原因往往有以下幾點(diǎn):

對(duì)于此類問題,業(yè)界已有有很好的解決思路:通過持續(xù)不斷的重構(gòu)將代碼中的“壞味道”清除掉。

重構(gòu)一書的作者M(jìn)artin Fowler對(duì)重構(gòu)的定義:

根據(jù)重構(gòu)的規(guī)??梢源笾路譃榇笮椭貥?gòu)和小型重構(gòu):

大型重構(gòu) :對(duì)頂層代碼設(shè)計(jì)的重構(gòu),包括:系統(tǒng)、模塊、代碼結(jié)構(gòu)、類與類之間的關(guān)系等的重構(gòu),重構(gòu)的手段有:分層、模塊化、解耦、抽象可復(fù)用組件等等。這類重構(gòu)的工具就是我們學(xué)習(xí)過的那些設(shè)計(jì)思想、原則和模式。這類重構(gòu)涉及的代碼改動(dòng)會(huì)比較多,影響面會(huì)比較大,所以難度也較大,耗時(shí)會(huì)比較長(zhǎng),引入bug的風(fēng)險(xiǎn)也會(huì)相對(duì)比較大。

小型重構(gòu) :對(duì)代碼細(xì)節(jié)的重構(gòu),主要是針對(duì)類、函數(shù)、變量等代碼級(jí)別的重構(gòu),比如規(guī)范命名和注釋、消除超大類或函數(shù)、提取重復(fù)代碼等等。小型重構(gòu)更多的是使用統(tǒng)一的編碼規(guī)范。這類重構(gòu)要修改的地方比較集中,比較簡(jiǎn)單,可操作性較強(qiáng),耗時(shí)會(huì)比較短,引入bug的風(fēng)險(xiǎn)相對(duì)來說也會(huì)比較小。什么時(shí)候重構(gòu) 新功能開發(fā)、修bug或者代碼review中出現(xiàn)“代碼壞味道”,我們就應(yīng)該及時(shí)進(jìn)行重構(gòu)。持續(xù)在日常開發(fā)中進(jìn)行小重構(gòu),能夠降低重構(gòu)和測(cè)試的成本。

2_代碼常見問題.png

代碼重復(fù)

方法過長(zhǎng)

過大的類

邏輯分散

嚴(yán)重的情結(jié)依戀

數(shù)據(jù)泥團(tuán)/基本類型偏執(zhí)

不合理的繼承體系

過多的條件判斷

過長(zhǎng)的參數(shù)列

臨時(shí)變量過多

令人迷惑的暫時(shí)字段

純數(shù)據(jù)類

不恰當(dāng)?shù)拿?/p>

過多的注釋

3_代碼質(zhì)量如何衡量.jpg

代碼質(zhì)量的評(píng)價(jià)有很強(qiáng)的主觀性,描述代碼質(zhì)量的詞匯也有很多,比如可讀性、可維護(hù)性、靈活、優(yōu)雅、簡(jiǎn)潔。這些詞匯是從不同的維度去評(píng)價(jià)代碼質(zhì)量的。其中,可維護(hù)性、可讀性、可擴(kuò)展性又是提到最多的、最重要的三個(gè)評(píng)價(jià)標(biāo)準(zhǔn)。

要寫出高質(zhì)量代碼,我們就需要掌握一些更加細(xì)化、更加能落地的編程方法論,這就包含面向?qū)ο笤O(shè)計(jì)思想、設(shè)計(jì)原則、設(shè)計(jì)模式、編碼規(guī)范、重構(gòu)技巧等。

4_SOLID原則.png

一個(gè)類只負(fù)責(zé)完成一個(gè)職責(zé)或者功能,不要存在多于一種導(dǎo)致類變更的原因。

單一職責(zé)原則通過避免設(shè)計(jì)大而全的類,避免將不相關(guān)的功能耦合在一起,來提高類的內(nèi)聚性。同時(shí),類職責(zé)單一,類依賴的和被依賴的其他類也會(huì)變少,減少了代碼的耦合性,以此來實(shí)現(xiàn)代碼的高內(nèi)聚、松耦合。但是,如果拆分得過細(xì),實(shí)際上會(huì)適得其反,反倒會(huì)降低內(nèi)聚性,也會(huì)影響代碼的可維護(hù)性。

添加一個(gè)新的功能,應(yīng)該是通過在已有代碼基礎(chǔ)上擴(kuò)展代碼(新增模塊、類、方法、屬性等),而非修改已有代碼(修改模塊、類、方法、屬性等)的方式來完成。

開閉原則并不是說完全杜絕修改,而是以最小的修改代碼的代價(jià)來完成新功能的開發(fā)。

很多設(shè)計(jì)原則、設(shè)計(jì)思想、設(shè)計(jì)模式,都是以提高代碼的擴(kuò)展性為最終目的的。特別是 23 種經(jīng)典設(shè)計(jì)模式,大部分都是為了解決代碼的擴(kuò)展性問題而總結(jié)出來的,都是以開閉原則為指導(dǎo)原則的。最常用來提高代碼擴(kuò)展性的方法有:多態(tài)、依賴注入、基于接口而非實(shí)現(xiàn)編程,以及大部分的設(shè)計(jì)模式(比如,裝飾、策略、模板、職責(zé)鏈、狀態(tài))。

子類對(duì)象(object of subtype/derived class)能夠替換程序(program)中父類對(duì)象(object of base/parent class)出現(xiàn)的任何地方,并且保證原來程序的邏輯行為(behavior)不變及正確性不被破壞。

子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能

調(diào)用方不應(yīng)該依賴它不需要的接口;一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上。接口隔離原則提供了一種判斷接口的職責(zé)是否單一的標(biāo)準(zhǔn):通過調(diào)用者如何使用接口來間接地判定。如果調(diào)用者只使用部分接口或接口的部分功能,那接口的設(shè)計(jì)就不夠職責(zé)單一。

高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象。

一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解

盡量使用合成/聚合的方式,而不是使用繼承。

單一職責(zé)原則告訴我們實(shí)現(xiàn)類要職責(zé)單一;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向接口編程;接口隔離原則告訴我們?cè)谠O(shè)計(jì)接口的時(shí)候要精簡(jiǎn)單一;迪米特法則告訴我們要降低耦合。而開閉原則是總綱,告訴我們要對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。

image.png

模塊結(jié)構(gòu)說明

代碼開發(fā)要遵守各層的規(guī)范,并注意層級(jí)之間的依賴關(guān)系。

多個(gè)方法代碼重復(fù)、方法中代碼過長(zhǎng)或者方法中的語句不在一個(gè)抽象層級(jí)。

方法是代碼復(fù)用的最小粒度,方法過長(zhǎng)不利于復(fù)用,可讀性低,提煉方法往往是重構(gòu)工作的第一步。

意圖導(dǎo)向編程 :把處理某件事的流程和具體做事的實(shí)現(xiàn)方式分開。

將函數(shù)放進(jìn)一個(gè)單獨(dú)對(duì)象中,如此一來局部變量就變成了對(duì)象內(nèi)的字段。然后你可以在同一個(gè)對(duì)象中將這個(gè)大型函數(shù)分解為多個(gè)小型函數(shù)。

方法參數(shù)比較多時(shí),將參數(shù)封裝為參數(shù)對(duì)象

任何有返回值的方法,都不應(yīng)該有副作用

臨時(shí)變量?jī)H使用一次或者取值邏輯成本很低的情況下

將復(fù)雜表達(dá)式(或其中一部分)的結(jié)果放進(jìn)一個(gè)臨時(shí)變量,以此變量名稱來解釋表達(dá)式用途

把復(fù)雜的條件表達(dá)式拆分成多個(gè)條件表達(dá)式,減少嵌套。嵌套了好幾層的if - then-else語句,轉(zhuǎn)換為多個(gè)if語句

當(dāng)出現(xiàn)大量類型檢查和判斷時(shí),if else(或switch)語句的體積會(huì)比較臃腫,這無疑降低了代碼的可讀性。 另外,if else(或switch)本身就是一個(gè)“變化點(diǎn)”,當(dāng)需要擴(kuò)展新的類型時(shí),我們不得不追加if else(或switch)語句塊,以及相應(yīng)的邏輯,這無疑降低了程序的可擴(kuò)展性,也違反了面向?qū)ο蟮拈_閉原則。

非正常業(yè)務(wù)狀態(tài)的處理,使用拋出異常的方式代替返回錯(cuò)誤碼

某一段代碼需要對(duì)程序狀態(tài)做出某種假設(shè),以斷言明確表現(xiàn)這種假設(shè)。

當(dāng)使用一個(gè)方法返回的對(duì)象時(shí),而這個(gè)對(duì)象可能為空,這個(gè)時(shí)候需要對(duì)這個(gè)對(duì)象進(jìn)行操作前,需要進(jìn)行判空,否則就會(huì)報(bào)空指針。當(dāng)這種判斷頻繁的出現(xiàn)在各處代碼之中,就會(huì)影響代碼的美觀程度和可讀性,甚至增加Bug的幾率。

空引用的問題在Java中無法避免,但可以通過代碼編程技巧(引入空對(duì)象)來改善這一問題。

根據(jù)單一職責(zé)原則,一個(gè)類應(yīng)該有明確的責(zé)任邊界。但在實(shí)際工作中,類會(huì)不斷的擴(kuò)展。當(dāng)給某個(gè)類添加一項(xiàng)新責(zé)任時(shí),你會(huì)覺得不值得分離出一個(gè)單獨(dú)的類。于是,隨著責(zé)任不斷增加,這個(gè)類包含了大量的數(shù)據(jù)和函數(shù),邏輯復(fù)雜不易理解。

此時(shí)你需要考慮將哪些部分分離到一個(gè)單獨(dú)的類中,可以依據(jù)高內(nèi)聚低耦合的原則。如果某些數(shù)據(jù)和方法總是一起出現(xiàn),或者某些數(shù)據(jù)經(jīng)常同時(shí)變化,這就表明它們應(yīng)該放到一個(gè)類中。另一種信號(hào)是類的子類化方式:如果你發(fā)現(xiàn)子類化只影響類的部分特性,或者類的特性需要以不同方式來子類化,這就意味著你需要分解原來的類。

繼承使實(shí)現(xiàn)代碼重用的有力手段,但這并非總是完成這項(xiàng)工作的最佳工具,使用不當(dāng)會(huì)導(dǎo)致軟件變得很脆弱。與方法調(diào)用不同的是,繼承打破了封裝性。子類依賴于其父類中特定功能的實(shí)現(xiàn)細(xì)節(jié),如果父類的實(shí)現(xiàn)隨著發(fā)行版本的不同而變化,子類可能會(huì)遭到破壞,即使他的代碼完全沒有改變。

舉例說明,假設(shè)有一個(gè)程序使用HashSet,為了調(diào)優(yōu)該程序的性能,需要統(tǒng)計(jì)HashSet自從它創(chuàng)建以來添加了多少個(gè)元素。為了提供該功能,我們編寫一個(gè)HashSet的變體。

通過在新的類中增加一個(gè)私有域,它引用現(xiàn)有類的一個(gè)實(shí)例,這種設(shè)計(jì)被稱為組合,因?yàn)楝F(xiàn)有的類變成了新類的一個(gè)組件。這樣得到的類將會(huì)非常穩(wěn)固,它不依賴現(xiàn)有類的實(shí)現(xiàn)細(xì)節(jié)。即使現(xiàn)有的類添加了新的方法,也不會(huì)影響新的類。許多設(shè)計(jì)模式使用就是這種套路,比如代理模式、裝飾者模式

繼承與組合如何取舍

Java提供了兩種機(jī)制,可以用來定義允許多個(gè)實(shí)現(xiàn)的類型:接口和抽象類。自從Java8為接口增加缺省方法(default method),這兩種機(jī)制都允許為實(shí)例方法提供實(shí)現(xiàn)。主要區(qū)別在于,為了實(shí)現(xiàn)由抽象類定義的類型,類必須稱為抽象類的一個(gè)子類。因?yàn)镴ava只允許單繼承,所以用抽象類作為類型定義受到了限制。

接口相比于抽象類的優(yōu)勢(shì):

接口雖然提供了缺省方法,但接口仍有有以下局限性:

接口缺省方法的設(shè)計(jì)目的和優(yōu)勢(shì)在于:

為了接口的演化

可以減少第三方工具類的創(chuàng)建

可以避免創(chuàng)建基類

由于接口的局限性和設(shè)計(jì)目的的不同,接口并不能完全替換抽象類。但是通過對(duì)接口提供一個(gè)抽象的骨架實(shí)現(xiàn)類,可以把接口和抽象類的優(yōu)點(diǎn)結(jié)合起來。 接口負(fù)責(zé)定義類型,或許還提供一些缺省方法,而骨架實(shí)現(xiàn)類則負(fù)責(zé)實(shí)現(xiàn)除基本類型接口方法之外,剩下的非基本類型接口方法。擴(kuò)展骨架實(shí)現(xiàn)占了實(shí)現(xiàn)接口之外的大部分工作。這就是模板方法(Template Method)設(shè)計(jì)模式。

Image [5].png

接口Protocol:定義了RPC協(xié)議層兩個(gè)主要的方法,export暴露服務(wù)和refer引用服務(wù)

抽象類AbstractProtocol:封裝了暴露服務(wù)之后的Exporter和引用服務(wù)之后的Invoker實(shí)例,并實(shí)現(xiàn)了服務(wù)銷毀的邏輯

具體實(shí)現(xiàn)類XxxProtocol:實(shí)現(xiàn)export暴露服務(wù)和refer引用服務(wù)具體邏輯

由于為了保持Java代碼的兼容性,支持和原生態(tài)類型轉(zhuǎn)換,并使用擦除機(jī)制實(shí)現(xiàn)的泛型。但是使用原生態(tài)類型就會(huì)失去泛型的優(yōu)勢(shì),會(huì)受到編譯器警告。

每一條警告都表示可能在運(yùn)行時(shí)拋出ClassCastException異常。要盡最大的努力去消除這些警告。如果無法消除但是可以證明引起警告的代碼是安全的,就可以在盡可能小的范圍中,使用@SuppressWarnings("unchecked")注解來禁止警告,但是要把禁止的原因記錄下來。

參數(shù)化類型不支持協(xié)變的,即對(duì)于任何兩個(gè)不同的類型Type1和Type2而言,List既不是List的子類型,也不是它的超類。為了解決這個(gè)問題,提高靈活性,Java提供了一種特殊的參數(shù)化類型,稱作有限制的通配符類型,即List? extends E和List? super E。使用原則是producer-extends,consumer-super(PECS)。如果即是生產(chǎn)者,又是消費(fèi)者,就沒有必要使用通配符了。

還有一種特殊的無限制通配符List?,表示某種類型但不確定。常用作泛型的引用,不可向其添加除Null以外的任何對(duì)象。

嵌套類(nested class)是指定義在另一個(gè)類的內(nèi)部的類。 嵌套類存在的目的只是為了它的外部類提供服務(wù),如果其他的環(huán)境也會(huì)用到的話,應(yīng)該成為一個(gè)頂層類(top-level class)。 嵌套類有四種:靜態(tài)成員類(static member class)、非靜態(tài)成員類(nonstatic member class)、匿名類(anonymous class)和 局部類(local class)。除了第一種之外,其他三種都稱為內(nèi)部類(inner class)。

總而言之,這四種嵌套類都有自己的用途。假設(shè)這個(gè)嵌套類屬于一個(gè)方法的內(nèi)部,如果只需要在一個(gè)地方創(chuàng)建實(shí)例,并且已經(jīng)有了一個(gè)預(yù)置的類型可以說明這個(gè)類的特征,就要把它做成匿名類。如果一個(gè)嵌套類需要在單個(gè)方法之外仍然可見,或者它太長(zhǎng)了,不適合放在方法內(nèi)部,就應(yīng)該使用成員類。如果成員類的每個(gè)實(shí)例都需要一個(gè)指向其外圍實(shí)例的引用,就要把成員類做成非靜態(tài)的,否則就做成靜態(tài)的。

通過對(duì)常見場(chǎng)景的代碼邏輯進(jìn)行抽象封裝,形成相應(yīng)的模板工具類,可以大大減少重復(fù)代碼,專注于業(yè)務(wù)邏輯,提高代碼質(zhì)量。

面向?qū)ο缶幊滔鄬?duì)于面向過程,多了實(shí)例化這一步,而對(duì)象的創(chuàng)建必須要指定具體類型。我們常見的做法是“哪里用到,就在哪里創(chuàng)建”,使用實(shí)例和創(chuàng)建實(shí)例的是同一段代碼。這似乎使代碼更具有可讀性,但是某些情況下造成了不必要的耦合。

對(duì)于頂層的(非嵌套的)類和接口,只有兩種的訪問級(jí)別:包級(jí)私有的(沒有public修飾)和公有的(public修飾)。

對(duì)于成員(實(shí)例/域、方法、嵌套類和嵌套接口)由四種的訪問級(jí)別,可訪問性如下遞增:

正確地使用這些修飾符對(duì)于實(shí)現(xiàn)信息隱藏是非常關(guān)鍵的,原則就是:盡可能地使每個(gè)類和成員不被外界訪問(私有或包級(jí)私有)。這樣好處就是在以后的發(fā)行版本中,可以對(duì)它進(jìn)行修改、替換或者刪除,而無須擔(dān)心會(huì)影響現(xiàn)有的客戶端程序。

不可變類是指其實(shí)例不能被修改的類。每個(gè)實(shí)例中包含的所有信息都必須在創(chuàng)建該實(shí)例時(shí)提供,并在對(duì)象的整個(gè)生命周期內(nèi)固定不變。不可變類好處就是簡(jiǎn)單易用、線程安全、可自由共享而不容易出錯(cuò)。Java平臺(tái)類庫中包含許多不可變的類,比如String、基本類型包裝類、BigDecimal等。

為了使類成為不可變,要遵循下面五條規(guī)則:

可變性最小化的一些建議:

TDD的最終目標(biāo)是整潔可用的代碼(clean code that works)。大多數(shù)的開發(fā)者大部分時(shí)間無法得到整潔可用的代碼。辦法是分而治之。首先解決目標(biāo)中的“可用”問題,然后再解決“代碼的整潔”問題。這與體系結(jié)構(gòu)驅(qū)動(dòng)(architecture-driven)的開發(fā)相反。

采用TDD另一個(gè)好處就是讓我們擁有一套伴隨代碼產(chǎn)生的詳盡的自動(dòng)化測(cè)試集。將來無論出于任何原因(需求、重構(gòu)、性能改進(jìn))需要對(duì)代碼進(jìn)行維護(hù)時(shí),在這套測(cè)試集的驅(qū)動(dòng)下工作,我們代碼將會(huì)一直是健壯的。

Image [6].png

添加一個(gè)測(cè)試 - 運(yùn)行所有測(cè)試并檢查測(cè)試結(jié)果 - 編寫代碼以通過測(cè)試 - 運(yùn)行所有測(cè)試且全部通過 - 重構(gòu)代碼,以消除重復(fù)設(shè)計(jì),優(yōu)化設(shè)計(jì)結(jié)構(gòu)

作者:VectorJin

需要一份500行的java程序,期末大作業(yè),最好帶詳細(xì)注釋。

Java生成CSV文件簡(jiǎn)單操作實(shí)例

CSV是逗號(hào)分隔文件(Comma Separated Values)的首字母英文縮寫,是一種用來存儲(chǔ)數(shù)據(jù)的純文本格式,通常用于電子表格或數(shù)據(jù)庫軟件。在 CSV文件中,數(shù)據(jù)“欄”以逗號(hào)分隔,可允許程序通過讀取文件為數(shù)據(jù)重新創(chuàng)建正確的欄結(jié)構(gòu),并在每次遇到逗號(hào)時(shí)開始新的一欄。如:

123? ?1,張三,男2,李四,男3,小紅,女? ?

Java生成CSV文件(創(chuàng)建與導(dǎo)出封裝類)

package com.yph.omp.common.util;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.LinkedHashMap;

import java.util.List;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import org.junit.Test;

/**

* Java生成CSV文件

*/

public class CSVUtil {

/**

* 生成為CVS文件

*

* @param exportData

*? ? ? ? ? ? 源數(shù)據(jù)List

* @param map

*? ? ? ? ? ? csv文件的列表頭map

* @param outPutPath

*? ? ? ? ? ? 文件路徑

* @param fileName

*? ? ? ? ? ? 文件名稱

* @return

*/

@SuppressWarnings("rawtypes")

public static File createCSVFile(List exportData, LinkedHashMap map,

String outPutPath, String fileName) {

File csvFile = null;

BufferedWriter csvFileOutputStream = null;

try {

File file = new File(outPutPath);

if (!file.exists()) {

file.mkdir();

}

// 定義文件名格式并創(chuàng)建

csvFile = File.createTempFile(fileName, ".csv",

new File(outPutPath));

// UTF-8使正確讀取分隔符","

csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(

new FileOutputStream(csvFile), "GBK"), 1024);

// 寫入文件頭部

for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator

.hasNext();) {

java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator

.next();

csvFileOutputStream

.write("\"" + (String) propertyEntry.getValue() != null ? (String) propertyEntry

.getValue() : "" + "\"");

if (propertyIterator.hasNext()) {

csvFileOutputStream.write(",");

}

}

csvFileOutputStream.newLine();

// 寫入文件內(nèi)容

for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {

Object row = (Object) iterator.next();

for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator

.hasNext();) {

java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator

.next();

/*-------------------------------*/ 

//以下部分根據(jù)不同業(yè)務(wù)做出相應(yīng)的更改

StringBuilder sbContext = new StringBuilder("");

if (null != BeanUtils.getProperty(row,(String) propertyEntry.getKey())) {

if("證件號(hào)碼".equals(propertyEntry.getValue())){

//避免:身份證號(hào)碼 ,讀取時(shí)變換為科學(xué)記數(shù) - 解決辦法:加 \t(用Excel打開時(shí),證件號(hào)碼超過15位后會(huì)自動(dòng)默認(rèn)科學(xué)記數(shù))

sbContext.append(BeanUtils.getProperty(row,(String) propertyEntry.getKey()) + "\t");

}else{

sbContext.append(BeanUtils.getProperty(row,(String) propertyEntry.getKey()));? ? ? ? ? ? ? ? ? ? ? ? ?

}

}

csvFileOutputStream.write(sbContext.toString());

/*-------------------------------*/? ? ? ? ? ? ? ? ?

if (propertyIterator.hasNext()) {

csvFileOutputStream.write(",");

}

}

if (iterator.hasNext()) {

csvFileOutputStream.newLine();

}

}

csvFileOutputStream.flush();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

csvFileOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return csvFile;

}

/**

* 下載文件

*

* @param response

* @param csvFilePath

*? ? ? ? ? ? 文件路徑

* @param fileName

*? ? ? ? ? ? 文件名稱

* @throws IOException

*/

public static void exportFile(HttpServletRequest request,

HttpServletResponse response, String csvFilePath, String fileName)

throws IOException {

response.setCharacterEncoding("UTF-8");

response.setContentType("application/csv;charset=GBK");

response.setHeader("Content-Disposition", "attachment; filename="

+ new String(fileName.getBytes("GB2312"), "ISO8859-1"));

InputStream in = null;

try {

in = new FileInputStream(csvFilePath);

int len = 0;

byte[] buffer = new byte[1024];

OutputStream out = response.getOutputStream();

while ((len = in.read(buffer)) 0) {

out.write(buffer, 0, len);

}

} catch (FileNotFoundException e1) {

System.out.println(e1);

} finally {

if (in != null) {

try {

in.close();

} catch (Exception e1) {

throw new RuntimeException(e1);

}

}

}

}

/**

* 刪除該目錄filePath下的所有文件

*

* @param filePath

*? ? ? ? ? ? 文件目錄路徑

*/

public static void deleteFiles(String filePath) {

File file = new File(filePath);

if (file.exists()) {

File[] files = file.listFiles();

for (int i = 0; i files.length; i++) {

if (files[i].isFile()) {

files[i].delete();

}

}

}

}

/**

* 刪除單個(gè)文件

*

* @param filePath

*? ? ? ? ? ? 文件目錄路徑

* @param fileName

*? ? ? ? ? ? 文件名稱

*/

public static void deleteFile(String filePath, String fileName) {

File file = new File(filePath);

if (file.exists()) {

File[] files = file.listFiles();

for (int i = 0; i files.length; i++) {

if (files[i].isFile()) {

if (files[i].getName().equals(fileName)) {

files[i].delete();

return;

}

}

}

}

}

@SuppressWarnings({ "unchecked", "rawtypes" })

@Test

public void createFileTest() {

List exportData = new ArrayListMap();

Map row1 = new LinkedHashMapString, String();

row1.put("1", "11");

row1.put("2", "12");

row1.put("3", "13");

row1.put("4", "14");

exportData.add(row1);

row1 = new LinkedHashMapString, String();

row1.put("1", "21");

row1.put("2", "22");

row1.put("3", "23");

row1.put("4", "24");

exportData.add(row1);

LinkedHashMap map = new LinkedHashMap();

map.put("1", "第一列");

map.put("2", "第二列");

map.put("3", "第三列");

map.put("4", "第四列");

String path = "d:/export";

String fileName = "文件導(dǎo)出";

File file = CSVUtil.createCSVFile(exportData, map, path, fileName);

String fileNameNew = file.getName();

String pathNew = file.getPath();

System.out.println("文件名稱:" + fileNameNew );

System.out.println("文件路徑:" + pathNew );

}

}

//注:BeanUtils.getProperty(row,(String) propertyEntry.getKey()) + "\t" ,只為解決數(shù)字格式超過15位后,在Excel中打開展示科學(xué)記數(shù)問題。

java 代碼重用 真么體現(xiàn)的? 重構(gòu)和重用是一個(gè)意識(shí)嗎?

重構(gòu)可以說是覆蓋,用覆蓋一詞來講就比較清楚。

在面向?qū)ο蟮囊粋€(gè)特性--繼承中就表現(xiàn)出重構(gòu)的意思。

重構(gòu),就是繼承于父類方法的子類將子類的方法重寫,方法名及參數(shù)完全相同.

重用是繼承了就可以用父類定義的方法和變量,不用再定義一次。

比如說

class B {

public void see(){

System.out.println("this is b");

}

}

public class A extends B{

public void see() {

System.out.println("this is a");

}

public static void main(String[] args) {

B b=new A();

b.see();

}

}

這是重構(gòu)的意思。

class B {

public void see(){

System.out.println("this is b");

}

}

public class A extends B{

public static void main(String[] args) {

B b=new A();

b.see();

}

}

這是重用的意思

文章題目:java代碼重構(gòu)大作業(yè) java大作業(yè)總結(jié)
本文路徑:http://m.rwnh.cn/article14/doocige.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站云服務(wù)器、品牌網(wǎng)站建設(shè)、微信小程序、品牌網(wǎng)站制作、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管
綦江县| 安仁县| 凤城市| 泾阳县| 奉化市| 呼和浩特市| 浮山县| 安康市| 防城港市| 定兴县| 葫芦岛市| 房产| 凉山| 五莲县| 鄂伦春自治旗| 博爱县| 石阡县| 闽清县| 阜康市| 西青区| 丹凤县| 长海县| 曲靖市| 桐梓县| 沁水县| 章丘市| 岐山县| 河间市| 阳东县| 屏东市| 桂平市| 嘉义县| 甘南县| 嫩江县| 江陵县| 封开县| 东源县| 都匀市| 遂溪县| 阜城县| 云南省|