静态方法
我们可以使用一个对象来调用静态方法,但是比较容易造成混淆,建议直接用类名来调用一个静态方法,而不是用对象来调用静态方法。
在下面两种境况下使用静态方法:
- 一个方法不需要访问对象状态,其所需要的参数都是通过显示参数提供(例如Math.pow)
- 一个方法只需要访问类的静态域(例如:Employee.getNextId)。
工厂方法
静态方法还有一类常见的用法就是使用静态工厂方法(factory method)来构造对象。例如工厂方法LocalDate.now和LocalDate.of.NumberFormat类使用的下面的方法产生不同风格的格式化对象:
NumberFormat currencyInstance = NumberFormat.getCurrencyInstance();
NumberFormat percentInstance = NumberFormat.getPercentInstance();
double x = 0.1;
System.out.println(currencyInstance.format(x));
System.out.println(percentInstance.format(x));
代码运行结果如下:
为什么NumberFormatter类不利用构造器来完成这些操作呢?
原因有2点:
- 无法命名构造器。构造器的名字必须与类相同。但是,这里希望得到的货币实例和百分比实例采用不同的名字。
- 当使用构造器时候,无法改变所构造的对象类型。而fatory方法将返回一个DecimalFormat类对象,这是NumberFormat的子类。
Main方法
main方法不对任何对象进行操作,事实上,在启动程序时候还没有任何一个对象。静态的main方法将执行并创建程序所需要的对象。每一个类可以有一个main方法,这是一个常用语对类进行单元测试的技巧。
main方法可以直接用来做单元测试,测试一个小方法逻辑是否有问题,例如demo3:
package corejava.chapter4;
/**
* @Auther WangYu
* @Date 2022/3/5
* 静态main方法可以用来做单元测试
*/
public class EmployeeB {
public static int nextId = 1;
private String name;
private double salary;
private int id;
public EmployeeB(String name, double salary, int id) {
this.name = name;
this.salary = salary;
this.id = id;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getId() {
return id;
}
public void setId(int id) {
id = nextId;
nextId++;
}
public static int getNextId() {
return nextId;
}
public static void main(String[] args) {
EmployeeB employeeB = new EmployeeB("Harry", 50000, 2);
System.out.println(employeeB.getName() + "" + employeeB.getSalary());
}
}
静态方法测试:
package corejava.chapter4;
/**
* @Auther WangYu
* @Date 2022/3/5
* 静态方式测试demo
*/
public class StaticTest {
public static void main(String[] args) {
// fill the staff array with three Employee objects
EmployeeB[] staff = new EmployeeB[3];
staff[0] = new EmployeeB("卧龙", 50000, 11);
staff[1] = new EmployeeB("凤雏", 40000, 22);
staff[2] = new EmployeeB("刘备", 60000, 33);
//print all staff information about all objects
for (EmployeeB employeeB : staff){
System.out.println("name = " + employeeB.getName() + ",salary = " + employeeB.getSalary() + ", id = " + employeeB.getId() );
int n = EmployeeB.getNextId();
System.out.println(" next available id = " + n);
}
}
}
方法参数
程序设计语言中有关将参数传递给方法或者函数的有两种途径,一种是按照引用调用,一种是按照方法名调用。java语言中参数的调用途径总是按照值调用,也就是是说,方法得到的所有参数值只是一份拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
java语言对独享采用的不是引用调用,实际上,对象引用是通过值传递的方式进行的。
小结:
- 一个方法不能修改一个基本数据类型的参数(即数值型或者布尔型)
- 一个方法可以改变一个对象参数的状态
- 一个方法不能让对象参数引用一个新的对象
可变参数与值传递的测试demo4:
package corejava.chapter4;
/**
* @Auther WangYu
* @Date 2022/3/5
* java中参数调用是值调用
*/
public class ParamTest {
public static void main(String[] args) {
/**
* test1: method can't modify numeric parameters
*/
System.out.println("test tripleValue:");
double percent = 10;
System.out.println("before: percent = " + percent);
tripleValue(percent);
System.out.println("after: percent = " + percent);
/**
* test2: method can change the state of object parameters
*/
System.out.println("test tripleSalary:");
EmployeeB xiaoMing = new EmployeeB("小明", 20000, 2);
System.out.println("before: salary = " + xiaoMing.getSalary());
tripleSalary(xiaoMing);
System.out.println("after: salary = " + xiaoMing.getSalary());
System.out.println("\n test swap:");
EmployeeB xiaoHong = new EmployeeB("小红", 30000, 3);
EmployeeB xiaoLv = new EmployeeB("小绿", 30000, 3);
System.out.println("before: xiaoHong =" + xiaoHong.getName());
System.out.println("before: xiaoLv =" + xiaoLv.getName());
swap(xiaoHong, xiaoLv);
System.out.println("after: xiaoHong =" + xiaoHong.getName());
System.out.println("after: xiaoLv =" + xiaoLv.getName());
}
public static void tripleValue(double x) {
x = x * 3;
System.out.println("end of method : x = " + x);
}
public static void tripleSalary(EmployeeB x) {
x.raiseSalary(200);
System.out.println("end of method , x= " + x);
}
public static void swap(EmployeeB x, EmployeeB y) {
EmployeeB temp = x;
x = y;
y = temp;
System.out.println(" end of method: x = " + x.getName());
System.out.println(" end of method: y = " + y.getName());
}
}