美文网首页
Java 学习记录二:OOP入门

Java 学习记录二:OOP入门

作者: 染微言 | 来源:发表于2017-05-02 16:45 被阅读51次

OOP基础

class是构造对象的模板或者说蓝图。由类构造的对象称为类的实例(instance)。
类封装是与对象有关的一个重要概念。从形式上来看,封装不过是将数据和行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。对象中的数据称为实例域,操纵数据的过程称为方法。对于每个特定的类实例,都有一组特定的实例域值。这些值的几何就是这个对象的当前状态。无论何时,只要想对象发送一个消息,它的状态就有可能发生改变。
实现封装的关键在于,绝对不能让类中的方法直接地访问其他类的实例域。程序仅仅通过对象的方法与对象数据进行交互。封装给对象赋予了黑盒特征,这是提高重用性和可靠性的关键。这意味着一个类可以全面地改变存储数据的方式,只要仍旧使用同样的方法操作数据,其他的对象就不会知道或介意所发生的变化。
OOP的另一个原则会让用户自定义Java类变得轻而易举:可以通过扩展一个类来建立一个新的类。
扩展一个已有的类时,新类就会具有所扩展的类的全部方法和属性。在新类中,只需要提供适用于这个新类的新方法和数据域就可以了。通过扩展一个类来建立新的类的过程称为继承。
传统的过程化程序设计,必须从顶部的main函数开始编写程序。在OOP程序设计时没有所谓的顶部,方法是:首先从设计类开始,然后再往每个类中添加方法

对象

对象有三个主要特性:

  1. 对象的行为——可以对对象施加那些操作,或者哪些方法。
  2. 对象的状态——当施加那些方法时,对象如何相应。
  3. 对象标识——如何比阿尼额具有相同行为与状态的不同对象。

同一个类的所有对象实例,由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法定义的。
此外,每个对象都保存着描述当前特征的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但是这种改变不是自发的。对象状态的改变必须通过调用方法实现。
但是,对象的状态并不能完全描述一个对象。每个对象都有一个唯一的身份。例如,在一个订单处理系统中,任何两个订单都存在着不同之处。即使所订购的货物完全相同也是如此。需要注意的是,作为一个类的实例,每个对象的标识永远是不同的,状态也常常存在着差异。

预定义类

Java中,没有类就无法做任何事情。也不是所有的类都具有面向对象特征。

对象与对象变量。

要想使用对象,就必须首先构造对象,并制定其初始状态。然后对对象应用方法。
在Java中,使用构造器构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。

Date类

构造器的名字应当与类名相同:new Date()
这个表达式构造了一个新对象。这个对象被初始化为当前的日期和时间。
我们需要储存这个构造出来的对象:Date birthday = new Date();
注意对象变量和对象是不同的,对象变量可以引用变量,在引用变量之前它什么都不是。
可以显式地将对象变量赋值为nullDate deadline = null;

GregorianCalendar类

在前面的例子中,已经使用了Java类库的Date类。Date类的实例有一个状态,即特定的时间点
尽管在使用Date类时不必知道这一点,但时间是用距离一个固定时间点的毫秒数(时间戳)来表示的。
但是Date类所提供的日期处理并没有太大的用途。Java类库的设计者认为,通用日期表示法只适用于我们一般的固有习惯。
类库设计者决定将保存时间与给时间点命名分开。所以Java类库分别包含了两个类,一个是表示时间点的Date类,一个是日历表示法GregorianCalendar类。将时间与日历分开是一种很好的面向对象设计。
通常,最好使用不同的类表示不同的概念。
GregorianCalendar类中有更多的构造器和方法。
可以提供年月日来构造一个表示某个特定日期午夜的日历对象:new GregorianCalendar(1998, 11, 31)
比较怪异的是,月份从0开始计数。为了清晰,可以用常量:new GregorianCalendar(1998, Calendar.DECEMBER, 31)
还可以设置时间:new GregorianCaldendar(1998, 11, 31, 23, 59, 59)

自定义类

从构造器开始

可以看到,构造器与类同名。在构造对象时,构造器会运行,以便将对象初始化为所希望的状态。

  • 构造器与类同名。
  • 每个类可以有多个构造器。
  • 构造器可以有0、1或者多个参数。
  • 构造器没有返回值。
  • 构造器总是伴随着new操作一起调用。

隐式参数和显式参数

方法用于操作对象和存取他们的实例域。

class a{
    int x;
    void b(int y){
        int x = y;
        this.x = x;
    }
}

上面是一个类的示例,类中有一个变量x,方法b中也有,this关键字就用来调用类中的参数,称为隐式参数。

静态域和静态方法

static是静态修饰符。

静态域

如果将域定义为static,每个类中只有一个这样的域。而每个对象对于所有的实例域却都有自己的一份拷贝。
static域是属于类的,所有对象共用一个。

静态方法

静态方法是不能向对象实施操作的方法。
可以认为static方法是没有this参数的方法。
使用静态方法主要在以下两种情况:

  1. 一个方法不需要访问对象状态,其所需的参数都是通过显示参数提供。
  2. 一个方法只需要访问类的静态域。

工厂方法

静态方法还有一种常见用途:采用不同的工厂方法产生不同风格的实例。
使用工厂方法主要有以下两种情况:

  1. 无法命名构造器,构造器的名字必须与类名相同。但是,这里希望得到的货币实例和百分比实例采用不同的名字。
  2. 当使用构造器时,无法改变所构造的对象类型。

方法参数

一般传参有两种形式:传引用、传值。
Java中总是采用按值调用的方式。方法得到的是所有参数值的一个拷贝。
特别地,方法不能修改传递给它的任何参数变量的内容。
然而,方法参数共有两种类型:基本数据类型、对象引用。
一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不同了。
可以在方法中修改对象的状态。
但这不是说对象引用可以改变对象变量的值,对象采用的不是引用调用,而是值传递。

对象构造

重载

多个方法有相同的名字,不同的参数列表,就产生了重载。
编译器根据方法的参数类型来判断具体执行哪个方法。

默认域初始化

如果再构造器中没有显式地给域赋予初值,那么就会自动地赋为默认值:数值为0,布尔值为false,对象引用为null。

无参数的构造器

如果再编写一个类是没有编写构造器,那么系统就会提供一个无参数构造器。
如果类中提供了至少一个构造器,但是没有提供无参数的构造器,则在构造对象时如果没有提供参数就会被视为不合法。

显示域初始化

由于类的构造方法可以重载,所以可以采用多种形式设置类的实例域的初始状态。
确保不管怎么样调用构造器,每个实例域都可以被设置为一个有意义的初值。
在执行构造器之前,先执行复制操作。当一个类的所有构造器都希望把相同的值富于某个特定的实例域是,这种方法特别有用。

Java使用包(package)来将类组织起来。借助包可以方便地组织自己的代码,并将自己的代码与别人提供的代码库分开管理。
标注你的Java类库分布于多个包中,包括java.lang``java.util``java.net等。标准的Java包都处于java``javax包层次中。
试用包的主要原因是确保类名的唯一性。加入两个程序员建立了同样类名的类,只要将这些类放置在不同的包中,就不会发生冲突。

类的导入

一个类可以使用所属包中的所有类,和其他包中的公共类。我们可以曹勇两种方式访问另一个包中的所有公共类。
第一种方式是在每个类名之前添加完整的包名:java.util.Date today = new java.util.Date()
这显然很繁琐。
更简单更常用的是使用import语句。
注意,只能用*导入一个包,不能导入所有包。

将类放入包中

要想将一个类放进包中,就必须将包的名字放在源文件的开头。
如果没有在源文件中放置package语句,这个源文件中的类就被放置在一个默认包中。默认包没有名字。
我们应当将包中的文件放到与完整的包名匹配的子目录中。

包作用域

前面已经接触过访问修饰符publicprivate。标记为public的部分可以被任意类使用,标记为private的部分职能被定义它们的类使用。
如果没有指定,这个部分可以被同一个包中的所有方法访问。

类路径

类的路径必须与包名匹配。
另外,类文件也可以存储在JAR文件中,在一个JAR文件中,可以包含多个压缩形式的类文件和子目录。这样既可以节省又可以改善性能。
在程序中用到第三方的库文件时,通常会给出一个或多个需要包含的JAR文件。JDK也提供了许多的JAR文件,例如,在jre/lib/re.jar中包含数千个类库文件。

为了使类能够被多个程序共享,需要做到以下几点:

  1. 把类放到一个目录中。需要注意,这个目录是包树状结构的基目录。如果希望将一个类添加到其中,这个类文件就必须位于子目录中。
  2. 在JAR文件放在一个目录中。
  3. 设置类路径,类路径是所有包含类文件的路径的集合。

在UNIX环境中,类路径中的不同项目之间采用冒号分隔。
而Windows环境中,类路径中的不同项目之间采用分号分隔。
类路径包括:

  • 基目录
  • 当前目录
  • JAR文件

文档注释

JDK包含一个很有用的工具,叫做javadoc,它可以由源文件生成一个HTML文档。
如果在源码中添加以专用的定界符开始的注释,那么可以很容易地生成一个看上去具有专业水准的文档。
这是一种很好的方式,因为这种方式可以将源码和注释保存在一个地方。如果将文档存入一个独立的文件中,就可能会随着时间的推移,出现代码和注释不一致的问题。

注释的插入

javadoc实用程序从下面几个特性中抽取信息:

  • 公用类和接口
  • 公有的和受保护的构造器和方法
  • 公有的和受保护的域

应该为上面几部分编写注释。注释应该放置在所描述的特性的前面。注释以/**开始,*/结束。
每个/**...*/文档注释在标记之后紧跟着自由格式文本。标记由@开始。
自由格式文本的第一句应该是一个概要性的句子。javadoc实用程序自动地将这些句子抽取出来形成概要页。

类设计技巧

下面简单记录一些OOP的类设计技巧。

1. 一定要保证数据私有

这是最重要的;绝对不要破坏封装性。有时候,需要编写一个访问器方法或更改器方法,但是最好还是保持实例域的私有性。
很多惨痛的经验告诉我们,数据的表示形式很可能会改变,但它们的使用方式却不会经常发生变化。当数据保持私有时,它们的表示形式的变化不会对类的使用者产生影响。

2. 一定要对数据初始化

Java不对局部变量进行初始化,但是会对对象的实例域进行初始化。最好不要依赖于系统的默认值,而是应该显式地初始化所有数据。
具体的初始化方式可以是提供默认值,也可以是在所有构造器中设置默认值。

3. 不要在类中使用过多的基本类型

就是说,用其他的类代替多个相关的基本类型的使用。这样会使类更加易于理解且已与修改。
例如,我们可以用一个新的类来替换类中的一些实例域。
这样可以更加容易地理解和处理变量。

4. 不是所有的域都需要独立的域访问器和域更改器

或许,需要获取或设置雇员的薪资。而一旦构造了雇员对象,就应该禁止更改雇用日期,并且在对象中,常常包含一些不希望别人获得或设置的实例域。

5. 将职责过多的类进行分解

这样说似乎有点含糊不清,究竟多少算是“过多”?
每个人的看法不同,但是如果明显地可以将一个复杂的类分解为两个更为简单的类,就应该将其分解。

6. 类名和方法名要能够体现它们的职责

与变量应该有一个能够反映其含义的名字一样,类也应该如此。
命名类名良好的习惯是采用一个名词、前面有形容词修饰的名词或动名词修饰的名词。
对于方法来说,习惯是访问器方法用小写get开头,更改器方法用小写set开头。

相关文章

网友评论

      本文标题:Java 学习记录二:OOP入门

      本文链接:https://www.haomeiwen.com/subject/vpzctxtx.html