java对象(二)

java 对象和类(二)

用户自定义类

最简单的类定义形式为:

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

写一个自定义类的例子:

import java.time.*;
/**
 * @author [email protected]
 * @date 2018/9/4 14:53
 */
public class EmployeeTest {
    public static void main(String[] args)
    {   //构造一个Employee数组,并填入三个雇员对象
        Employee[] staff = new Employee[3];

        staff[0] = new Employee("刘甲",75000,1991,1,1);
        staff[1] = new Employee("刘乙",50000,1991,2,2);
        staff[2] = new Employee("刘丙",30000,1991,3,3);
        //使用raiseSalary方法提升每个雇员5%的薪水
        for (Employee e : staff)
            e.raiseSalary(5);

        //调用3种方法将每个雇员的信息打印出来
        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;
    }
}

对这个例子进行分析:

你可能会注意到这一个源文件包含了两个类,但是也可以将每一个类存在一个单独的源文件中。、

你会发现可以直接运行EmployeeTest.java,并没有显示的编译Employee.java,会发现正常运行。原因是java编译器发现EmployeeTest.java使用了Employee类时会自动查找Employee class文件,当查找不到时,会自动搜索Employee.java文件然后进行编译。重要的是:如果Employee.java版本比已有的Employee class文件版本新,java编译器会自动地重新编译这个文件。

Employee类中包含一个构造器和4个方法,这个类中的所有方法都被标记为public,意味着任何类的任何方法都可以调用这些方法。private确保只有Employee类自身的方法能够访问这些实例域,而其他类的方法不能够读写这些域。有两个实例域本身就是对象,name域是String类对象,hireDay是localDate类对象,类通常帮括类型属于某个类类型的实例域。

构造器

Employee类中的构造器与类同名,在构造Employee类的对象时,构造器会运行,以便将实例域初始化为所希望的状态。

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

注:不要在构造器中定义与实例域重名的局部变量。

隐式参数与显示参数

例如:test123.raiseSalary(5); //结果将test123.salary域的值增加5%


//其实调用的是执行的下列指令
double raise = test123.salary * 5 /100;
test123.salary += raise;

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

可以看到,显示参数是明显地列在方法声明中的,例如double byPercent,关键字this表示隐式参数,如果需要的话可以按下列编写方式。

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

封装的优点

需要获得或设置实例域的值,应该提供下面三项内容:

  • 一个私有的数据域
  • 一个公有的域访问器方法
  • 一个公有的域更改器方法

这样做比提供一个简单的公有数据域复杂,但是有明显的好处:可以改变内部实现,除了该类的方法之外,不会影响其他代码。例:

//将存储名字的域改为下面
String firstName;
String lastName;
那么getName方法可以改为返回
firstName + " " + lastName

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

其次,更改器方法可以执行错误检查,然后直接对域进行赋值就不会处理这些。

注:不要编写返回引用可变对象的访问器方法,在上面的例子中如果将localDate类换成Date类就违反了这个设计原则。因为Date对象是可变的,这样就破坏了封装性,Date类中有一个更改器方法setTime,可以设置毫秒数。

猜你喜欢

转载自blog.csdn.net/u014793102/article/details/82390107