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にした際はゲッター、セッターを使用してフィールドの値を扱う
广告
将在 10 秒后关闭
bannerAds