Java基础系列——面向对象之封装与构造(14)

Java基础系列——面向对象之封装与构造(14)

封装

概念

在面向对象编程方法中,封装(英语:Encapsulation)是指,一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。同时,它也是一种防止外界调用端,去访问对象内部实现细节的手段,这个手段是由编程语言本身来提供的。封装被视为是面向对象的四项原则之一。

适当的封装,可以将对象使用接口的程序实现部分隐藏起来,不让用户看到,同时确保用户无法任意更改对象内部的重要数据,若想接触数据只能通过公开接入方法(Publicly accessible methods)的方式( 如:"getters" 和"setters")。它可以让代码更容易理解与维护,也加强了代码的安全性。

解释

在面向对象的语言里,封装往往指以下两个相关联但是独立的概念,有时候这两者是存在因果关系。

  1. 一种编程语言的机制,限制直接访问某些对象的部件。
  2. 一种编程语言的结构体,其将数据和操作该数据的方法绑在一起,提供了便利性。

一些编程语言的研究者和学者将定义①或者定义①+②作为辨认一门语言是否为面向对象语言的标准之一。一些编程语言提供了闭包作为封装,但是这种功能不属于面向对象的范畴。

在许多编程语言里,组件并不会自动隐藏并且能够被重写,因此,一些倾向于定义②的人会将信息隐藏(information hiding)作为一个单独的定义列举出来。

在使用类的大多面向对象的编程语言中,虽然封装是被支持的,但是仍有其他替代品可以选择。

信息隐藏

封装可以隐藏成员变量以及成员函数,对象的内部实现通常被隐藏,并用定义代替。举个例子,仅仅对象自身的方法能够直接接触或者操作这些成员变量。隐藏对象内部信息能供保证一致性,当用户擅自修改内部部件的数据,这可能造成内部状态不一致或者不可用。隐藏对象内部信息能阻止这种后果。一个众所周知的好处是,降低系统的复杂度和提高健壮性。

大多数语言(如:C++、C#、 Delphi、Java)通过设定等级去控制内部信息隐藏,经典的是通过保留字public 暴露信息和 private去隐藏信息。一些语言(如: Smalltalk 和 Ruby )只允许对象去访问隐藏信息。

通常,也是存在方法去暴露隐藏信息,如:通过反射(Ruby、Java、C#、etc.),名字修饰(Python)

示例如下:

public class Employee {
    private BigDecimal salary = new BigDecimal(50000.00);

    public BigDecimal getSalary() {
        return salary;
    }

    public static void main() {
        Employee e = new Employee();
        BigDecimal sal = e.getSalary();
    }
}

封装的实现

根据封装的定义,其实就是将该隐藏的东西(字段或方法)隐藏起来;将该暴露出来的东西(字段或方法)暴露出来。具体的实现是通过使用权限修饰符。

权限修饰父本身有3个,但是具体的访问级别是4个。如下所示:
|修饰符|类内部|同一个包|不同包的子类|同一个工程|
|:————:|:————:|:————:|:————:|:————:|
|private|Yes||||
|(缺省)|Yes|Yes|||
|protected|Yes|Yes|Yes||
|public|Yes|Yes|Yes|Yes|

具体示例:

public class Encapsulation {
	// 成员变量在 实例化(创建类的对象)时会赋予默认值private String name;// 私有属性,只能在本类内部使用
	private int age;
	// 对于私有的属性,我们需要提供访问方法(get) 和 设值方法(set)
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		if(age<0){
			System.out.println("输入正常的一个数吧");
		}else if( age <150){
			this.age = age;
		}else{
			System.out.println("滚蛋");
		}
	}
	/**
	* 访问方法:
	* 1、 是以get为前缀,以属性名为后缀(属性名的第一个字母要变大写)
	* 2、不需要任何参数
	* 3、返回类型与属性的类型一致
	* 4、内部需要返回对应的属性的值
	* 5、按照封装的要求,返回方法被定义成 public*/
	public String getName(){
		return this.name;// 返回 this 的name
	}
	/**
	* 设值方法:
	* 1、 是以set为前缀,以属性名为后缀(属性名的第一个字母要变大写)
	* 2、需要接受一个与属性类型相同的参数
	* 3、不需要任何返回
	* 4、内部将参数传入的值,赋值给对应的属性
	* 5、按照封装的要求,返回方法被定义成 public
	*/
	public void setName(String name){
		this.name = name;// 将参数传入的name 的值 设置到 我(this)的name中
	}
}

构造

构造器(英语: Constructor,有时简称 ctor),别称:构造方法、构造函数、建构子)是一个类里用于创建对象的特殊子程序。它能初始化一个新建的对象,并时常会接受参数用以设定实例变量。

构造器跟一般的实例方法十分相似;但是与其它方法不同,构造器没有返回类型,不会被继承,且不会有范围修饰符。构造器的函数名称一般与它所属的类的名称相同。 它承担着初始化对象数据成员并创建类不变象的任务;在类不变象无效的时候它会失败。一个正确编写的构造器会使它生成的对象保持在一个有效状态。不可变对象必须在构造器内完成所有初始化。

Java语言允许构造器重载 – 一个类被允许拥有多个接受不同参数种类的构造器同时存在。不接收任何参数的构造器被称作“无参数构造器”。在 Java 语言中, 构造是创建对象的重要途径: 即便是工厂模式、 反射等等, 本质上也是依赖于构造的; 默认构造:当没有显式地书写构造时, 系统会自动为类添加一个无参构造;

在Java里,构造器和其他方法的主要差别在于:

  • 构造器不具有任何显性返回类型。
  • 构造器无法被直接“new” invokes them).
  • 构造器无法被标示为synchronized, final, abstract, native, 或者 static。

Java 里的构造器会按照以下顺序完成下列工作:

  1. 将类变量初始到缺省值。(byte, short, int, long, float, 和 double 变量会默认设为它们相应的0值,booleans 会被设为 false, chars 会被设为空字符(“u0000”),对象引用会被设为 null)
  2. 引用父类的构造器,如果没有定义任何构造器。
  3. 将实例变量初始化到指定值。
  4. 执行构造器内的代码。

在 Java 中可以通过关键词 super 访问父类的构造器。

public class Example{
    // Definition of the constructor.
    public Example() {
        this(1);
    }

    // Overloading a constructor
    public Example(int input) {
        data = input; // This is an assignment
    }
    // Declaration of instance variable(s).
    private int data;
}

注意:构造本身是没有返回值的,但是new + 构造 是有返回值的。

  • new 关键字在堆内存中开辟空间
  • 为 指定的对象的各个字段赋予默认值。
  • 执行 构造方法中的代码
  • 将内存中的该对象的首地址返回;通常在前面使用等号进行赋值操作,将首地址赋予某一个具体的变量。
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » Java基础系列——面向对象之封装与构造(14)