日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通用编程准则

發(fā)布時(shí)間:2023/12/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通用编程准则 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文是我們名為“ 高級Java ”的學(xué)院課程的一部分。

本課程旨在幫助您最有效地使用Java。 它討論了高級主題,包括對象創(chuàng)建,并發(fā),序列化,反射等。 它將指導(dǎo)您完成Java掌握的過程! 在這里查看 !

目錄

1.簡介 2.可變范圍 3.類字段和局部變量 4.方法參數(shù)和局部變量 5.裝箱和拆箱 6.接口 7.琴弦 8.命名約定 9.標(biāo)準(zhǔn)庫 10.不變性 11.測試 12.接下來是什么 13.下載源代碼

1.簡介

在本部分的教程中,我們將繼續(xù)討論Java良好編程風(fēng)格和健壯設(shè)計(jì)的一般原理。 我們已經(jīng)在本教程的前面部分中看到了其中一些原則,但是在此過程中將引入許多新的實(shí)用建議,以提高您作為Java開發(fā)人員的技能。

2.可變范圍

在本教程的第3部分如何設(shè)計(jì)類和接口中 ,我們討論了如何將可見性和可訪問性應(yīng)用于類和接口成員,從而限制了它們的范圍。 但是,我們尚未討論在方法實(shí)現(xiàn)中使用的局部變量。

在Java語言中,每個(gè)局部變量(一旦聲明)都有一個(gè)作用域。 從聲明位置到聲明的方法(或代碼塊)的末尾,該變量將變?yōu)榭梢姟R虼?#xff0c;只有一條規(guī)則可遵循:將局部變量聲明為靠近其所在的位置盡可能使用。 讓我們看一些典型的例子:

for( final Locale locale: Locale.getAvailableLocales() ) {// Some implementation here }try( final InputStream in = new FileInputStream( "file.txt" ) ) {// Some implementation here }

在這兩個(gè)代碼段中,局部變量的范圍都限于它們在其中聲明的執(zhí)行塊。一旦塊結(jié)束,局部變量將超出范圍,并且不再可見。 看起來簡潔明了,但是隨著Java 8的發(fā)布和lambda的引入,使用局部變量的許多眾所周知的習(xí)慣用法已經(jīng)過時(shí)了。 讓我們重寫前面示例中的for-each循環(huán),改為使用lambda:

Arrays.stream( Locale.getAvailableLocales() ).forEach( ( locale ) -> {// Some implementation here} );

局部變量成為函數(shù)的參數(shù),該函數(shù)本身作為forEach方法的參數(shù)傳遞。

3.類字段和局部變量

Java中的每個(gè)方法都屬于某個(gè)類(如果是Java 8,則該接口屬于某個(gè)接口,并且該方法被聲明為default )。 這樣,在方法實(shí)現(xiàn)中使用的局部變量與類成員之間可能會(huì)發(fā)生名稱沖突。 Java編譯器可以從范圍中選擇正確的變量,盡管它可能不是開發(fā)人員打算使用的變量。 現(xiàn)代Java IDE進(jìn)行了大量工作,以向開發(fā)人員提示發(fā)生此類沖突的時(shí)間(警告,突出顯示等),但是在開發(fā)時(shí)最好考慮一下。 讓我們看一下這個(gè)例子:

public class LocalVariableAndClassMember {private long value;public long calculateValue( final long initial ) {long value = initial; value *= 10;value += value;return value;}}

該示例看起來很簡單,但是有一個(gè)陷阱。 方法calculateValue引入一個(gè)具有名稱value的局部變量,并以此隱藏具有相同名稱的類成員。 第08行本應(yīng)該將類成員和局部變量相加,但是它所做的卻非常不同。 正確的版本可能如下所示(使用關(guān)鍵字this ):

public class LocalVariableAndClassMember {private long value;public long calculateValue( final long initial ) {long value = initial; value *= 10;value += this.value; return value;}}

雖然有些天真的實(shí)現(xiàn),但它突出了重要的問題,在某些情況下,調(diào)試和故障排除可能要花費(fèi)數(shù)小時(shí)。

4.方法參數(shù)和局部變量

Java開發(fā)人員經(jīng)常遇到的另一個(gè)陷阱是使用方法參數(shù)作為局部變量。 Java允許用不同的值重新分配非final方法參數(shù)(但是,它對原始值沒有任何影響)。 例如:

public String sanitize( String str ) {if( !str.isEmpty() ) {str = str.trim();}str = str.toLowerCase();return str; }

它不是一段漂亮的代碼,但足以說明問題:將方法參數(shù)str重新分配給另一個(gè)值(基本上用作局部變量)。 在所有情況下(無一例外),可以并且應(yīng)該避免這種模式(例如,通過將方法參數(shù)聲明為final )。 例如:

public String sanitize( final String str ) {String sanitized = str;if( !str.isEmpty() ) {sanitized = str.trim();}sanitized = sanitized.toLowerCase();return sanitized; }

即使遵循引入本地變量的代價(jià),遵循此簡單規(guī)則的代碼也更易于遵循和推理。

5.裝箱和拆箱

裝箱和拆箱都是Java語言中用于在原始類型(例如int , long , double )之間轉(zhuǎn)換為各自的原始類型包裝器(例如Integer , Long , Double )的相同技術(shù)的名稱。 在本教程的第4部分“ 如何以及何時(shí)使用Generics”中 ,我們已經(jīng)在討論原始類型包裝器作為泛型類型參數(shù)時(shí)看到了它的實(shí)際作用。

盡管Java編譯器試圖通過執(zhí)行自動(dòng)裝箱來盡力隱藏這些轉(zhuǎn)換,但有時(shí)它會(huì)使情況變得更糟并導(dǎo)致意外的結(jié)果。 讓我們看一下這個(gè)例子:

public static void calculate( final long value ) {// Some implementation here }final Long value = null;calculate( value );

上面的代碼段可以很好地編譯,但是當(dāng)Long和long之間的轉(zhuǎn)換發(fā)生時(shí),它將在第02行拋出NullPointerException 。 這里的建議是更喜歡使用原始類型(但是,我們已經(jīng)知道,這并不總是可能的)。

6.接口

在本教程的第3部分“ 如何設(shè)計(jì)類和接口”中 ,我們討論了基于接口和基于契約的開發(fā),并著重強(qiáng)調(diào)了在可能的情況下,接口應(yīng)優(yōu)先于具體類的事實(shí)。 本節(jié)的目的是通過展示真實(shí)的示例來說服您再有時(shí)間首先考慮接口。

接口不依賴于任何特定的實(shí)現(xiàn)(默認(rèn)方法是一個(gè)例外)。 它們只是合同,因此,它們在履行合同的方式上提供了很多自由和靈活性。 當(dāng)實(shí)施涉及外部系統(tǒng)或服務(wù)時(shí),這種靈活性變得越來越重要。 讓我們看一下以下簡單接口及其可能的實(shí)現(xiàn):

public interface TimezoneService {TimeZone getTimeZone( final double lat, final double lon ) throws IOException; }public class TimezoneServiceImpl implements TimezoneService {@Overridepublic TimeZone getTimeZone(final double lat, final double lon) throws IOException {final URL url = new URL( String.format("http://api.geonames.org/timezone?lat=%.2f&lng=%.2f&username=demo",lat, lon) );final HttpURLConnection connection = ( HttpURLConnection )url.openConnection();connection.setRequestMethod( "GET" );connection.setConnectTimeout( 1000 );connection.setReadTimeout( 1000 );connection.connect();int status = connection.getResponseCode();if (status == 200) {// Do something here}return TimeZone.getDefault();} }

上面的代碼段演示了典型的接口/實(shí)現(xiàn)模式。 該實(shí)現(xiàn)使用外部HTTP服務(wù)( http://api.geonames.org/ )來檢索特定位置的時(shí)區(qū)。 但是,由于聯(lián)系方式是由界面驅(qū)動(dòng)的,因此很容易引入另一個(gè)使用數(shù)據(jù)庫或什至平面文件的實(shí)現(xiàn)。 這樣,接口可以極大地幫助設(shè)計(jì)可測試的代碼。 例如,在每次測試運(yùn)行中調(diào)用外部服務(wù)并不總是可行的,因此提供替代的虛擬實(shí)現(xiàn)(也稱為存根或模擬)是有意義的:

public class TimezoneServiceTestImpl implements TimezoneService {@Overridepublic TimeZone getTimeZone(final double lat, final double lon) throws IOException {return TimeZone.getDefault();} }

此實(shí)現(xiàn)可在需要TimezoneService接口的每個(gè)地方使用,從而將測試方案與對外部組件的依賴隔離開來。

在Java標(biāo)準(zhǔn)集合庫中封裝了許多適當(dāng)使用接口的出色示例。 Collection , List , Set ,所有這些接口都有幾種實(shí)現(xiàn)的支持,當(dāng)傾向于使用合同時(shí),這些實(shí)現(xiàn)可以無縫且可互換地替換,例如:

public static< T > void print( final Collection< T > collection ) {for( final T element: collection ) {System.out.println( element );} }print( new HashSet< Object >( /* ... */ ) ); print( new ArrayList< Integer >( /* ... */ ) ); print( new TreeSet< String >( /* ... */ ) ); print( new Vector< Long >( /* ... */ ) );

7.琴弦

字符串是Java以及大多數(shù)編程語言中使用最廣泛的類型之一。 Java語言通過本機(jī)支持串聯(lián)和比較,大大簡化了字符串常規(guī)操作。 另外,Java標(biāo)準(zhǔn)庫提供了許多不同的類來提高字符串操作的效率,這就是我們將在本節(jié)中討論的內(nèi)容。

在Java中,字符串是不可變的對象,以UTF-16格式表示。 每次連接字符串(或執(zhí)行任何修改原始字符串的操作)時(shí),都會(huì)創(chuàng)建String類的新實(shí)例。 因此,連接操作可能會(huì)變得非常無效,從而導(dǎo)致創(chuàng)建許多中間字符串實(shí)例(通常來說,會(huì)生成垃圾)。

但是Java標(biāo)準(zhǔn)庫提供了兩個(gè)非常有用的類,旨在促進(jìn)字符串操作: StringBuilder和StringBuffer (它們之間的唯一區(qū)別是StringBuffer是線程安全的,而StringBuilder不是)。 讓我們看看使用這些類之一的幾個(gè)示例:

final StringBuilder sb = new StringBuilder();for( int i = 1; i <= 10; ++i ) {sb.append( " " );sb.append( i ); }sb.deleteCharAt( 0 ); sb.insert( 0, "[" ); sb.replace( sb.length() - 3, sb.length(), "]" );

盡管建議使用StringBuilder / StringBuffer來處理字符串,但在連接兩個(gè)或三個(gè)字符串的簡單情況下,它看起來可能會(huì)過分殺傷,因此可以使用常規(guī)+運(yùn)算符代替,例如:

String userId = "user:" + new Random().nextInt( 100 );

通常,直接連接的更好替代方法是使用字符串格式設(shè)置,并且Java標(biāo)準(zhǔn)庫也通過提供靜態(tài)幫助器方法String.format來提供幫助。 它支持一組豐富的格式說明符,包括數(shù)字,字符,日期/時(shí)間等(有關(guān)完整參考,請?jiān)L問官方文檔 )。 讓我們通過示例來探索格式化的力量:

String.format( "%04d", 1 ); -> 0001 String.format( "%.2f", 12.324234d ); -> 12.32 String.format( "%tR", new Date() ); -> 21:11 String.format( "%tF", new Date() ); -> 2014-11-11 String.format( "%d%%", 12 ); -> 12%

String.format方法提供了一種干凈方便的方法來從不同的數(shù)據(jù)類型構(gòu)造字符串。 值得一提的是,某些現(xiàn)代Java IDE能夠根據(jù)傳遞給String.format方法的參數(shù)來分析格式規(guī)范,并在檢測到任何不匹配時(shí)向開發(fā)人員發(fā)出警告。

8.命名約定

Java作為一種語言并沒有強(qiáng)迫開發(fā)人員嚴(yán)格遵守任何命名約定,但是社區(qū)已經(jīng)開發(fā)了一套易于遵循的規(guī)則,這些規(guī)則使Java代碼在標(biāo)準(zhǔn)庫和所有其他Java項(xiàng)目中看起來都是一致的。

  • 軟件包名稱小寫形式輸入: org.junit , com.fasterxml.jackson , javax.json
  • 類,枚舉,接口注釋名稱大寫字母鍵入: StringBuilder , Runnable , @Override
  • 方法字段名 ( static final除外)以駝峰形式輸入: isEmpty , format , addAll
  • 靜態(tài)最終字段枚舉常量名稱大寫字母鍵入, 并用下劃線 “ _” MIN_RADIX : LOG , MIN_RADIX , INSTANCE
  • 局部變量方法參數(shù)名稱駝峰式鍵入: str , newLength , minimumCapacity
  • 泛型類型參數(shù)名稱通常以大寫形式表示為一個(gè)字符 : T , U , E

通過遵循這些簡單的約定,您正在編寫的代碼將與其他任何庫或框架看起來簡潔明了,并沒有區(qū)別,給人的印象是它是由同一人創(chuàng)作的(約定真正起作用的罕見情況之一)。

9.標(biāo)準(zhǔn)庫

無論您從事哪種Java項(xiàng)目,Java標(biāo)準(zhǔn)庫都是您最好的朋友。 是的,很難不同意它們有一些粗糙的邊緣和奇怪的設(shè)計(jì)決策,但是在99%的情況下,這是專家編寫的高質(zhì)量代碼。 值得學(xué)習(xí)。

每個(gè)Java版本都為現(xiàn)有庫帶來了許多新功能(可能會(huì)淘汰舊功能),并增加了許多新庫。 Java 5帶來了在java.util.concurrent包下協(xié)調(diào)的新并發(fā)庫。 Java 6提供了(很少javax.script知道)腳本支持( javax.script包)和Java編譯器API(在javax.tools包下)。 Java 7對java.util.concurrent了很多改進(jìn),在java.nio.file包下引入了新的I / O庫,并通過java.lang.invoke包支持了動(dòng)態(tài)語言。 最后,Java 8提供了一個(gè)期待已久的日期/時(shí)間API,該API在java.time程序包下java.time 。

Java作為平臺正在不斷發(fā)展,緊跟這一發(fā)展非常重要。 每當(dāng)您打算將第三方庫或框架引入您的項(xiàng)目時(shí),請確保Java標(biāo)準(zhǔn)庫中沒有所需的功能(實(shí)際上,有許多專門的高性能算法實(shí)現(xiàn)要優(yōu)于標(biāo)準(zhǔn)庫中的實(shí)現(xiàn))但在大多數(shù)情況下,您實(shí)際上并不需要它們)。

10.不變性

不變性遍及本教程,在這一部分中,它提醒您:請認(rèn)真對待不變性。 如果您正在設(shè)計(jì)的類或正在實(shí)現(xiàn)的方法可以提供不變性保證,那么它幾乎可以在任何地方使用,而不必?fù)?dān)心并發(fā)修改。 這將使您作為開發(fā)人員的生活更加輕松(也希望與您的隊(duì)友一起生活)。

11.測試

測試驅(qū)動(dòng)開發(fā)(TDD)做法在Java社區(qū)中非常流行,從而提高了所編寫代碼的質(zhì)量標(biāo)準(zhǔn)。 與所有這些考慮TDD在桌子上帶來的好處,這是可悲的,觀察到Java標(biāo)準(zhǔn)庫不包含任何測試框架或棚架今天的。

盡管如此,測試已成為現(xiàn)代Java開發(fā)中必不可少的部分,在本節(jié)中,我們將介紹使用出色的JUnit框架的一些基礎(chǔ)知識。 本質(zhì)上,在JUnit中 ,每個(gè)測試都是關(guān)于期望對象狀態(tài)或行為的一組斷言。

編寫出色測試的秘訣在于使它們簡短而簡單,一次只測試一件事。 作為練習(xí),讓我們編寫一組測試來驗(yàn)證“ 字符串 ”部分中的String.format函數(shù)是否返回了所需的結(jié)果。

package com.javacodegeeks.advanced.generic;import static org.junit.Assert.assertThat; import static org.hamcrest.CoreMatchers.equalTo;import org.junit.Test;public class StringFormatTestCase {@Testpublic void testNumberFormattingWithLeadingZeros() {final String formatted = String.format( "%04d", 1 );assertThat( formatted, equalTo( "0001" ) );}@Testpublic void testDoubleFormattingWithTwoDecimalPoints() {final String formatted = String.format( "%.2f", 12.324234d );assertThat( formatted, equalTo( "12.32" ) );} }

測試看起來非常易讀,其執(zhí)行是實(shí)例化。 如今,普通的Java項(xiàng)目包含數(shù)百個(gè)測試用例,為開發(fā)人員提供了有關(guān)正在開發(fā)的回歸或功能的快速反饋。

12.接下來是什么

本教程的這一部分完成了與Java編程實(shí)踐和指南相關(guān)的一系列討論。 在下一部分中,我們將通過探索Java異常的世界,其類型,使用方式和使用時(shí)間來返回到語言功能。

13.下載源代碼

這是關(guān)于“通用編程準(zhǔn)則”的課程,是“高級Java”課程的課程。 您可以在此處下載源代碼: AdvancedJavaPart7

翻譯自: https://www.javacodegeeks.com/2015/09/general-programming-guidelines.html

總結(jié)

以上是生活随笔為你收集整理的通用编程准则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。