Java封装是什么?
什么是封装?
限制对类的字段和方法的访问的功能。
其作用是防止字段和方法被用于意外的用途。
//例:フィールドに文字列のname、整数のmoneyを持つUserクラス
public class User {
String name;
int money;
public User(String name, int money) {
this.name = name;
this.money = money;
}
}
User类的实例的name和money可以随意更改。
public class Main {
public static void main(String[] args) {
User user = new User("鈴木太郎", 100);
System.out.println(user.name + "の所持金は" + user.money + "円");
//空白の名前にされてしまうことや
user.name = "";
//金額がマイナスにされてしまう可能性がある
user.money = -1000;
System.out.println(user.name + "の所持金は" + user.money + "円");
}
}
执行结果
鈴木太郎の所持金は100円
の所持金は-1000円
封装方法
为了封装,需要将不希望其他类修改的字段和方法的访问修饰符设为私有。
通过这样做可以防止其他班级对其进行更改。
设定私有字段和公共方法是常用的做法。
//例:Userクラスをカプセル化
public class User {
private String name;
private int money;
public User(String name, int money) {
this.name = name;
this.money = money;
}
}
私有字段的访问方式
将字段设置为私有后,其他类将无法获取和修改该字段的值。
public class User {
//このままだとインスタンスのname, moneyが変更できない
private String name;
private int money;
public User(String name, int money) {
this.name = name;
this.money = money;
}
}
在这种情况下,通过在类中定义用于获取和修改字段值的方法,可以安全地从类外部获取和修改字段的值。
用于获取字段值的方法称为getter,用于修改字段值的方法称为setter。
获取器的定义方式
通常情况下,Getter方法的命名方式是“get字段名”。它返回字段的值作为返回值。
//例:Userクラスにname、moneyのゲッターを追加
public class User {
private String name;
private int money;
public User(String name, int money) {
this.name = name;
this.money = money;
}
//nameのゲッター
public String getName() {
return this.name;
}
//moneyのゲッター
public int getMoney() {
return this.money;
}
}
//ゲッターを使ってnameとmoneyを取得
public class Main {
public static void main(String[] args) {
User user = new User("鈴木太郎", 100);
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
}
}
执行结果
鈴木太郎の所持金は100円
拦网手的定义方法
一般来说,Setter方法的命名通常是按照「set字段名」的方式进行的。
这些方法将接收到的参数值赋给相应的字段。
//例:Userクラスにname、moneyのセッターを追加
public class User {
private String name;
private int money;
public User(String name, int money) {
this.name = name;
this.money = money;
}
//nameのゲッター
public String getName() {
return this.name;
}
//nameのセッター
public void setName(String name) {
this.name = name;
}
//moneyのゲッター
public int getMoney() {
return this.money;
}
//moneyのセッター
public void setMoney(int money) {
this.money = money;
}
}
public class Main {
public static void main(String[] args) {
User user = new User("鈴木太郎", 100);
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
user.setName("佐藤太郎");
user.setMoney(500);
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
}
}
执行结果
鈴木太郎の所持金は100円
佐藤太郎の所持金は500円
使用Getter、Setter的好处
可能会认为使用Getter和Setter可以访问和修改私有字段,所以与公有字段没有区别。但是,使用Getter和Setter有以下优点。
1. 可以将字段设置为只读或者只写
只需定义getter而不定义setter的字段将变为只读,可以防止从其他类中进行修改,同时可以使用该字段的值。
而且,对于字段只定义了setter方法,而没有定义getter方法的话,此字段就变成了只读的。(然而,这种用法并不常见)
//例:Userクラスのmoneyのセッターを無効にしてmoneyを読み取り専用にする
public class User {
private String name;
private int money;
public User(String name, int money) {
this.name = name;
this.money = money;
}
//nameのゲッター
public String getName() {
return this.name;
}
//nameのセッター
public void setName(String name) {
this.name = name;
}
//moneyのゲッター
public int getMoney() {
return this.money;
}
//moneyのセッターが無ければ
//他のクラスからmoneyが変更されるのを防げる
//
// public void setMoney(int money) {
// this.money = money;
// }
}
2. 更改字段名称不会影响其他类。
当在后期更改字段名称时,如果没有使用getter和setter,就需要修改所有使用该字段的类的代码。
然而,如果使用了getter和setter,只需修改getter和setter方法内的代码即可解决。
//例:UserクラスのnameをuserNameに変更してもメインメソッドは変更不要
public class Main {
public static void main(String[] args) {
User user = new User("鈴木太郎", 100);
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
user.setName("佐藤太郎");
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
}
}
public class User {
private String userName; //name -> userNameに変更
private int money;
public User(String userName, int money) {
this.userName = userName;
this.money = money;
}
//userNameのゲッター
public String getName() {
return this.userName;
}
//userNameのセッター
public void setName(String userName) {
this.userName = userName;
}
//メインメソッドにuserNameという変数が登場しないのでコード変更不要
public class Main {
public static void main(String[] args) {
User user = new User("鈴木太郎", 100);
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
user.setName("佐藤太郎");
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
}
}
执行结果
鈴木太郎の所持金は100円
佐藤太郎の所持金は100円
在修改字段值之前,可以进行值的检查。
通过在setter方法中添加检查参数值的代码,可以防止字段的值被更改为意外的值。
在修改User类的userName之前,检查字符数是否合适。
//userNameのセッター
//引数の文字列が3文字以上10文字以内ならuserNameを変更
public void setName(String userName) {
if (userName.length() < 3) {
System.out.println("名前が短過ぎます");
} else if (userName.length() > 11) {
System.out.println("名前が長過ぎます");
} else {
this.userName = userName;
System.out.println("名前を「" + this.userName + "」に変更しました");
}
}
public class Main {
public static void main(String[] args) {
User user = new User("鈴木太郎", 100);
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
user.setName("鈴木");
user.setName("俺の名前は鈴木太郎!!");
user.setName("佐藤太郎");
System.out.println(user.getName() + "の所持金は" + user.getMoney() + "円");
}
}
执行结果
鈴木太郎の所持金は100円
名前が短過ぎます
名前が長過ぎます
名前を「佐藤太郎」に変更しました
佐藤太郎の所持金は100円
概括一下
-
- カプセル化とはクラスのフィールドやインスタンスの使用を制限する機能
-
- 外部のクラスから想定外のフィールドの書き込みやメソッドの使用を防ぐことができる
-
- フィールドはprivate、メソッドはpublicにするのが定石
- フィールドをprivateにした際はゲッター、セッターを使用してフィールドの値を扱う