盡管過去我做過很多C / C ++,但自2001年以來我一直在做Java,所以我實際上忘記了很多我所知道的東西,此外,Objective-C還是不太像C ++。 結果是,您覺得自己在異國他鄉被洗劫一空,無法說該語言,并且武裝著曬黑和詞典。
在學習所有這些新知識時,我意識到Java是一種非常好的語言,其原因首先是因為您不必考慮內存分配和釋放,您可以繼續編寫應用程序。 在用Objective-C編寫iOS應用程序時,您既要為對象分配內存,然后又要清理,然后將對象的內存返回給空閑池。 這似乎是21世紀第二個十年的老派。 此外,在為對象分配內存后,您必須跟蹤對該對象的引用數量-一種稱為引用計數的做法,這是我在前身為C ++程序員的過程中首次遇到的問題。 這里的基本思想是,每次創建對對象的新引用時,都將增加引用計數器,當完成對象引用后,您將減小其引用計數器。
當計數器達到零時,系統將內存釋放回空閑池。 在Objective-C中,減少引用計數的功能稱為release ; 因此,如果Java具有引用計數,并且例如,如果我想讓AddressService查找我的地址,則需要執行以下操作:
// create an object and set the reference count to 1AddressService addressService = new AddressService(); // Use the objectAddress address = addressService.findAddress(id);// pass it to a methodmodel.addAttribute("address", address);// free the memory addressService.release();
那是簡單的場景,但是如果某個方法或其他方法將對象引用作為方法參數傳遞給您,會發生什么情況? 在那種情況下,您必須決定如何堅持下去,似乎有兩種方法可以做到這一點。 第一個是復制對象,第二個是增加其引用計數。 制作副本可能是最安全的主意,但會占用更多內存并會變慢,而增加引用計數很快,但不如程序的其他部分那么安全,可能會使引用計數錯誤并使計數減少太多次,這意味著您已經引用了一些可能已釋放的內存,并且當您嘗試訪問釋放的對象時,程序將崩潰……。 同樣,如果Java具有引用計數,那么Spring Controller請求處理程序方法將如下所示:
@RequestMapping(value = "/find", method = RequestMethod.GET)public String findAddress(@RequestParam("id") int id, Model model) {// increment the reference count - 'retain' is the Objective-C method for doing this.model.retain(); // create a new string object - with reference count of oneString msg = new String().withFormat("Processing an address page request for address with id: " + id);// pass the string to the loggerlogger.info(msg);// release the string's memorymsg.release();AddressService addressService = new AddressService();Address address = addressService.findAddress(id);model.addAttribute("address", address);addressService.release();// finished with the modelmodel.release();return "address-display";}
這里有兩點需要注意–首先,將處理程序方法傳遞給模型對象,因此我通過調用keep來增加引用計數,然后在方法結束后在模型上調用release來調用引用計數。 其次,即使在創建瑣碎的對象(例如傳遞給記錄器的消息字符串)時,您也必須應用引用計數規則并在完成后釋放內存。
下面的示例演示了增加引用計數的替代方法:制作自己的對象副本…
@RequestMapping(value = "/find", method = RequestMethod.GET)public String findAddress(@RequestParam("id") int id, Model model) {// increment the reference count - 'retain' is the Objective-C method for doing this.Model myModel = model.copy(); // As previous example// finished with the modelmyModel.release();return "address-display";}
這些示例只是微不足道的,有大量引用計數規則需要應用,如果弄錯了,Ka-Bam程序就會崩潰,弄錯了意味著您嘗試訪問已經釋放的內存,或者變慢由于忘記了釋放一些內存而導致的內存泄漏而死亡。 盡管我猜這里的關鍵是所有權 :如果您擁有一個對象,則增加它的引用計數,當您完成一個對象后,再減少它的引用計數。
上面的代碼只是寫了些雜文來說明這一點–它不會編譯。 該代碼實際上來自我在GitHub上的Address示例,在現實生活中看起來像這樣:
@RequestMapping(value = "/find", method = RequestMethod.GET)public String findAddress(@RequestParam("id") int id, Model model) {logger.info("Processing an address page request for address with id: " + id);Address address = addressService.findAddress(id);model.addAttribute("address", address);return "address-display";}
……體積更小,更容易理解。 最后一點,你們中的一些人會注意到,在引用計數示例中,我分配了(Objective-C字)新的AddressService –這是因為iOS編程與依賴注入或Spring框架完全不同,因此您將回到為自己創建對象。 (在Spring給家伙們的說明:“ Spring iOS” –對我來說聽起來像是個主意……)
那些知道的人將著重強調一個事實,即蘋果公司最近推出了一種稱為“自動引用計數”的東西。 雖然它不是垃圾收集,它的簡化,內部監督辦公室現在會自動追蹤您的指針引用的內存和可用內存為你當計數達到為零,這意味著東西,你不必費心調用保留和釋放方法。
另外,此博客也沒有貶低Objective-C –我非常喜歡Objective-C。 與Java相比,它的語法看起來相當晦澀難懂,但感覺很冗長,但是它迫使您在編程技術上要更有紀律,因此,如果像我一樣,您認為好的編程就取決于“思想的清晰性”,那么在編寫Objective-在C程序中,您必須更加清楚一點,而且我真的很喜歡。
我還猜想,很多讀者可能會提出許多原因,說明他們為什么認為Java是一種糟糕的語言,以及為什么他們喜歡的語言“做得更好”,無論它是什么,所以我很期待對您的評論...
最后,在iOS編程方面,我只是一個“新手”,因此,如果有任何iOS / Objective-C大師遇到此博客,請告訴我我錯了。
參考: Java不是一種文明語言嗎? 來自我們的JCG合作伙伴 ? 調試隊長博客的 Roger Hughes。
翻譯自: https://www.javacodegeeks.com/2012/02/isnt-java-civilised-language.html