色婷婷狠狠18禁久久YY,CHINESE性内射高清国产,国产女人18毛片水真多1,国产AV在线观看

為什么Java不支持運算符重載?

錢多多2年前27瀏覽0評論

Java不支持運算符重載 = 小白也能學編程

Java之所以不支持運算符重載,并不是如下原因:

  1. 會使JVM變得復雜、性能下降:君不見C++內(nèi)置運算符重載的能力?C++的性能在任何時代秒殺Java相信沒有爭議。
  2. 便于靜態(tài)分析、工具化等:一葉障目、不見泰山。運算符重載只是一種動態(tài)特性,動態(tài)語言的形式化靜態(tài)分析方法已經(jīng)有成熟的方法論。
  3. Java是面向?qū)ο笳Z言:Ruby是比Java更徹底的面向?qū)ο蟮恼Z言,然而它對運算符重載的支持非常優(yōu)秀,在Ruby中一切都是對象,幾乎一切都可以override。

不支持運算符重載的根本原因,是源自James Gosling設(shè)計Java的初衷:那就是要讓Java的學習門檻足夠低,這樣才能讓這個編程語言被更多的人使用,從而擁有最大的市場占有率。

Java誕生之前, 基本上是C/C++的天下。光C語言的一個指針,就嚇退了多少莘莘學子?C++引入更多的動態(tài)特性:多態(tài)、多重繼承、函數(shù)重載、函數(shù)重寫、運算符重載、泛型……這更不知道讓多少人望而卻步!

正是在那樣的大環(huán)境下,James Gosling才萌生了“開發(fā)一個小白都能上手”的編程語言的念頭。

運算符重載的底層思想并不是面向?qū)ο?/h3>

運算符重載的底層邏輯來自函數(shù)式編程。它的祖師爺是Lisp,一個“從來被模仿、從未被超越”的神級語言。

可以負責任地講,如今流行的Python、Javascript、Typescript、Go、Ruby、Haskell、Scala、Groovy等,在動態(tài)高級特性上都是在不斷模仿60多年前的Lisp。包括Java從誕生起就在鼓吹的垃圾回收等優(yōu)點,全部都是“偷師”Lisp。有興趣的小伙伴可以自行下載Lisp的發(fā)明者——John McCarthy老爺爺1960年發(fā)表的GC論文。

函數(shù)式語言的核心思想其實是數(shù)學。

說得更白話一點:通過數(shù)學表達式描述問題,而不是人肉模擬解答過程。問題描述完了,也就解決了——運行時處理執(zhí)行細節(jié)。

說得更學院派一點:通過無狀態(tài)的函數(shù)加以其他優(yōu)化特性,將這些函數(shù)組件進行拼接。

看到這里,估計有不少人要來拍磚:運算符重載看起來那么復雜,明明可以定義方法或者函數(shù)來解決,除了裝逼格,沒有實用價值。

筆者這里回應一下:數(shù)學本來就不是普通大眾擅長的,數(shù)學的目的就是用最簡潔的方式來解決最復雜的問題。所以函數(shù)式語言從誕生之初,就沒有想過要蕓蕓眾生。它追求的是大道至簡。

這里來看一個例子:計算一組數(shù)據(jù)(假設(shè)放在一個一維數(shù)組中)的標準差。

如果不采用函數(shù)式編程,采用通常的面向過程或者面向?qū)ο蟮木幊谭妒剑敲粗荒埽?/p>

第一步,先通過循環(huán)體(for/foreach/while等),挨個遍歷求出平均值mean;

第二步,再來一次循環(huán),挨個求與mean的差值并平方,然后逐個累加得到平方合sumOfSquares;

第三步,對sumOfSquares調(diào)用平方根函數(shù),求出最終值standardDeviation。

下面我們來進化一點:

有基本函數(shù)式編程概念的小伙伴可能會寫出如下的簡化范式(這里以Ruby為例):

mean = a.inject {|x,y| x+y } / a.size

sumOfSquares = a.map{|x| (x-mean)**2 }.inject{|x,y| x+y }

standardDeviation = Math.sqrt(sumOfSquares/(a.size-1))

但是真正的函數(shù)式編程高手是會這樣寫的:

第一步:寫一個通用的數(shù)學意義上的復合函數(shù)(f(g(x)) = f*g(x))的表達:

module Functional

def apply(enum)

enum.map &self

end

alias | apply

def reduce(enum)

enum.inject &self

end

alias <= reduce

def compose(f)

if self.respond_to?(:arity) && self.arity == 1

lambda {|*args| self[f[*args]] }

else

lambda {|*args| self[*f[*args]] }

end

end

alias * compose

end

第二步:把計算標準差所需要的各個元素的數(shù)學表達列示好:

sum = lambda {|x,y| x+y } # A function to add two numbers

mean = (sum<=a)/a.size # Or sum.reduce(a) or a.inject(&sum)

deviation = lambda {|x| x-mean } # Function to compute difference from mean

square = lambda {|x| x*x } # Function to square a number

第三步:像寫標準差的數(shù)學表達式一樣,一步到位:

standardDeviation = Math.sqrt((sum<=square*deviation|a)/(a.size-1))

總結(jié)

Java之所以流行,并不是因為其語言設(shè)計得最優(yōu)秀,相反地,在很多地方——比如泛型、Lambda、完全面向?qū)ο蟮仍O(shè)計上都存在不足。它的成功在于:揚長避短,把所有牛X的高級語言特性在一開始全部都拋棄,留一個最小核,然后通過營銷,大規(guī)模地培養(yǎng)本語言陣營的程序員,建立各種各樣的“輪子”,成就了巨無霸的生態(tài);在站穩(wěn)格局之后,慢慢地再逐步添加回來一些以前拋棄的其他語言的優(yōu)秀特性——這是一種比較實用的策略,但是帶來的惡果就是:歷史包袱比較重,導致新特性很多時候是“半殘”的。

回到運算符重載本身,對于高手,可以利用該特性寫出極具“魔性”、接近數(shù)學語言的代碼,這樣的代碼可以體現(xiàn)“極簡之美”——但是,一個不利影響就是:數(shù)學不好的小伙伴,不容易看得懂,也很難體會其中蘊含的“數(shù)學之美”。