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);
}
}