java中重载和重写的区别详解?
1、首先是重载,重载就是在同一个类当中有多个名称相同方法,但各个相同方法的参数列表不同(无关返回值类型)。如下,在test3中三个方法名相同的add方法,第一个是两个int类型的书相加,第二个是三个int相加,第三个是两个float相加,他们的参数个数不同或类型不同就构成了重载。
2、重写则发生在不同的类当中,并且两者要有继承关系,重写是方法名字和参数的列表是要完全一致的,重写的意义在于父类的方法已经不能满足时,子类重写为自己需要的。如下,在父类Test3中num方法是想做两数的加法运算,而在子类Test4中我想做两数的减法运算,则继承的num方法不能满足,则重写为test4中的num方法进行减法运算。
java方法的重载的问题,返回类型必须相同吗?
方法的重载没有明确规定要同样的返回类型,可以试试看就知道了重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准
java项目如何创建包以及调试运行?
1、首先我们在桌面找到eclipse,双击将其打开。
2、在这里我已经创建了一个名为helloworld的java项目,但其下还为创建任何的包以及文件。下边我们开始创建第一个包路径。一般来说java代码都是写在src文件夹下,选中src右击鼠标创建一个包路径,选择new然后选择package。
3、在创建包路径界面,我们需要给我们的包进行命名。命名规则一般为域名.公司名.工程名.模块名……假如需要建立一个百度地图的应用包ditu.baidu.com,那我们的包名即为com.baidu.ditu。命名结束后点击Finish。
4、我们可以看到包的路径已经建好了。
5、接下来我们需要在包里面建立java文件,右击包名称,选择new-〉class。
6、java文件的命名规则为单词首字母大写,如果多个单词则每个首字母都需要大写。在新建java文件页面,我们看到下方有个设置项为public static void main(string args),这个选项是对该java类自动创建一个主函数。我们将其选中,并点击Finish。
7、可以看到在新创建的这个类中已经自动创建了一个主函数,以及类的包路径都已经自动的引入。在左侧试图中可以查看到新创建的java类。
8、那eclipse中如何对java工程进行调试呢?这里我们通过一个最简单也是初学者入门就接触的一个实例叫“hell oworld!”。我们在主程序中添加一行代码,也是最常见的输出命令。改行代码的意思为当程序运行时将“测试输出”输出到控制台。
9、接下来我们再java类中右击鼠标,选择run as-〉java application。
10、接下来我们可以看到“测试输出!”的字样在控制台打印出来了。这样一个完整的java调试就结束了。
为什么Java不支持运算符重载?
Java不支持运算符重载 = 小白也能学编程
Java之所以不支持运算符重载,并不是如下原因:
- 会使JVM变得复杂、性能下降:君不见C++内置运算符重载的能力?C++的性能在任何时代秒杀Java相信没有争议。
- 便于静态分析、工具化等:一叶障目、不见泰山。运算符重载只是一种动态特性,动态语言的形式化静态分析方法已经有成熟的方法论。
- Java是面向对象语言:Ruby是比Java更彻底的面向对象的语言,然而它对运算符重载的支持非常优秀,在Ruby中一切都是对象,几乎一切都可以override。
不支持运算符重载的根本原因,是源自James Gosling设计Java的初衷:那就是要让Java的学习门槛足够低,这样才能让这个编程语言被更多的人使用,从而拥有最大的市场占有率。
Java诞生之前, 基本上是C/C++的天下。光C语言的一个指针,就吓退了多少莘莘学子?C++引入更多的动态特性:多态、多重继承、函数重载、函数重写、运算符重载、泛型……这更不知道让多少人望而却步!
正是在那样的大环境下,James Gosling才萌生了“开发一个小白都能上手”的编程语言的念头。
运算符重载的底层思想并不是面向对象
运算符重载的底层逻辑来自函数式编程。它的祖师爷是Lisp,一个“从来被模仿、从未被超越”的神级语言。
可以负责任地讲,如今流行的Python、Javascript、Typescript、Go、Ruby、Haskell、Scala、Groovy等,在动态高级特性上都是在不断模仿60多年前的Lisp。包括Java从诞生起就在鼓吹的垃圾回收等优点,全部都是“偷师”Lisp。有兴趣的小伙伴可以自行下载Lisp的发明者——John McCarthy老爷爷1960年发表的GC论文。
函数式语言的核心思想其实是数学。
说得更白话一点:通过数学表达式描述问题,而不是人肉模拟解答过程。问题描述完了,也就解决了——运行时处理执行细节。
说得更学院派一点:通过无状态的函数加以其他优化特性,将这些函数组件进行拼接。
看到这里,估计有不少人要来拍砖:运算符重载看起来那么复杂,明明可以定义方法或者函数来解决,除了装逼格,没有实用价值。
笔者这里回应一下:数学本来就不是普通大众擅长的,数学的目的就是用最简洁的方式来解决最复杂的问题。所以函数式语言从诞生之初,就没有想过要芸芸众生。它追求的是大道至简。
这里来看一个例子:计算一组数据(假设放在一个一维数组中)的标准差。
如果不采用函数式编程,采用通常的面向过程或者面向对象的编程范式,那么只能:
第一步,先通过循环体(for/foreach/while等),挨个遍历求出平均值mean;
第二步,再来一次循环,挨个求与mean的差值并平方,然后逐个累加得到平方合sumOfSquares;
第三步,对sumOfSquares调用平方根函数,求出最终值standardDeviation。
下面我们来进化一点:
有基本函数式编程概念的小伙伴可能会写出如下的简化范式(这里以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))
但是真正的函数式编程高手是会这样写的:
第一步:写一个通用的数学意义上的复合函数(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
第二步:把计算标准差所需要的各个元素的数学表达列示好:
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
第三步:像写标准差的数学表达式一样,一步到位:
standardDeviation = Math.sqrt((sum<=square*deviation|a)/(a.size-1))
总结
Java之所以流行,并不是因为其语言设计得最优秀,相反地,在很多地方——比如泛型、Lambda、完全面向对象等设计上都存在不足。它的成功在于:扬长避短,把所有牛X的高级语言特性在一开始全部都抛弃,留一个最小核,然后通过营销,大规模地培养本语言阵营的程序员,建立各种各样的“轮子”,成就了巨无霸的生态;在站稳格局之后,慢慢地再逐步添加回来一些以前抛弃的其他语言的优秀特性——这是一种比较实用的策略,但是带来的恶果就是:历史包袱比较重,导致新特性很多时候是“半残”的。
回到运算符重载本身,对于高手,可以利用该特性写出极具“魔性”、接近数学语言的代码,这样的代码可以体现“极简之美”——但是,一个不利影响就是:数学不好的小伙伴,不容易看得懂,也很难体会其中蕴含的“数学之美”。

