标签:
本节初步介绍类的细节。
首先,按照我的对象优先教学策略,先介绍类的知识而非先讲控制结构。所以,早在第一章第二节,就直接给出一个完整的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) ,针对某个属性进行读写的各个方法,俗称setter和getter。
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-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)。(读取一个文件时,要注意换行符的处理。)
★程序必须是写给人读的,仅仅偶尔让机器执行——Abelson and Sussman
★Any fool can write code that a computer can understand. Good programmers write code that humans can understand——Martin Fowler
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 |
|
|
|
|
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,验证各种文字的语法。(我发现我有极端轻视语法教学的倾向。)
对新程序员而言,语法错误非常容易出现。
语意(或语义,semantics)通常指语言结构所表达的含义,或者说一个语句执行时,计算机将做些什么。绝大多数情况下,高级语言采用自然语言和数学的习惯用法来表达语意,因而可以不太关注语意,通常将语法和语意合为一体来讨论。如果借助直觉能够理解的语言结构越多,说明该语言越友好。
通常语言结构的语意是明确的,即每一条语句有且只有一种解释。然而,有时候一门语言对某种结构没有定义其语意,如[3.2.2 操作符]中表达式的求值顺序,在C语言中没有定义其语意。同一个合法的语句,不同的程序员表达的意思可能不同,不同的执行环境运行后得到的结果可能不同。另外,语言结构所表达的不同于人们想当然的语意,就要注意语意的学习。如
for(int x : list){
x++;
}
别指望它能够对int[]list = {1,3,5,7,9}的各元素加一,使数组元素变成{2,4,6,8,10}。
约定(convention)。语法是程序员“必须”遵守的规定,否则编译不通过。约定是“应该”遵守的,因为它是程序员社区的要求。约定如同现实生活中的公德约束——应该给老人、孕妇等让座。需要约定的基本原因,是为了程序员能够容易地读懂(他人的)代码。编程约定能够有效地增强代码的可读性、更好的维护性。如命名约定、排版约定等等。
程序并非都是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()); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/yqj2065/article/details/46705971