Java核心技术4:Java的对象与类

4.1     OOP概述

        面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。

        传统的结构化程序设计首先要确定如何操作数据,然后再决定如何组织数据,以便于数据操作。OOP调换了这个次序,数据被放在第一位,然后再考虑操作数据的算法。

4.1.1    类

        由类class构造construct对象的过程称为创建类的实例instance。

        封装encapsulation:将数据和行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。

        对象中的数据称为实例域instance fields,操纵数据的过程称为方法method,每个特定的类实例(对象)都有一组特定的实例域值,这些值的集合就是这个对象的当前状态state。

        实现封装的关键:绝对不能让类中的方法直接地访问其他类的实例域。程序仅通过对象的方法与对象数据进行交互。

        类可以通过扩展另一个类来建立,终极父类Object。

4.1.2    对象

        对象的状态的改变必须通过调用方法实现。每个对象都保存着描述当前特征的信息。

4.1.3    识别类

        首先从设计类开始,然后再往每个类中添加方法。

4.1.4    类之间的关系

        常见关系:依赖use-a,聚合has-a,继承is-a

        依赖:如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。应将相互依赖的类减至最少,耦合度最小。

        聚合:聚合意味着类A的对象包含类B的对象。

        继承:表示特殊与一般关系的。如果类A扩展类B,类A不但包含从类B继承的方法,还有一些额外的功能。

4.2     使用现有类

4.2.1    对象与对象变量

        Java使用构造器constructor构造新实例。构造器的名字与类名相同。

        Date类,它的对象描述一个时间点。Date day=new Date();。构造了一个新对象,被初始化为当前的日期和时间。day则是一个对象变量,上例使用新构造的对象初始化这个变量,也可以让这个变量引用一个已存在的对象:day=birthday;

        一个对象变量并没有实际包含一个对象,仅仅引用一个对象。任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new操作符的返回值也是一个引用。显式地将对象变量设置为null,表明这个对象变量目前没有引用任何对象。

        所有的Java对象都存储在堆中,当一个对象包含另一个对象变量时,这个变量依然包含着指向另一个堆对象的指针。

4.2.2    GregorianCalendar类

        表示日历,扩展自Calendar类。

4.2.3    更改器方法与访问器方法,setter & getter

        对实例域做出修改的方法为更改器方法mutator method,仅访问实例域的方法为访问器方法accessor method。

        已知年月日,希望创建一个包含这个时间值的Date对象,由于Date类不知如何操作日历,所以首先构造一个GregorianCalendar对象,如何调用getTime方法获得一个日期对象:GregorianCalendar calendar=new GregorianCalendar(year, month, day); Date day = calendar.getTime();

        如果希望获得Date对象的年月日,需要构造一个GregorianCalendar对象,设置时间,然后调用get方法:GregorianCalendar calendar=new GregorianCalendar(); calendar.setTime(day); int year = calendar.get(Calendar.YEAR);

        DateFormatSymbols:获得当前地区的星期几或月份的名称,利用Calendar的星期和月份常量作为数组索引值。

4.3    用户自定义类

4.3.1    一个Employee类

        class ClassName{

            constructor;method;fields;

        }

        class Employee{~~~~~}

        在一个源文件中,只能有一个公有类,与文件名相匹配,但可以有任意数目的非公有类。

4.3.2    多个源文件的使用

        Employee类存在文件Employee.java中,EmployeeTest类存放在文件EmployeeTest.java中。

        使用javac EmployeeTest.java 变异,没有显式地编译Employee.java,当Java编译器发现EmployeeTest.java使用了Employee类时会查找名为Employee.class的文件,如果没有找到,就会自动搜索Employee.java,然后对它进行编译。如果Employee.java版本较已有的Employee.class文件版本新,Java编译器会自动重新编译这个文件。

4.3.3    解析Employee类

        关键字public意味着任何类的任何方法都可以调用这些方法。

        关键字private确保只有Employee类自身的方法能够访问这些实例域,而其他类的方法不能读写这些域。

        类通常包括类型属于某个类的实例域。

4.3.4    从构造器开始

        构造器与类同名,构造器总是伴随着new操作符的执行被调用,而不能对一个已经存在的对象调用构造器来达到重新设置实例域的目的。每个类可以有一个以上的构造器,构造器可以有0个、1个或1个以上的参数,构造器没有返回值。

4.3.5    隐式参数与显式参数

        public void raiseSalary(double byPercent){

            double raise = salary * byPercent / 100; salary += raise;

        }

        raiseSalary有两个参数,第一个参数称为隐式参数,是出现在方法名前的Employee类对象,第二个参数位于方法名后面括号中的数值,是一个显式参数。

        显式参数是明显地列在方法声明中的显示参数。隐式参数没有出现在方法声明中。

        在每一个方法中,关键字this表示隐式参数。

4.3.6    封装的优点

        有时,需要获得或设置实例域的值,因此应该提供:一个私有的数据域,一个公有的域访问器,一个公有的域更改器。

        好处:1.可以改变内部实现,除了该类的方法外,不会影响其他代码。2.更改器方法可以执行错误检查,直接对域进行赋值将不会进行这些处理。

4.3.7    基于类的访问权限

        方法可以访问所调用对象的私有数据。一个方法可以访问所属类的所有对象的私有数据。

4.3.8    私有方法

        有时希望将一个计算代码划分成若干独立的辅助方法,这些辅助方法不应成为公有接口的一部分。

4.3.9    Final实例域

        Final实例域,在构建对象时必须初始化这样的域,且在后面的操作中,不能再对它进行修改。

        final修饰符多应用于基本数据类型域,或不可变类(类中每个方法都不会改变其对象)的域。

4.4    静态域与静态方法

4.4.1    静态域(类域)

        如果将域定义为static,每个类中只有一个这样的域,它属于类,而不属于任何独立的对象。

4.4.2    静态常量

        公有常量可以设置为public。

4.4.3    静态方法

        静态方法不能向对象实施操作。没有隐式参数。

        两种情况下使用静态方法:1.一个方法不需要访问对象状态,其所需参数都是通过显式参数提供(工具类方法)。2.一个方法只需要访问类的静态域。

4.4.4    Factory方法

4.4.5    Main方法

4.5    方法参数

        值调用(call by value)表示方法接收的是调用者提供的值,引用调用(call by reference)表示方法接收的是调用者提供的变量地址。

        Java总数采用值调用,方法得到的是所有参数值的一个拷贝,不能修改传递给它的任何参数变量的内容。

        对于对象引用参数,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。

        1. 一个方法不能修改一个基本数据类型的参数

        2. 一个方法可以改变一个对象参数的状态

        3. 一个方法不能实现让对象参数引用一个新的对象。

4.6    对象构造

4.6.1    重载

        如果多个方法有相同的名字、不同的参数,便产生了重载。编译器通过用各个方法给出的参数与特定方法调用所使用的值类型进行匹配来挑选出相应的方法。

        方法名和参数类型,叫做方法的签名。返回类型不是方法签名的一部分。

4.6.2    默认域初始化

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

4.6.3    默认构造器

        没有参数的构造器。如果没有编写构造器,系统会提供一个默认构造器,将所有的实例域设置为默认值。

4.6.4    显式域初始化

        在类定义中,直接将一个值赋给任何域。

4.6.5    参数名

4.6.6    调用另一个构造器

        关键字this引用方法的隐式参数。另一层含义:如果构造器的第一个语句形如this(...),这个构造器将调用同一个类的另一个构造器。对公共的构造器代码部分只编写一次即可。

4.6.7    初始化块

        初始化块是初始化数据域的第三种方式,前两种是在构造器中设置值和在声明中赋值。

        首先运行初始化块,然后才运行构造器的主体部分。

        调用构造器的具体处理步骤:

        1.所有数据域被初始化为默认值

        2.按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块

        3.如果构造器第一行调用了第二个构造器,则执行第二个构造器主体

        4.执行这个构造器的主体

4.6.8    对象析构与finalize方法

4.7    包

        包package将类组织起来。

4.7.1    类的导入

        一个类可以使用所属包中的所有类,以及其他包中的公有类。

        import语句是一种引用包含在包中的类的简明描述。可以使用import导入一个特定的类或者整个包。

4.7.2    静态导入

        导入静态方法和静态域,也可以导入特定的方法或域。不过,有时会不利于代码的清晰度。

4.7.3    将类放入包中

        将包的名字放在源文件的开头,包中定义类的代码之前。将包中的文件放到与完整的包名匹配的子目录中。

4.7.4    包作用域

        标记为public的部分可以被任意的类使用,标记为private的部分只能被定义它们的类使用;如果没有指定public或private,这个部分(类、方法或变量)可以被同一个包中的所有方法访问。

4.8    类路径

4.9    文档注释

4.9.1    注释的插入

        Javadoc从以下几个特性中抽取信息:包、公有类与接口、公有的和受保护的方法、公有的和受保护的域。

        应为上面几部分编写注释,以/**开始,以*/结束。

4.9.2    类注释

        类注释放在import之后,类定义之前。

4.9.3    方法注释

        方法注释放在所描述的方法之前。除通用标记外,还可以使用:@param,@return,@throws

4.9.4    域注释

        只需要对公有域(通常是静态常量)建立文档。

4.9.5    通用注释

        如下标记可以用在类文档的注释中:@author  name,@version  text,

        如下标记可用于所有的文档注释:@since  text,@deprecated   text,@see reference

4.9.6    包与概述注释

4.9.7    注释的抽取

4.10    类设计技巧

        1. 将数据设计为私有:不要破坏封装性。

        2. 要对数据初始化:java不对局部变量初始化,但是会对对象的实例域进行初始化。不要依赖于系统默认值,而应显式初始化。

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

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

        5. 使用标准格式进行类的定义:

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值