java的封装



什么是封装

封装需要分为两部分理解:

1. 将对象的状态信息隐藏在内部,不允许外部程序直接访问
2. 通过公开的方法让外部实现对内部信息的访问和操作

之所以要这样做,是因为在公开的方法里,程序员可以设计程序逻辑,阻止外界的非法访问,让访问可以控制在有效的范围内



访问控制符

java是通过访问控制符来实现封装。
java有4个访问控制级别,它们的权限从小到大依次为private、default、protected、public。提供了3个访问控制符:private、protected、public。如果什么都不写,就是default权限。

访问控制级别介绍

  1. private(当前类内部访问权限):private表明是私有的,private可以修饰成员变量、方法、构造器、内部类等,表明这些私有成员只能在当前类的内部访问private不能修饰类,因为这是一个与类内部成员有关的访问修饰符,类的访问修饰符只有默认的default和public两种。private一般用于修饰成员变量,表明类变量或者实例变量是类或对象的私有状态。private修饰构造器是比较少见的用法,表明不允许外部直接用该构造器创建对象,比如单例类。private也会用于修饰一些工具方法,这些方法只是为内部的其他方法服务,不希望被外界公开使用
  2. default(包访问权限):如果没有访问控制符,那就表明是default权限(默认权限),default可以用于修饰类、成员变量、方法、构造器等,如果修饰类或对象的成员,就表明这些成员可以被同一个包里的任意类访问,如果修饰外部类本身,就表明同一个包的其他类可以访问这个类。
  3. protected(子类访问权限)protected可以修饰成员变量、方法、构造器等它的权限在包权限的基础上,增加了不同包的子类内部可以访问,注意:是子类的内部能访问,不可以用子类的对象访问父类的protected修饰的方法。protected的作用就是和继承相关,protected修饰方法表明,希望子类重写父类的方法。protected修饰构造器表明,希望子类调用父类的构造器又不想外界直接使用父类的构造器。protected修饰成员变量表明,希望子类可以继承父类的成员变量,但不希望其他包直接访问父类的成员变量。protected不能修饰类,因为protected是希望子类能访问父类内部的成员,与类本身没有关系。
  4. public(公共访问权限):public等于没有限制,public可以修饰成员变量、方法、构造器、类,表明这些成员或者类本身可以在任何地方被访问。

访问控制符和局部变量无关,因为局部变量只在方法内部有效,不需要访问控制符限制。

访问修饰符针对的是类,而不是对象。比如一个类的方法的形参包含自身类型的参数,这样就可能发生a对象的方法传入了b对象的实参,但是a对象的方法内部允许直接访问b对象的私有变量。
举例:

public class Employee {
    private String name;

    public Employee(String name) {
        this.name = name;
    }

    public boolean equals(Employee other) {
        // 如果2个员工对象名字相同,就返回true,否则返回false
        return name.equals(other.name);
    }

    public static void main(String[] args) {
        var one = new Employee("Cauchy");
        var two = new Employee("Cauchy");
        var boss = new Employee("Lin");
        System.out.println(one.equals(two));
        // 这里one对象的equals方法直接访问了boss的私有实例变量name
        System.out.println(one.equals(boss));
    }
}

这件事咋看起来有点奇怪,但并不危险,因为这些代码都是在类的内部定义的,是同一个开发者完成的类的设计。开发者自身不会在自身设计的方法内部进行不合法的访问。
访问修饰符真正防止的是,另一个使用类的人员做非法访问和修改。

private与static无关,private的含义就是在类的内部有效。static的方法内部可以创建一个自身类的对象,然后直接访问该对象的私有实例变量。因为static的方法在类的内部,在类的内部就可以直接访问private修饰的成员变量。
举例:

public class Student {
    private String name;

    public static void main(String[] args) {
    	// 类自身的静态方法可以直接创建自身类的对象,再通过点运算符直接为私有变量赋值
        Student s1 = new Student();
        s1.name = "Cauchy";
    }
}

public与文件名关系

java有一条规定,如果某个java文件里有public修饰的类,那么java文件名必须和这个类的类名相同。如果某个java文件里没有一个public修饰的类,那它的文件名可以任意取,只要文件名合法。
而且,一个java文件只能有一个public类。可以有很多个不是public的类,但public的类只能有一个。

但在实际开发中,一般一个文件里面只有一个类,只需要让文件名和类名相同即可。

setter和getter方法

因为类的成员变量通常需要封装,也就是设置为private权限,所以需要与之相关的setter和getter方法,这些公开的读取和写入的方法,可以按照设计者的意图,给外界提供可控的访问

我们一般的命名规则为set+成员变量名(变量名首字母大写),比如age这个实例变量的setter和getter方法为:setAge方法和getAge方法

这样做和直接公开成员变量访问权限的区别是,方法内部可以通过代码设计访问的逻辑,让成员变量的访问是可控制的

访问控制符的使用规则

规则如下

  1. 除了一些类似全局变量的静态常来那个(很少使用),绝大部分成员变量都要用private修饰,保证类或对象的状态信息不对外界公开。一些只为类内部的其他方法调用的工具方法,应该用private修饰
  2. 如果类里的方法只希望被子类重写,不希望被其他包直接调用,应该用protected修饰。
  3. 希望暴露出来给外界使用的方法,应该使用public修饰。
  4. 有的类希望只能通过静态方法创建对象,比如单例类。它的构造器应该设置为private。

封装的好处

把成员变量设置为私有,同时提供公开的setter和getter方法,这看起来会更麻烦,但却带来了很多好处:

  1. 可以把数据的读取和修改控制在合理的范围内
    将成员变量隐藏后,外界没办法直接察觉到成员变量的存在,不能随心所欲的随意访问和修改它们。而公开的访问器方法和修改器方法本身可以设计程序逻辑,让成员变量的访问和修改变得可控。
  2. 可以在类的内部修改成员变量的组成,只要对外公布的部分不发生改变
    比如private String name; 名字这个成员变量非常常见,如果改成private String firstName; 和 private String lastName; 虽然改变了内部成员变量的组成,但只要public String getName() {方法体省略} 这个公开的访问器方法的返回值不变,外界根本察觉不到内部的变化。原本方法体内是return name; 只需要改成return firstName + lastName; 对外界来说,根本没区别。

隐晦的破坏封装的方法

并不是给成员变量设置为private,再提供公开的getter和setter方法就算完成封装了。

如果成员变量是可变对象的引用,提供该引用的访问器方法,就可能破坏封装。
private只能保证引用变量的值是私有的。但是只要提供公开的访问器方法,即使没有提供公开的修改器方法,也可以得到引用指向的可变对象的索引。
只要外界可以得到可变对象的索引,也就可以通过这个索引改变可变对象内部的数据。
即使把这个成员变量设置为final也没用,因为final只能限制引用本身一旦初始化就不被修改,但是我们可以通过引用来改变可变对象内部的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值