《Core Java》读书笔记——第4章

对象与类

本章代码

4.1 面向对象程序设计概述


4.2 使用预定义类

主要是用日期相关的类举例,具体看代码。

4.2.1 对象与对象变量

要想使用对象,就必须首先构造对象,并指定其初始状态。构造新对象需要在构造器前面加上new操作符,以Date类为例。
new Date();
在Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new操作符的返回值也是一个引用。

Java类库中的GregorianCaledar类
GregorianCalendar有几个很有用的构造器:
1.new GregorianCalendar(); 用于表示对象构造是的日期和时间。

2.new GregorianCalendar(1999,11,31); 提供年,月,日构造一个表示某个特定日期的日历对象。但是月份是从0开始计数的,所以11表示十二月,为了避免混淆,可以使用常量,如:Calendar.DECEMBER。

3.new GregorianCalendar(1999,Calendar.DECEMBER,31,23,59,59); 后面三个参数表示时间,即:23:59:59。

更改器方法与访问器方法
主要是get与set方法,仍然以GregorianCalendar为例。
get方法。可以获取某个时间点的年月日等信息。这需要借助Calendar类中定义的一些常量。如:Calendar.MONTH 或 Calendar.DAY_OF_WEEK:

    GregorianCalendar now = new GregorianCalendar();
    int month = now.get(Calendar.MONTH);
    int weekday = now.get(Calendar.DAY_OF_WEEK);

更多的请参考API文档

set方法。调用set方法,可以改变对象的状态。

    deadline.set(Calendar.YEAR,2001);
    deadline.set(Calendar.MONTH,Calendar.APRIL);
    deadline.set(Calendar.DAY_OF_MONTH,15);
    deadline.set(2001,Calendar.APRIL,15);  //直接设置年月日
    deadline.add(Calendar.MONTH,2);   //deadline后移2个月

4.3 用户自定义类

    class ClassName
    {
        field1
        field2
        ...
        constructor1
        constructor2
        ...
        method1
        method2
    }

以上是Java中,最简单的类的定义形式。

4.3.1 Employee 类

    class Employee
{
    private String name;
    private double salary;
    private Date hireDay;

    public Employee(String n, double s, int year, int month, int day)
    {
        name = n;
        salary = s;
        GregorianCalendar d = new GregorianCalendar(year,month-1,day);
        hireDay = d.getTime();
    }

    public String getName()
    {
        return name;
    }

    public double getSalary()
    {
        return salary;
    }

    public Date getHireDay(){
        return hireDay;
    }

    public void raiseSalary(double byPercent)
    {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
}

4.3.2 多个源文件的使用

Employee.java 和 EmployeeTest.java 可以分开。

4.3.3 剖析Employee类

这个类包含一个构造器和4个方法。所有的方法被标记为public,共有4中访问级别。

4.3.4 从构造器开始

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

4.3.5 隐式参数与显式参数

类中的非静态方法会包含一个隐式参数,即this,关键字this指向对象本身。显式参数则是明显地列于方法声明中的。

4.3.6 封装的优点

私有的数据域
公有的域访问器方法
公有的域更改器方法
注意不要编写返回引用可变对象的访问器方法。这样会破坏封装性。

4.3.7 基于类的访问权限

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

4.3.8 私有方法

4.3.9 final实例域

可以将实例域定义为finall。构建对象时必须初始化这样的域。
final修饰符大都应用于基本类型域,或不可变类的域。


4.4 静态域与静态方法

4.4.1 静态域

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

    class Employee
    {
        private static int nextID = 1;
        private int id;
        ...
    }

每一个雇员对象都有一个自己的id域,但是所有的对象共享一个nextID域。

4.4.2 静态常量

public static final, 类中静态常量的声明。

4.4.3 静态方法

静态方法是一种不能向对象实施操作的方法。也就意味着静态方法不能访问类中非静态域的任何其他实例域。在下面两种情况下使用静态方法。

一个方法不需要访问对象状态,其所需参数都是通过显式参数提供。(例如:Math.pow)
一个方法只需要访问类的静态域(例如:Employee.getNextId).

4.4.4 工厂方法

以NumberFormat举例,它使用工厂方法产生不同风格的格式对象。这是静态方法的用途之一。

无法命名构造器。这里希望将得到的货币实例和百分比实例采用不同的名字。

当使用构造其实,无法改变所构造的对象的类型。而Factory方法将返回一个DecimalFormat类对象,这是NumberFormat的子类。

4.4.5 main方法

main方法不对任何对象进行操作。


4.5 方法参数

方法参数有按值调用(call by value) 和 按引用调用(call by reference) 两种。Java中总是采用按值调用。也即方法得到的是所有参数值的一个拷贝。这里主要看看基本类型和引用类型作为参数传递的不同之处。

基本类型

    public static void tripleValue(double x)
    {
        x = 3 * x;
    }

    double percent = 10;
    triplevalue(percent);

普通类型参数传递
由上图可以看到,x先被初始化为percent的一个拷贝,x被乘以3之后等于30。但是percent仍然是10。方法调用完之后,x的生命周期就结束了,percent并没有被改变。

引用类型的传递

    public static void tripleSalary(Employee x)
    {
        x.raiseSalary(200);
    }
    harry = new Employee(...);
    tripleSalary(harry);

引用类型的参数传递
x被初始化为harry的一个拷贝,x也是一个对象的引用,与harry指向同一个对象
rasieSalary方法应用于这个对象引用。因此harry的薪金也提高了2倍。
方法调用结束后,x的声明周期结束,harry仍然使用,harry的值已经改变。

总结:
一个方法不能修改一个基本数据类型的参数
一个方法可以修改对象参数的状态
一个方法不能让一个对象参数引用一个新的对象。


4.6 对象构造

4.6.1 重载

函数名相同,参数列表不同

4.6.2 默认域初始化

如果在构造器中没有显示地给域赋予初值,那么就会被自动地赋为默认值。这是域和局部变量的主要不同点。必须明确地初始化方法中的局部变量。但是如果没有初始化类中的域,将会被初始化为默认值

4.6.3 无参数的构造器

如果在编写一个类时没有编写构造器,那么系统就会提供一个无参数构造器。一定要记住,仅当类没有提供任何构造器的时候,系统才会提供一个默认构造器。

4.6.4 显式域初始化

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

    class Employee
    {
        private String name = "";
    }

4.6.5 参数名

    public Employee(String name, double salary)
    {
        this.name = name;
        this.salary = salary    
    }

4.6.6 调用另一个构造器

如果构造器的第一个语句形如this(…),这个构造器将调用同一个类的另一个构造器。

    public Employee(double s)
    {
        this("Employee #" + nextId, s);
        nextId++;
    }

这种方式可以对公共的构造器代码部分只编写一次即可。

4.6.7 初始化块

在一个类的声明中可以包含多个代码块,只要构造类的对象,这些块就会被执行。

    class Employee
    {
        private static int nextId;
        private int id;
        private String name;
        private double salary;

        //对象初始化块
        {
            id = nextId;
            nextId++;
        }

        public Employee(String n, double s)
        {
            name = n;
            salary = s;
        }

        public Employee()
        {
            name = "";
            salary = 0;
        }
        ...
    }

调用构造器的具体处理步骤:
1)所有数据域初始化为默认值
2)按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块。
3)如果构造器第一行调用了第二个构造器,则执行第二个构造器主体。
4)执行这个构造器主体。

还可以提供一个静态初始化块来初始化类的静态域。

4.6.8 对象析构与finalize方法

不常用

4.7 包

Java允许使用包将类组织起来。从编译器的角度来看,嵌套的包之间没有任何关系。每一个都有独立的类集合

4.7.1 类的导入

一个类可以使用所属包中的所有类,以及其他包中的公有类。可以有两种方式访问另一个包中的公有类。第一种是在类名之前添加完整的包名。第二种是用import语句。注意,import只能导入类,不能导入包。不能import java.*; 导入以java为前缀的所有的包。

如果两个包中有类名冲突,在类名前加上完整的包名。

4.7.2 静态导入

import static java.lang.System.*;
加上以上语句,就可以使用System类的静态方法和静态域,而不必加类名前缀
out.println(“Goodbye, World!”);
exit(0);

4.7.3 将类放入包中

package语句。另外,编译器对文件进行操作,而Java解释器加载类带有(.分隔符)。

4.7.4 包作用域

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


4.8 类路径

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

1)把类放到一个目录中,例如/home/user/classdir。需要注意,这个目录是包树状结构的基目录。
2)将JAR文件放在一个目录中,例如:/home/user/archives
3)设置类路径(classpath)。类路径是所有包含类文件的路径的集合。

要想import语句能够正常引用其他包中的类,则其他包也必须要位于classpath下。虚拟机会根据设置的classpath的顺序来查找所需的类。


4.9 文档注释


4.10 类设计技巧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值