方法
public方法
一个class可以包含多个field,但是直接把field用public暴露给外部可能会破坏封装性,造成逻辑混乱,为了避免外部代码直接去访问field,我们可以用private修饰field,拒绝外部访问。
把field从public改成private,外部代码不能访问这些field,所以我们需要使用方法(method)来让外部代码可以间接修改field。
public class MyFirstClass {
public static void main(String[] args){
Person cheng = new Person();//new操作符创建了一个person类型的实例,并通过引用类型的变量cheng指向它
cheng.setName("xiao");
cheng.setAge(18);
System.out.println(cheng.getName()+","+cheng.getAge());
}
}
class Person{
private String name;//外部代码不能直接读取private字段
private int age;//外部代码不能直接修改private字段
public String getName(){//通过getName间接获取private字段的值
return this.name;
}
public void setName(String name){//直接调用方法setName()来间接修改private字段
if(name == null||name.isEmpty())
throw new IllegalArgumentException("name is invalid");//抛出非法数据异常
this.name = name;
}
public int getAge(){
return this.age;
}
public void setAge(int age){//在方法内部,我们有机会检查参数是否正确
if(age<0||age>100)
throw new IllegalArgumentException("age is invalid");
this.age = age;
}
}
综上,一个类通过定义方法,就可以给外部代码暴露一些操作的接口,同时,内部自己保证逻辑一致性。
private方法
和private字段一样,private方法不允许外部调用,定义private方法的作用是内部方法可以调用private方法。
public class MyFirstClass {
public static void main(String[] args){
Person cheng = new Person();
cheng.setBirth(2008);
System.out.println(cheng.getBirth());
}
}
class Person{
private String name;
private int birth;
public void setBirth(int birth){
this.birth = birth;//在方法内部,可以使用一个隐含的变量this,它始终指向当前实例。
//因此,通过this.feild就可以访问当前实例的字段
}
public int getBirth(){
return calcAge(2019);//调用private方法
}
//calcAge()是一个private方法,外部代码无法调用,但是内部方法getBirth()可以调用
private int calcAge(int currentAge){
return currentAge - this.birth;
}
}
可变参数
可变参数用类型...定义,可变参数相当于数组类型:
public class MyFirstClass {
public static void main(String[] args){
//把对象在内存中的地址赋值给引用变量num
Person num = new Person();//这里的num是引用变量,new Person()是实例,也就是对象
//调用时可以这样写
num.setName("cheng","dong","ni");//传入了3个String
}
}
class Person{
private String[] name;
public void setName(String... name){//定义了一个可变参数name
this.name = name;
}
}
参数绑定
基本类型参数绑定
//基本类型参数绑定
public class MyFirstClass {
public static void main(String[] args){
Person cheng = new Person();
int n = 20;
cheng.setAge(20);
System.out.println(cheng.getAge());
n = 18;//修改局部变量n,不影响实例p的age字段
// 原因是setAge()方法获得的参数,复制了n的值,因此p.age和局部变量互不影响
System.out.println(cheng.getAge());
}
}
class Person{
private int age;
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
引用类型参数绑定
//引用类型参数绑定
public class MyFirstClass {
public static void main(String[] args){
Person p = new Person();
String fullname[] = new String[]{"cheng","dong"};
p.setName(fullname);//传入fullname数组
System.out.println(p.getName());
fullname[0] = "ni";//修改fullname数组的第一个值
System.out.println(p.getName());//数值改变
//引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方
}
}
class Person{
private String name[];
public void setName(String name[]){
this.name = name;
}
public String getName(){
return this.name[0]+","+this.name[1];
}
}
//引用类型参数绑定
public class MyFirstClass {
public static void main(String[] args){
Person p = new Person();
String name = "cheng";
p.setName(name);
System.out.println(p.getName());
name = "alice";
System.out.println(p.getName());//两次输出结果都是cheng,因为name的引用指向没有变
}
}
class Person{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
小结
- 方法可以让外部代码安全地访问实例字段
- 方法是一组执行语句,并且可以执行任意逻辑
- 方法内部遇到return时返回,void表示不返回任何值(注意和返回null不同)
- 外部代码通过public方法操作实例,内部代码可以调用private方法
- 理解方法的参数绑定