4.3 自定义类

本文介绍了一个具体的Java类设计案例——Employee类,并详细解析了类的属性、构造器及方法等核心元素。此外,还讨论了类之间的聚合关系、构造器的特性、封装的好处以及如何正确实现类的访问权限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 一个员工类

一个典型的类形式如下:

class 类名字
{
    属性1
    属性2
    ...

    构造器1
    构造器2
    ...

    方法1
    方法2
    ... 
}

一个是实际例子

public class Employee
{
    // 属性
    private String name;
    private double salary;
    private LocalDate hireDay;

    // 构造器
    public Employee(String n, double s, int year, int month, int day)
    {
        name = n;
        salary = s;
        hireDay = LocalDate.of(year, month, day);
    }

    // 一个方法
    public String getName()
    {
    return name;
    }
    // 更多的方法
    public double getSalary()
    {
        return salary;
    }

    public LocalDate getHireDay()
    {
        return hireDay;
    }

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

使用这个类

class EmployeeTest
{
    public static void main(String[] args)
    {
        // 用数组创建这个类的变量
        Employee[] staff = new Employee[3];

        staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
        staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
        staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);
        // 给每个人涨5%的薪水
        for (Employee e : staff)
            e.raiseSalary(5);
        // 打印每个人的薪水信息
        for (Employee e : staff)
            System.out.println("name=" + e.getName() + ",salary=" + e.getSalary() + ",hireDay="
            + e.getHireDay());
    }
}

如果可以看到这里有两个类,一个是EmployeeTest、一个是Employee类。
但是在编译的时候只要运行javac EmployeeTest.java就可以了,因为编译器会自动寻找Employee类进行编译。

2 多个源文件的使用

javac Employee*.java

这样Java编译器会把所有以Employee字符开始的.java文件都进行编译。

3 仔细分析Employee类

注意道Employee类使用了String类和LocalDate类。这就是之前说的类之间的聚合关系。

4 构造器

构造器只能被new关键字调用,不能够使用类名或者类的实例对象来调用构造器。

  1. 构造器名称和类名相同
  2. 一个类可以拥有很多构造器
  3. 一个构造器可以没有参数,或者1个参数,或者很多参数
  4. 构造器没有返回值
  5. 构造器总是用new关键字调用

注意:构造器内部定义的变量是局部变量,其他方法是不可以使用其局部变量的。

5 隐式参数和显示参数

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

仔细看这个方法,salary变量是属于调用这个方法的类对象,这个方法内部并没有salary变量。所以,这类的变量是隐式参数。更确切的说,raiseSalary()方法传入了2个参数,除了显示参数double类的byPercent还有一个隐式参数this,这个this指的是调用这个方法的类对象。这个类对象有salary变量,自然的,这个方法也可以使用这个变量啦。

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

推荐这样写这样写方法,因为会把类对象的变量和方法内局部变量分的很清楚。

6 封装的好处

为什么要用修改器和访问器方法?因为我们用private关键字把对象的属性或者方法给保护起来了,那么外界就不能随便更改这些属性或者调用这些方法,只能通过修改器和访问器方法修改属性,别的public方法调用被保护的方法,好处是,那么一旦,我们修改这类的代码,那么对外界的影响也是最小的。
第二个好处是修改器方法可以检查修改的属性对不对,你不能把一个负数当成年龄。

面向对象的语言有3大好处:封装 多态 继承

值得注意的是:前往小心返回值是类对象的访问器方法。
这里写图片描述
如图所示,如果改变d则就变相改变了harry这个雇员的雇佣时间了。解决办法是,不要传出雇佣时间,如果别人想知道雇佣时间,就传出副本,clone()方法。

public Date getHireDay()
{
    return (Date)hireDay.clone();
}

这样d和hireDay引用的就不是同一个实例对象了,那么也就不会发生更改雇佣时间的问题了。

7 基于类的访问权限

class Employee
{
    . . .
    public boolean equals(Employee other)
    {
        return name.equals(other.name);
    }
}

注意到这个方法调用了other.name,即便你设置了private 的name,这个类的方法还是可以访问到这个类的所有属性。

8 私有方法

方法也可以设置成为private,禁止外界访问嘛。但是要注意,即使是私有地,这个类的其他方法还是可以用这个方法的,毕竟自己都不能用,那还定义这个方法干嘛?

9 最终属性

你可以把一个属性定义成为final的。

class Employee
{
    private final String name;
}

一旦一个属性被声明为final,那么这个属性就不能被更改了。
要注意,这里的不可更改指的是这个变量对象不能被更改,String类还好,所有name一旦被初始化,那么就不能更改了。
但是如果是LocalDate类,即便hireDay被初始化,那么它会永远指向被初始化的对象,问题是,LocalDate是有方法可以改变它保存的时间的。
所以也不要盲目使用final,一定要多多注意这种情况哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值