Java学习day014 用户自定义类(下)(封装的优点、基于类的访问权限、私有方法)

使用的教材是java核心技术卷1,我将跟着这本书的章节同时配合视频资源来进行学习基础java知识。

day014  用户自定义类(下)(封装的优点、基于类的访问权限、私有方法)

我们已经开始编写了一些简单的类。但是,那些类都只包含一个简单的main方法。现在开始学习如何设计复杂应用程序所需要的各种主力类(workhorseclass)。通常,这些类没有main方法,却有自己的实例域和实例方法。要想创建一个完整的程序,应该将若干类组合在一起,其中只有一个类有main方法。


首先我们把之前的程序代码放在这里:

import java.time.*;

public class EmployeeTest 
{
	public static void main(String[] args)
	{
		//fill the staff array with three Employee objects
		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);
		
		//raise everyone's salary by 5%
		for (Employee e : staff)
			e.raiseSalary(5);
		
		//print out information about all Employee objects
		for (Employee e : staff)
			System.out.println("name="+e.getName()+",salary="+e.getSalary()+",hireDay="+e.getHireDay());
	}
}

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;
		//double raise = this.salary * byPercent / 100;
		//this.salary += raise;
	}	
}

 

我们继续分析这个程序。


6.封装的优点

仔细地看一下非常简单的getName方法、getSalary方法和getHireDay方法。

public String getName()
	{
		return name;
	}
	
	public double getSalary()
	{
		return salary;
	}
	
	public LocalDate getHireDay()
	{
		return hireDay;
	}

这些都是典型的访问器方法。由于它们只返回实例域值,因此又称为域访问器。

将name、salary和hireDay域标记为public,以此来取代独立的访问器方法会不会更容易些呢?

关键在于name是一个只读域。一旦在构造器中设置完毕,就没有任何一个办法可以对它进行修改,这样来确保name域不会受到外界的破坏。

虽然salary不是只读域,但是它只能用raiseSalary方法修改。特别是一旦这个域值出现了错误,只要调试这个方法就可以了。如果salary域是public的,破坏这个域值的捣乱者有可能会出没在任何地方。

在有些时候,需要获得或设置实例域的值。因此,应该提供下面三项内容:

1.一个私有的数据域

2.一个公有的域访问器方法

3.一个公有的域更改器方法

这样做要比提供一个简单的公有数据域复杂些,但是却有着下列明显的好处:

首先,可以改变内部实现,除了该类的方法之外,不会影响其他代码。例如,如果将存储名字的域改为:

String firstName;
String lastName;

那么getName方法可以改为返回

firstName + " " + lastName

对于这点改变,程序的其他部分完全不可见。

当然,为了进行新旧数据表示之间的转换,访问器方法和更改器方法有可能需要做许多工作。但是,这将为我们带来了第二点好处:更改器方法可以执行错误检查,然而直接对域进行赋值将不会进行这些处理。例如,setSalary方法可以检查薪金是否小于0。

注意不要编写返回引用可变对象的访问器方法。如果需要返回一个可变对象的引用,应该首先对它进行克隆(clone)。对象clone是指存放在另一个位置上的对象副本。


7.基于类的访问权限

从前面已经知道,方法可以访问所调用对象的私有数据。一个方法可以访问所属类的所有对象的私有数据,这令很多人感到奇怪!例如,下面看一下用来比较两个雇员的equals方法。

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

典型的调用方法是:

if (harry.equals(boss))...

这个方法访问harry的私有域,这点并不会让人奇怪,然而,它还访问了boss的私有域。这是合法的,其原因是boss是Employee类对象,而Employee类的方法可以访问Employee类的任何一个对象的私有域。


8.私有方法

在实现一个类时,由于公有数据非常危险,所以应该将所有的数据域都设置为私有的。然而,方法又应该如何设计呢?尽管绝大多数方法都被设计为公有的,但在某些特殊情况下,也可能将它们设计为私有的。有时,可能希望将一个计算代码划分成若干个独立的辅助方法。通常,这些辅助方法不应该成为公有接口的一部分,这是由于它们往往与当前的实现机制非常紧密,或者需要一个特别的协议以及一个特别的调用次序。最好将这样的方法设计为private的。

在Java中,为了实现一个私有的方法,只需将关键字public改为private即可。

对于私有方法,如果改用其他方法实现相应的操作,则不必保留原有的方法。如果数据的表达方式发生了变化,这个方法可能会变得难以实现,或者不再需要。然而,只要方法是私有的,类的设计者就可以确信:它不会被外部的其他类操作调用,可以将其删去。如果方法是公有的,就不能将其删去,因为其他的代码很可能依赖它。


9.final实例域

可以将实例域定义为final。构建对象时必须初始化这样的域。也就是说,必须确保在每一个构造器执行之后,这个域的值被设置,并且在后面的操作中,不能够再对它进行修改。例如,可以将Employee类中的name域声明为final,因为在对象构建之后,这个值不会再被修改,即没有setName方法。

class Employee
{
    private final String name;
    ...
}

final修饰符大都应用于基本(primitive)类型域,或不可变(immutable)类的域(如果类中的每个方法都不会改变其对象,这种类就是不可变的类。例如,String类就是一个不可变的类)。

对于可变的类,使用final修饰符可能会对读者造成混乱。例如,

private final StringBuilder evaluations;

在Employee构造器中会初始化为:

evaluations = new StringBuilder();

final关键字只是表示存储在evaluations变量中的对象引用不会再指示其他StringBuilder对象。不过这个对象可以更改:

public void giveGoldStar()
{
    evaluations.append(LocalData.now()+":Gold star!\n");
}

用户自定义类就学完了,写程序的时候往往需要我们自己自定义类来写方法操作我们的数据,所以这一块需要熟练掌握。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值