4.3用户自定义类
通常这些类没有 main 方法 , 却有自己的实例域和实例方法 。
(实例域:定义类时的最外层的那两个大括号那个范围。
实例方法:没有static关键字的都叫实例方法。有关键字的叫类方法。)
4.3.1需求
1.构造一个数组,填入三个员工的信息。
2.将每个员工的工资提高5%。
3.将每个员工的信息打印出来。
4.3.2实现
package com.eleven.oop;
import java.time.LocalDate;
/**
* 将员工的工资提高5%
*
* @author sywangu
*
*/
public class EmployeeTest {
public static void main(String[] args) {
// 1.构造一个数组,填入三个雇员对象
Employee[] staff = new Employee[3];
staff[0] = new Employee("伊莱文", 30000.0, 1989, 12, 15);
staff[1] = new Employee("Eleven", 40000.0, 1987, 10, 21);
staff[2] = new Employee("Keep", 50000.0, 1980, 11, 21);
// 2.将每个雇员的薪水提高5%
for (Employee e : staff) {
e.raiseSaraly(5);
}
// 3.打印出每个雇员的信息
for (Employee e : staff) {
System.out.println("员工" + "姓名:" + e.getName() + "工资:" + e.getSalary() + "薪水:" + e.getHireday());
}
}
}
class Employee { // Employee是实例
private String name; // 实例域
// 其中private Double salary和private LocalDate
// hireday它们两个的实例域的本身就是对象。name域是String类对象,hireDay域是LocalDate类对象
private Double salary;
private LocalDate hireday; // 雇佣
/**
* 如果有 1000 个 Employee 类的对象 , 则有 1000 个实例域 id 。 但是 , 只有一 个静态域 nextld 。
*/
// 实例域:Java定义类中的属性;静态域:在属性前面加上static关键字
private static int nextId = 1; // 静态域id
private int id; // 实例域id
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public LocalDate getHireday() {
return hireday;
}
public void setHireday(LocalDate hireday) {
this.hireday = hireday;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + ", hireday=" + hireday + "]";
}
// 一个构造器和4个方法,其中构造器和类名要相同
public Employee(String n, Double s, int year, int month, int day) {
super();
this.name = n;
this.salary = s;
this.hireday = LocalDate.of(year, month, day);
}
public Employee() {
super();
}
/**
* 提高工资的5%
*
* @param byPercent
*/
public void raiseSaraly(double byPercent) {
double raise = salary * byPercent / 100; // 提高后的薪水
salary += raise; // 原有的薪水 + 提高后的薪水
}
/**
* 比较两个员工的equals方法
*
* @param other
* @return
*/
public boolean equals(Employee other) {
return name.equals(other.name);
}
public void setId() {
id = nextId;
nextId++;
}
}
4.3.3输出
员工姓名:伊莱文工资:31500.0薪水:1989-12-15
员工姓名:Eleven工资:42000.0薪水:1987-10-21
员工姓名:Keep工资:52500.0薪水:1980-11-21
4.4构造器
构造器与类同名
• 每个类可以有一个以上的构造器
• 构造器可以有0 个 、 1 个或多个参数
• 构造器没有返回值
• 构造器总是伴随着new 操作一起调用
4.5隐式参数和显式参数
隐式参数:出现在方法名前面的对象,隐式参数用关键字this表示。
显式参数:方法名后面括号中的数值。
4.5.1完整代码
package com.eleven.oop;
import java.time.LocalDate;
public class ShowHiddenParam { // 隐式参数
private String name;
private Double salary;
private LocalDate hireday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public LocalDate getHireday() {
return hireday;
}
public void setHireday(LocalDate hireday) {
this.hireday = hireday;
}
// 出现在方法名前面的ShowHiddenParam是隐式参数
public void raiseSaraly(double byPercent) { // 方法名括号后面的数值:double byPercent是一个显示参数
// double raise = salary * byPercent / 100;
// salary += raise;
// 关键字this表示隐式参数,有人喜欢这种方式,因为这样可以将实例域与局部变量明显地区分开来
double raise = this.salary * byPercent / 100;
this.salary += raise;
}
}
4.6final实例域
被定义为final时,这个值不会被修改,同样,也没有set方法。
final 修饰符大都应用于基本 ( primitive ) 类型域, 或不可变 ( immutable )类的域 ( 如果类中的每个方法都不会改变其对象 , 这种类就是不可变的类。 例如 , String 类就是一个不可变的类 ) 。
4.7静态域
4.7.1需求
假如有 1000 个 Employee 类的对象 , 则有 1000 个实例域 id 。 但是 , 只有一 个静态域 nextld 。
4.7.2完整代码
package com.eleven.oop;
import java.time.LocalDate;
/**
* 将员工的工资提高5%
*
* @author sywangu
*
*/
public class EmployeeTest {
public static void main(String[] args) {
// 1.构造一个数组,填入三个雇员对象
Employee[] staff = new Employee[3];
staff[0] = new Employee("伊莱文", 30000.0, 1989, 12, 15);
staff[1] = new Employee("Eleven", 40000.0, 1987, 10, 21);
staff[2] = new Employee("Keep", 50000.0, 1980, 11, 21);
// 2.将每个雇员的薪水提高5%
for (Employee e : staff) {
e.raiseSaraly(5);
}
// 3.打印出每个雇员的信息
for (Employee e : staff) {
System.out.println("员工" + "姓名:" + e.getName() + "工资:" + e.getSalary() + "薪水:" + e.getHireday());
}
}
}
class Employee { // Employee是实例
private String name; // 实例域
// 其中private Double salary和private LocalDate
// hireday它们两个的实例域的本身就是对象。name域是String类对象,hireDay域是LocalDate类对象
private Double salary;
private LocalDate hireday; // 雇佣
/**
* 如果有 1000 个 Employee 类的对象 , 则有 1000 个实例域 id 。 但是 , 只有一 个静态域 nextld 。
*/
// 实例域:Java定义类中的属性;静态域:在属性前面加上static关键字
private static int nextId = 1; // 静态域id
private int id; // 实例域id
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public LocalDate getHireday() {
return hireday;
}
public void setHireday(LocalDate hireday) {
this.hireday = hireday;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + ", hireday=" + hireday + "]";
}
// 一个构造器和4个方法,其中构造器和类名要相同
public Employee(String n, Double s, int year, int month, int day) {
super();
this.name = n;
this.salary = s;
this.hireday = LocalDate.of(year, month, day);
}
public Employee() {
super();
}
/**
* 提高工资的5%
*
* @param byPercent
*/
public void raiseSaraly(double byPercent) {
double raise = salary * byPercent / 100; // 提高后的薪水
salary += raise; // 原有的薪水 + 提高后的薪水
}
/**
* 比较两个员工的equals方法
*
* @param other
* @return
*/
public boolean equals(Employee other) {
return name.equals(other.name);
}
public void setId() {
id = nextId;
nextId++;
}
}
4.8静态常量
相比静态变量,静态常量用的比较多些。
package com.eleven.oop;
/**
* 静态常量
*
* @author sywangu
*
*/
public class StaticConstant {
// 有static关键字的叫静态域,反之没有叫实例域
public static final double PI = 3.1415926; // 定义了一个静态常量
public static void main(String[] args) {
// 可以通过StaticConstant类来访问里面的PI
System.out.println(StaticConstant.PI);
}
}
4.9静态方法
- 0.前面有关键字static,就叫静态方法,反之为非静态方法。
- 1.静态方法不能直接向对象实施操作。
- 2.静态方法是没有this参数的方法。(说明不是隐式参数)
- 3.静态方法可以访问自身类中的静态域。
package com.eleven.oop;
/**
* 0.前面有关键字static,就叫静态方法,反之为非静态方法。
* 1.静态方法不能直接向对象实施操作。
* 2.静态方法是没有this参数的方法。(说明不是隐式参数)
* 3.静态方法可以访问自身类中的静态域。
* @author sywangu
*
*/
public class StaticMethod {
public static String getType() {
return "人类";
}
public String getName() {
return "张三";
}
public static void main(String[] args) {
// 01静态方法可以直接使用类名调用
String type = StaticMethod.getType();
System.out.println(type); // 人类
// 02非静态方法需要使用实例对象(StaticMethod)调用
StaticMethod method = new StaticMethod();
String name = method.getName();
String type1 = method.getType(); // 当然getType方法也可以通过对象进行调用
System.out.println("姓名:"+name+",类别:"+type1); // 姓名:张三,类别:人类
}
}
4.10main方法
4.10.1需求
程序包含了 Employee 类的一个简单版本 , 其中有一个静态域 nextId 和一个静态方法 getNextId 这里将 5 个 Employee对象写入数组 , 然后打印雇员信息 。 最后 , 打印出下一个可用的员工标识码来展示静态方法 。
4.10.2实现
package com.eleven.oop;
/**
* 程序包含了 Employee 类的一个简单版本 , 其中有一个静态域 nextId 和一个静态方法 getNextId 这里将 5 个 Employee
* 对象写入数组 , 然后打印雇员信息 。 最后 , 打印出下一个可用的员工标识码来展示静态方法 。
*
* @author sywangu
*
*/
public class StaticTest {
public static void main(String[] args) {
Person[] p = new Person[3];
p[0] = new Person("伊莱文", 5000.0);
p[1] = new Person("Keep", 666.8);
p[2] = new Person("Eleven", 9089.02);
// 打印所有员工的信息
for (Person e : p) {
e.setId();
System.out.println("name=" + e.getName() + ",id=" + e.getId() + ",salary=" + e.getSalary());
}
// 调用静态方法
int n = Person.getNextId();
System.out.println("下一个id为:" + n);
}
}
class Person {
private static int nextId = 1; // 静态域nextId = 1
private int id;
private String name;
private double salary;
// 静态方法
public static int getNextId() {
return nextId; // 返回静态字段
}
public static void setNextId(int nextId) {
Person.nextId = nextId;
}
public int getId() {
return id;
}
public void setId() {
id = nextId; // 将nextId设置给id
nextId++;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Person(String n, double s) {
name = n;
salary = s;
id = 0;
}
// 单元测试
public static void main(String[] args) {
Person p = new Person("伊莱文", 5000.0);
System.out.println(p.getName() + " " + p.getSalary());
}
}
4.11方法参数
**按值调用:**表示方法接收的是调用者提供的值。
**按引用调用:**表示方法接收的是调用者提供的变量地址。
一个方法可以修改传递引用所对应的变量值 , 而不能修改传递值调用所对应的变量值。
Java 程序设计语言总是采用按值调用。 也就是说 , 方法得到的是所有参数值的一个拷贝, 特别是 , 方法不能修改传递给它的任何参数变量的内容。
package com.eleven.oop;
/**
* 方法参数共有两种类型:
* 1.基本数据类型
* 2.对象引用
* 其中:
* 1.一个方法不可能修改一个基本数据类型的参数。
* @author sywangu
*
*/
public class MethodParam {
public static void main(String[] args) {
double percent = 10;
abc(percent); // 10.0
Employee harry = new Employee();
harry = new Employee("伊莱文", 400.0, 1998, 12, 12);
def(harry); // Employee [name=伊莱文, salary=1200.0, hireday=1998-12-12]
}
// 01一个方法不可能修改一个基本数据类型的参数。
public static void abc(double x) {
x = x * 3; // x = 30,当这个方法结束后,参数变量x就不再使用。
}
// 02对象引用作为参数则可以实现"提高工资的50%"
public static void def(Employee e) {
e.raiseSaraly(50);
}
}