博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JavaEE - 05OOP封装

Posted on 2020-11-30 22:40  Kingdomer  阅读(114)  评论(0编辑  收藏  举报

JavaEE - 05OOP封装

(1)面向对象特征之一: 封装与隐藏

(1.1)问题的引入

  • 当我们创建一个类的对象以后,可以通过"对象.属性"的方式,给对象的属性进行赋值。
    • 赋值操作要受属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。
  • 在实际问题中,往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,只能通过方法进行限制条件的添加。
    • 同时,需要避免用户再使用"对象.属性"的方式对属性进行赋值。需要将属性声明为私有的(private)。
  • 此时,针对属性就提现了封装性。

(1.2)封装性概述

  • 为什么需要封装?封装的作用和含义?
    • 给属性添加额外的限制条件
  • 程序设计追求"高内聚,低耦合"。
    • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
    • 低耦合:仅对外暴露少量的方法用于使用。
  • 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。
    • 通俗的说,把该隐藏的隐藏起来,把该暴露的暴露出来。这就是封装性的设计思想。
  • 通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。
    • 面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。
    • 可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程 接口。

> 未对类的属性进行限制前:

public class Animal {
    String name;
    int age;
    int legs;
    public void show(){
        System.out.println("我有"+ legs +"条腿");
    }
}
public class AnimalTest {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.name = "大红";
        a.age = 1;
        a.legs = 4;  
        a.show();  // 我有4条腿

        a.legs = -4;  // -4不合理
        a.show();  // 我有-4条腿
    }
}

> 对类的属性设置限制,添加方法对属性进行设置和获取

public class Animal {
    String name;
    int age;
    private int legs;
    // 对属性的设置
    public void setLegs(int i){
        if(i >= 0 && i%2==0){
            legs = 1;
        }else{
            legs = 0;
        }
    }
    // 对属性的获取
    public int getLegs(){
        return legs;
    }

    public void show(){
        System.out.println("我有"+ legs +"条腿");
    }
}
public class AnimalTest {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.name = "大红";
        a.age = 1;
//        a.legs = 4;   //' legs' has private access in 'Animal'

        a.setLegs(4);
        a.show();   // 我有1条腿
        System.out.println(a.getLegs());  // 1
    }
}

(1.3)封装性的体现

  • 将类的属性xxx私有化(private),同时提供公共的(public)方法来获取(getXxx)和设置(setXxx)属性。
  • 不对外暴露的私有方法
  • 单例模式

 

(2)四种访问权限修饰符

  • 四种权限可以用来修饰类及类的内部结构: 属性、方法、构造器、内部类。
  • Java权限修饰符public、protected、private置于类的成员定义之前,用来限定对象对该类成员的访问权限。
  • 对于class的权限修饰符只可以用public和 default(缺省)。
    • public 类可以在任意地方被访问。
    • default类只可以被同一个包内部的类访问。
修饰符 类内部 同一个包 不同包的子类 同一个工程
private Yes      
缺省 Yes Yes    
protected Yes Yes Yes  
public Yes Yes Yes Yes

 

 

 

 
 
 
 
 
 
> 出了Order类,私有属性和私有方法都不能调用;出了同一包,缺省的就不能访问了
public class OrderTest2 {
    public static void main(String[] args) {
        Order order = new Order();
        // 'orderDefault' is not public in 'com.bearpx.java.Order'.Cannnot be accessed from outside package.
//        order.orderDefault = 111;
        order.orderPublic = 112;
        // 出了Order类之后,私有属性不可以调用了
//        order.orderPrivate = 113;

//        order.methodDefault();
        order.methodPublic();
        //'methodPrivate()' has private access in 'Order'
//        order.methodPrivate();
    }
}

 

(3)类的成员之三: 构造器(构造方法)

(3.1)构造器特征

  • 它具有与类相同的名称
  • 它不声明返回值类型。(与声明为void不同)
  • 不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值。

(3.2)构造器作用

  • 构造器作用: 
    • 创建对象。 new + 构造器  Person p = new Person();  
    • 给对象进行初始化                   Person p = new Person("Peter",15);
  • 如果没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器。
  • 定义构造器的格式: 权限修饰符 类名(形参列表) {}  
  • 一个类中定义的多个构造器,彼此构成重载
  • 一旦我们显示的定义了类的构造器之后,系统就不再提供默认的空参构造器

(3.3)属性赋值的先后顺序

先后顺序:  默认初始化 显示初始化  构造器中赋值  通过"对象.方法" 或"对象.方法"的方式赋值

public class User {
    String name;
    int age = 1;

    public User(){
    }
    public User(int a){
        age = a;
    }
    public void setAge(int a){
        age = a;
    }
}
public class UserTest {
    public static void main(String[] args) {
        User u = new User();
        System.out.println(u.age); //1

        User u1 = new User(2);
        System.out.println(u1.age); //2
        u1.setAge(3);
        System.out.println(u1.age); //3
    }
}

 

 

(4)拓展知识

(4.1)JavaBean

  • JavaBean是一种Java语言写成的可重用组件
  • 所谓JavaBean, 是指符合以下标准的Java类:
    • 类是公共的
    • 有一个无参的公共的构造器
    • 有属性,且有对应的get、set方法
  • 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创建的对象进行打包,
    • 并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。
  • 用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

(4.2)UML类图

  • + 表示 public 类型, - 表示private类型, #表示 protected类型
  • 方法的写法: 方法的类型(+、-) 方法名(参数名: 参数类型) : 返回值
  • 方法有下划线 表示为构造器 

 

(5)关键字: this

  • this表示当前对象,可以调用类的属性、方法和构造器 
    • 它在方法内部使用,即 这个方法所属对象的引用;
    • 它在构造器内部使用,表示该构造器正在初始化的对象。
  • 什么时候使用this关键字?
    • 当在方法内部需要用到调用该方法的对象时,就用this。
    • 具体的:方法的形参和类的属性同名时,用this来区分局部变量和属性。 比如: this.name = name;  构造器同理。
    • 在类的方法中,使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。通常,省略"this."。
  • this调用构造器
    • 在类的构造器中,可以显式的使用"this(形参列表)"方法,调用本类中指定的其他构造器
public class User {
    private String name;
    private int age = 1;

    public User(){

    }
    public User(int age){
        this.age = age;
    }

    public void setAge(int age){
        this.age = age;
    }
    
    public void eat(){
        System.out.println("人吃饭");
        this.study();
    }
    public void study(){
        System.out.println("学习");
    }
}

 

    public User(int age){
        this.age = age;
    }
    
    public User(String name, int age){
        this(age);   
        this.name = name;
//        this.age = age;  // 初始化时,可以抽象的共同的代码, 使用this(age)先一步处理。
    }
    
 

(6)关键字: package、import

(6.1)package关键字

  • 为了更好的实现项目中类的管理,提供包的概念。
  • 使用package声明类或接口所属的包,声明在源文件的首行。
  • 包,属于标识符,遵循标识符的命名规则、规范,"见名知意"
  • 每"." 一次,就代表一层文件目录。
  • 同一包下,不能命名同名的接口、类;不同的包下,可以命名同名的接口、类。

 

(6.2)import关键字
  • 在源文件中显式的使用import结构导入指定包下的类、接口
  • 声明在包的声明和类的声明之间
  • 如果需要导入多个结构,则并列写出即可。
  • 使用"xxx.*"的方式,表示可以导入xxx包下的所有结构
  • 如果使用的类或接口是java.lang包下定义的类或接口,可以省略import结构
  • 如果使用的类或接口是本包下定义的,可以省略import结构
  • 如果源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
  • 使用"xxx.*"方式声明可以调用xxx包下的所有结构。但是如果使用的是xxx子包下的结构,仍需要显式导入。
  • import static : 导入指定类或接口中的静态结构。