《编程导论(Java)·3.1.2 方法》之 副作用

4. 副作用

在一些语言如Pascal中,子程序被分成两种:函数和过程。虽然Java没有强制性地要求将方法区分为命令和函数,然而这种区别对于良好地设计程序有很大的帮助[1]

首先说明一个概念:副作用(side effect)。副作用一般是针对操作(表达式)而言的,一个操作/表达式有“副作用”是指在对该表达式求值时,会改变程序的一个或多个数据,以致再次对该表达式求值时,可能会得出不同的结果。事实上,Java的4种表达式语句如赋值、自增自减、方法调用、对象创建都可能带来副作用。

这里讨论方法的副作用。一个方法的执行,如果在返回一个值之外还导致某些外部“状态”发生变化,则称该方法产生了副作用。这里所谓“状态”发生变化,可以是实例域或静态变量被修改、方法的实参被修改(Java 中不会出现这种情况。但是实参为引用时,其指向的对象可能被修改从而产生副作用)、将数据传递给显示器、打印机或存入文件中等等。

当然,方法内部的表达式也会出现副作用,如果它仅仅影响局部变量而不影响外部状态,则方法没有副作用。基于副作用概念,定义两个术语:

2       有返回值而且没有副作用的方法称为函数(function)。

2       没有返回值的方法必然有副作用,除非它的方法体是空的或者方法没有意义。所以,没有返回值的方法、有返回值但有副作用的方法称为过程(procedure)或命令(command)。简言之,有副作用的方法称为过程。

如此严格地定义出函数的概念,是因为函数使得系统的状态稳定,函数的行为容易预测。更进一步,如果函数是纯粹的函数(pure function,纯函数)——它的输出值依靠和仅仅依靠其输入、对于相同的输入总是返回相同的值,(由于纯函数的纯粹和无副作用)对纯函数的调用就能够被一个值取代(或者说,将方法视为一个值),这就是函数式编程语言中著名的引用透明(referentialtransparency)特性。

例程 3?3纯函数

package semantics.method;
public class SideEffectsDemo{
    private static int x = 0;
    //纯函数(pure function)
    public static int times(int i,int j){
        return  i * j ;
    }
    //非纯函数
    public static int m(int i,int j){
        return  i * j +x;
    }
}

函数式编程语言(functionalprogramming language)如Haskell[2]中,尤其强调避免副作用。当然了,完全不产生副作用的编程语言是没有任何用处的,例如数据显示和存入文件等等副作用都是必要的,强调无副作用的Haskell 语言,使用一种技术将它们分离出来,用一种安全的方式单独执行。

Java是命令式面向对象语言,但能够借鉴函数式语言的优点,也期待Java中加入重要的函数式语言的特性。随着Java 8的发布,引入的λ表达式(Lambda Expressions)表明,Java开始大力引入函数式语言的特性。(They enable you to treat functionality as a method argument, or code as data.)


练习3-5:何谓方法、函数、纯函数? 解释副作用的含义。


练习3-6:实现方法,求f(x)=x^3 + 3x+1。注:书中x^3表示x*x*x.


[1] 参考RichardMitchell,Jim Mackim著,孟岩译,Design by Contract原则与实践。

[2] http://www.haskell.org/learning.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-15 10:30:49

《编程导论(Java)·3.1.2 方法》之 副作用的相关文章

《编程导论(Java)·2.1.3改写(override)》

<编程导论(Java)·2.1.3改写(override)>,收集override内容. 方法改写(method overriding)是指对于父类定义的一个实例方法,同意子类提供自己的实现的一种语言特性.子类的实现将改写(override)或代替(replace)父类中的实现. 改写成功必须"同一时候"满足下列条件. 两者的方法签名全然同样. 方法签名(signature)指一个方法的名字和形參列表.a method's signature is its name and

《编程导论(Java)&amp;#183;3.3.2 按值传递语义》

不要受<Java编程思想>的影响,计算机科学中的术语--按引用传递(pass-by-reference).不要搞成自说自话的个人用语. 这些术语也不是专门针对Java的,你不应该从某一本Java书上学习 不可以用于C.C++或Fortran语言的 特殊的"按引用传递". 验证按值传递很easy.在方法体中使用一个赋值语句,将形參作为左值. 按值传递时,对形參的赋值,不会影响实參.也就是说.那个赋值语句不会有不论什么副作用. 对于foo(A a),注意方法体中你要玩的是 a=

《编程导论(Java)&#183;1.1.2 颠倒的世界(柏拉图法则)》

<编程导论(Java)>将Plato法则.Liskov原则和Parnas原则作为面向对象编程范式的三大基石. 面向对象范式的第一原则,yqj2065称之为柏拉图法则,它是对象技术的观念范式和心理范式的根源,对象技术是通过颠倒的理念世界而模拟唯物的真实世界. ★柏拉图法则:类的世界独立存在,对象世界由类创建而来. 虽然有人认为,这一原则非常自然,没有必要提出和强调,但是,我发现,对这一原则的理解和接纳程度,决定了你对面向对象的领悟程度. 提出的依据: 1.对象(object)是一个具有浓郁的哲学

《编程导论(Java)&amp;#183;3.2.4 循环语句》

本文全然复制<编程导论(Java)·3.2.4 循环语句>的内容.除[]中的说明文字.请阅读和比較其它编程教材. 我知道.假设我是一个刚開始学习的人,<编程导论(Java)>非常不适合自学.建议同学们阅读时,一定选择一本其它的书同一时候看,或上网. ,由于太一般或简单的内容.或我不想留在书中占用篇幅的东西,都省略了. 毕竟,网络上相关的一般描写叙述的内容.大把大把. 卓别林在<摩登时代>中.说明流水线上的工人在高强度下重复运行同一个动作是多么令人郁闷.然而循环/迭代(l

《编程导论(Java)&#183;1.4.1 范式》

这个楼主,是我的学生么?2013年写的! 嗯,"编程范式也许是学习任何一门编程语言时要理解的最重要的术语".这句话早在2005年出版<Java程序设计>(宋中山,严千钧编著,清华大学出版社)中写过.但是, "托马斯.库恩提出"科学的革命"的范式论之后,Robert Floyd在1979年图灵奖的颁奖演说中使用了编程范式一词.编程范式一般包括三个方面,以OOP为例:.....",好像在<编程导论(Java)>出版之前,仅仅在

《编程导论(Java)&#183;3.2.4 循环语句》

本文完全复制<编程导论(Java)·3.2.4 循环语句>的内容,除[]中的说明文字.请阅读和比较其他编程教材. 我知道,如果我是一个初学者,<编程导论(Java)>很不适合自学.建议同学们阅读时,一定选择一本其他的书同时看,或上网.,因为太一般或简单的内容.或我不想留在书中占用篇幅的东西,都省略了.毕竟,网络上相关的一般描述的内容,大把大把. 卓别林在<摩登时代>中,说明流水线上的工人在高强度下反复执行同一个动作是多么令人郁闷.然而循环/迭代(loop/iterati

《编程导论(Java)&#183;2.2.3 变量的声明模型》

PL4 声明模型(绑定.可见性.作用域和生命期) 1. 变量的含义 在编程语言的教学中,yqj2065经常困惑:是否应该使用比喻--例如将变量比喻成数学中的变量概念.不知道从哪位老先生开始,有这样的说法:"不同于常量,变量的值是可以改变的".如果你是我的学生,也这样说,嗯,你过来,我保证不打死你. 在汇编语言中,程序员就开始使用变量例如AX.BX以表示操作数的存放地址,而该地址中保存实际的值.变量(variable)表示一个存储场所,是源代码中保存值的符号化地址. 请记住变量和值的区别

《编程导论(Java)&amp;#183;1.4.1 范式》

这个楼主,是我的学生么?2013年写的! 嗯."编程范式或许是学习不论什么一门编程语言时要理解的最重要的术语".这句话早在2005年出版<Java程序设计>(宋中山,严千钧编著,清华大学出版社)中写过. 可是, "托马斯.库恩提出"科学的革命"的范式论之后,Robert Floyd在1979年图灵奖的颁奖演说中使用了编程范式一词.编程范式一般包含三个方面,以OOP为例:.....",好像在<编程导论(Java)>出版之前.

《编程导论(Java)&amp;#183;2.1.2 啊,我看到了多态》-什么是多态(polymorphism)

1.不明觉厉 很多人学习多态时,会认为. 之所以不明觉厉,由于多态的定义:事物存在的多种表现形态:而后,有人将重载(overload).改写(override).多态变量和泛型归结于同一个术语"多态"之下.比如:Polymorphism (computer science) yqj2065觉得:[(前言 page VII)好像孔乙己说"多态这个字有4种写法"一样,除了凸显多态这一术语比較多态外,并没有理论意义和教学意义,因而本书使用了一个标题--"2.1.