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

本节初步介绍类的细节。

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——做练习为主。

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

时间: 2024-10-30 07:04:56

《编程导论(Java)·1.2类》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: