《编程导论(Java)·1.2类》

来源:互联网 发布:王婉茹 黄翔 知乎 编辑:程序博客网 时间:2024/05/18 22:15

本节初步介绍类的细节。

1.2.1 类体结构

首先,按照我的对象优先教学策略,先介绍类的知识而非先讲控制结构。所以,早在第一章第二节,就直接给出一个完整的Dog例程例程1-1。而1.2.1类体结构围绕例程,总体介绍状态、行为和身份标识(引用)。很多东西,不方便现在解释的,就不解释。同学们先在BlueJ中操作它

★Learning by doing.

package zoo;/** * class Dog 描述了人类忠实的朋友狗。类声明。 * @author yqj2065  * @ version 0.1 */public class Dog {  // 类头、类声明    private String name = "baby" ; //字符串 狗名,默认时叫baby。private表示私有的访问权限    private boolean sex;  //布尔/逻辑数据 性别。性别只有两种,必居其一。true代表雄性。    private int age = 0;    //整数(integer) 年龄,默认为0岁。        /* setter and getter*/    /**     * 设置狗的名字.     * @param n 狗的名字(字符串)。     * @throws 以后再考虑参数检查的事情,现在搞不定。不得用总统的名字。     */    public void setName(String n) {        name = n;    }//设置狗的名字。void表示返回值是空的、不需要的。    String  getName() {return name;} // return/返回狗的名字      /**@param  isMale  true代表雄性 */    void   setSex(boolean isMale) {  sex = isMale; }    int    getAge() {return age;}        /**摇尾巴行为。输出字符串Hello World */    void wagTail()  {  System.out.println("Hello World");     }    /**狗会做简单的加法*/    int add(int i ,int j){return i+j;}    }

1.对象的状态(state)是对象的所有属性值的集合。每一个对象拥有自己的内存空间保存自己的状态,即保存名字、年龄、性别等等属性值。

2.客观对象的“行为”是一种概括的说法。如Dog有摇尾巴、咆哮等动作、有(被人)设定其年龄或询问其年龄的活动;抽象的对象如圆,有计算其面积和周长的公式、计算过程或算法。源代码将客体行为建模为可被执行的代码块,Java中称为方法(method) ,针对某个属性进行读写的各个方法,俗称settergetter

3.对象的身份标识(或同一性),在本教程的讨论范围内,完全按照它在内存中占据的位置(通过引用)判断。即两个对象占据相同的内存位置,它们就是“同一个”对象;否则,即使它们的状态完全一样,仅仅是“相等的”。


练习1-11.使用BlueJ IDE,掌握附录A.1的内容:编辑和编译源代码。

练习1-12.:熟练掌握附录A.2与类、对象交互:在BlueJ中创建一个Dog对象,并调用其wagTail()、getName() 和setName(String)方法。说明如何查看上面的3个方法调用后的效果。 提醒:字符串文字作为参数时注意用双引号包围它。

练习1-17:什么是对象的同一性?


4.类的结构综述

类作为对象的模板,最基本的组成部分是对象的状态和行为,还包括内部类、内部接口(请参见[9.4嵌套类型])。Java中,它们被称为类的成员

类还有一个重要工作,就是为更方便地创建自己的对象做好准备。因而在类定义时,源代码中经常安放了这种目的的代码块——构造器、初始化块。这些代码块不用于描述对象特征,故它们不被视为类的成员。就像旁听生一样,虽然在class中,却不是班级的一分子。有时称其为类的非成员

因此,普通类的结构通常为:

//package xxx;//import xxx;/**类简介 */public class Xxxx{    <域声明>    <构造器,初始化块>    <方法定义>    <内部类、内部接口>}

1.2.2 空白与注释

下面围绕例程1-1 zoo.Dog.java,说明源代码的构成——注释、空白五种Java词法元素:标识符、关键字、文字、操作符和分隔符。同时请做一个游戏,把Dog代码复制到zoo. Dog4Fun中,逐一删除已经介绍的部分。

空白包括空格、制表符(Tab)和换行符。

*单词和单词之间如private String name,需要使用一个空格进行间隔(它是一个分隔符)

*制表符——有规律的缩进,主要的作用是使代码的结构清晰。

*源代码是纯文本文件,每一行以换行符结束。换行符有ASCII码中的CR (Carriage return, '\r', 0x0D, 13)和LF (Line feed, '\n', 0x0A, 10)。(读取一个文件时,要注意换行符的处理。)

注释,在书中占用的篇幅接近“类的结构”,特别是列举了常用的JavaDoc的块标记。不管如何强调都不过分,

★程序必须是写给人读的,仅仅偶尔让机器执行——Abelson and Sussman

★Any fool can write code that a computer can understand. Good programmers write code that humans can understand——Martin Fowler

1.2.3 五种Java元素

Java词法元素(token、语言符号)是Java编译器能够识别的最小单元,包括如下五种:标识符、关键字、文字、操作符和分隔符

例程 1-2 不同种类的标识符相互独立

package semantics;public class YQJ {   YQJ YQJ(YQJ YQJ){     YQJ:        for(; ;){          if(YQJ.YQJ(YQJ)==YQJ)             break YQJ;     }     return YQJ;   }}
标识符的语法简单列举了一下。Java中的标识符、注释、字符文字、字符串文字可以使用Unicode,而关键字、操作符等其他Java元素则使用ASCII字符。

练习1-25. 定义一个方法,判断一个字符是否为标识符可用字符。请用各种字符(包括汉字)替换下面代码中的符号"★"。并证实2mail、room#是或不是合法的标识符。

                   chard='★';

                   booleanb1=Character.isJavaIdentifierStart(d);//是否合法的标识符首字符

                   booleanb2=Character.isJavaIdentifierPart(d);

                   System.out.println(b1 + " "+ b2);

可用字符的详细资料参考JDK Documentation中Character.isJavaIdentifierStart()等方法的文档。

(这是我的尝试,在这个阶段,学生能够完成练习1-25吗?)

练习1-30. 数值0、字母A、a的ASCII吗分别为____。(1)0、65、66 (2)48、65、97 (2)48、96、97。

2.关键字

abstract

assert

boolean

break

byte

case

catch

char

class

const

continue

default

do

double

else

enum

extends

final

finally

float

for

goto

if

implements

import

instanceof

int

interface

long

native

new

package

private

protected

public

return

short

static

strictfp

super

switch

synchronized

this

throw

throws

transient

try

void

volatile

while

 

 

 

 

false、 true和null理论上是文字,没有填入表1-1中。

3.文字

文字也称为常量值、字面值。

整数文字通常使用十进制数,也可以使用2、8或16进制数,数字之间可以加_以增强可读性;以零(0)开头的数为八进制数;以零b(0b或0B)开头的数是二进制数,以零x(0x或0X)开头的数是十六进制数。String文字是String对象的引用。

4.[3.2.2 操作符]将全面介绍操作符。

5.分隔符(separators)将程序不同部分分隔开来。如一个空格分割单词,逗号分割方法的参数,分号表示语句的结束(因为可以把多个语句放在一行)。剩下的就是{} ()。

练习1-35:编写程序typeSystem.primitive.Literal.java,验证各种文字的语法。(我发现我有极端轻视语法教学的倾向。)

1.2.4 语法、语意和约定

语法(syntax、句法;syntactic grammar、语法规则) 严格规定了一系列词法元素如何组成句法正确的语句。它是编写程序时必须遵循的规则。编译器能够按照编程语言的token和一套语法规则,判定程序的诸多元素是否正确的组合在一起。

对新程序员而言,语法错误非常容易出现。

语意(或语义,semantics)通常指语言结构所表达的含义,或者说一个语句执行时,计算机将做些什么。绝大多数情况下,高级语言采用自然语言和数学的习惯用法来表达语意,因而可以不太关注语意,通常将语法和语意合为一体来讨论。如果借助直觉能够理解的语言结构越多,说明该语言越友好。

通常语言结构的语意是明确的,即每一条语句有且只有一种解释。然而,有时候一门语言对某种结构没有定义其语意,如[3.2.2 操作符]中表达式的求值顺序,在C语言中没有定义其语意。同一个合法的语句,不同的程序员表达的意思可能不同,不同的执行环境运行后得到的结果可能不同。另外,语言结构所表达的不同于人们想当然的语意,就要注意语意的学习。如

       for(int x : list){

           x++;

        }

别指望它能够对int[]list = {1,3,5,7,9}的各元素加一,使数组元素变成{2,4,6,8,10}。


约定(convention)。语法是程序员“必须”遵守的规定,否则编译不通过。约定是“应该”遵守的,因为它是程序员社区的要求。约定如同现实生活中的公德约束——应该给老人、孕妇等让座。需要约定的基本原因,是为了程序员能够容易地读懂(他人的)代码。编程约定能够有效地增强代码的可读性、更好的维护性。如命名约定、排版约定等等。

1.2.5 案例:分数

程序并非都是Dog这样的语言教学例子,先看看一些实用性的而且简单的代码。

Fraction类中仅列举了加法功能,其他功能代码如减法、乘除在学完[3.2实现]后请自行实现。为了得到规格化形式的分数,需要一个计算a,b的最大公约数的功能模块gcd(int,int),其实现采用了欧几里德(Euclid)算法/辗转相除法,参见[10.1.1 算法]。

package tips;public class Fraction{    private  int num; //分子numerator    private  int den = 1; //分母denominator        public int getNum(){return num;}public int getDen(){return den;}    public Fraction(){this(0);}    /** N/1 形式的分数*/    public Fraction(int N){        num  = N;    }    /**创建一个分数等于 N/D     * @param N   分子numerator,     * @param  D   分母denominator,非0的int值。 */    public Fraction(int N , int D){        int n =  N >= 0 ? N: -N ;        int d =  D >= 0? D: -D ;        int g =  gcd (n ,d); // 规格化        this.num = (( N>= 0) == ( D>= 0))? (n/g):( - n/g);        this.den = d/g;    }     /**将一个分数相加到本对象身上*/      public void add(Fraction f){         num= num*f.den +den*f.num;         den = den *f.den;         int g = gcd(num,den);         num /= g;         den /= g;    }        /**计算a,b的最大公约数greatest common divisor */    public final int gcd(int a,int b){         while(b != 0){            int tep=a % b;            a = b;            b = tep ;        }        return a>=0?a:-a;            }    /**改写Object的toString() */    @Override public String toString(){        return (den == 1 )? (""+getNum()):(getNum()+"/"+getDen());    } }

本节共10页,建议教学课时1h,课下自学4h——做练习为主。



0 0