Java基础知识篇02——封装

打印 上一主题 下一主题

主题 866|帖子 866|积分 2600

各人好,我是白夜,今天给各人聊聊面向对象的三大特征——封装
一、包(package)

1.1、包的引入

先来看看我们之前写的代码结构

以上代码存在的问题

  • 全部类写在一个目录下面,非常难管理,因为以后项目不大概只有这么几个类,当类数量很大的时候,就不轻易管理了。
  • 不能写同名但是差别需求的类。
为了解决这些问题,我们必要把差别的东西放到专门的里面,进行分类管理。也就是通过文件夹进行管理,Java 中的文件夹就是
1.2、定义包

包命名规范:一般是公司域名反写.项目名.模块名字.子模块名;
要求:包名是全英文小写。
例如 : itsource.cn 域名
package  cn.itsource.erp.oa.domain; 主动化办公
package  cn.itsource.erp.sa.entity; 系统管理
  1. package cn.itsource.packagedemo;// 声明包
  2. /**
  3. * 包package
  4. */
  5. public class PackageDemo {
  6.         public static void main(String[] args) {
  7.                 new java.util.Date();
  8.                 new java.sql.Date(1L);
  9.                 System.out.println();
  10.         }
  11. }
复制代码
1.3、导入包

当我们必要使用别人大概 JDK 中的类的时候,就必要告知 JVM 从什么地方去加载这个类,这个过程就是导包
其实本质是导入包中的类。
导入包的语法 :
​         import 包名.子包名.类名
注意:

  • 导入包的代码应该在声明包(就是该类所在的包)的后面,声明类的前面。
  • import java.util;  表示导入本包中全部会使用到的 util 包中的类,只会导入 util 包下面直接的类型,不包括util 包的子包中的类型。
  • java.lang是核心包,下面的直接类型是主动导入的;
    例如:String、System类,lang 包的子包中的类型不会主动导入,必要手动导入。
  • 在一个类中会用到同名差别包的时候必须使用全限定路径
    例如:同时使用 java.util.Date 和 java.sql.Date
  1. package cn.itsource.packagedemo;//声明包
  2. import java.util.*;// 只会导入util包下使用到的类
  3. /**
  4. * 包package
  5. */
  6. public class PackageDemo {
  7.         public static void main(String[] args) {// String是java.lang核心包下的,程序会自动导入;
  8.                 // 使用Arrays类中的toString方法
  9. //                String str = java.util.Arrays.toString(new int[]{1, 2, 3});// 每次都写全限定类名比较麻烦
  10.                
  11.                 // 使用Arrays类中的sort方法排序
  12. //                java.util.Arrays.sort(new int[]{3, 2, 1});
  13.                
  14.                 // 用自动导包可以简化上面代码
  15.                 String str = Arrays.toString(new int[]{1, 2, 3});// 每次都写全限定类名比较麻烦
  16.                 System.out.println(str);
  17.                 Arrays.sort(new int[]{3, 2, 1});
  18.                
  19.                 // 当使用同名不同包的多个类怎么用? 必须用全限定类名
  20.                 new java.util.Date();// java.util包下
  21.                 new java.sql.Date(1L);// java.sql包下
  22.         }
  23. }
复制代码
1.4、Java中常用的包(了解)

java/ javax(java 增强包)
java.lang (java 的核心包--基本包) 帮我们主动导包的
java.util(java 的工具包 --聚集框架 ArrayList LinkedList)
java.io(java IO包input-output 读写文件)
java.net (网络编程)
java.awt/javax.swing(java的图形化界面)
java.math 数学相关的包
java.sql  数据库相关的包
java.text 是文本格式化相关的包
java.time 时间相关的包
二、封装

2.1、为什么要封装

来看下面一个案例
  1. package cn.itsource.potting1;
  2. /**
  3. *        账户Account类
  4. *        封装引入
  5. */
  6. public class Account {
  7.         /** String类型成员变量姓名name */
  8.         protected String name;
  9.        
  10.         /** String类型成员变量密码pwd */
  11.         String pwd;
  12.        
  13.         /** double类型成员变量余额money */
  14.         double money;
  15.        
  16.         /** boolean类型成员变量是否是vip用户 */
  17.         boolean vip;
  18.        
  19.         /**
  20.          * Account类无参构造
  21.          */
  22.         public Account() {}
  23.        
  24.         /**
  25.          * 有4个参数构造方法
  26.          * @param n
  27.          * @param p
  28.          * @param m
  29.          * @param v
  30.          */
  31.         public Account(String n, String p, double m, boolean v) {
  32.                 name = n;// 将局部变量n赋值给成员变量name
  33.                 pwd = p;// 将局部变量p赋值给成员变量pwd
  34.                 money = m;// 将局部变量m赋值给成员变量money
  35.                 vip = v;// 将局部变量v赋值给成员变量vip
  36.         }
  37.        
  38.         /**
  39.          * 获取当前成员变量money的值
  40.          * @return
  41.          */
  42.         public double getMoney() {
  43.                 return money;
  44.         }
  45. }
  46. 测试类:
  47. package cn.itsource.potting1;
  48. /**
  49. *        Account测试类
  50. *        封装的引入
  51. */
  52. public class AccountTest {
  53.         public static void main(String[] args) {
  54.                 // 创建Account对象,调用无参构造
  55.                 Account acc1 = new Account();
  56.                 // 给acc1成员变量赋值
  57.                 acc1.name = "某菲";
  58.                 acc1.pwd = "6969";
  59.                 acc1.money = 1.0;
  60.                 acc1.vip = false;
  61.                 // 打印acc1成员变量的值
  62.                 System.out.println(acc1.name);
  63.                 System.out.println(acc1.pwd);
  64.                 System.out.println(acc1.money);
  65.                 System.out.println(acc1.vip);
  66.                 // acc1调用getMoney方法
  67.                 double money = acc1.getMoney();// 因为getMoney方法是非static修饰,并且有返回值,所以用acc1调用,用double变量接收
  68.                 System.out.println(money);
  69.                
  70.                 // 需求:当money达到50000.00的时候,会将vip升级为true。现在,能不能没有达到5万就不能升级。
  71.                 acc1.vip = true;// 这里没有经过任何权限判断,直接修改了值,不安全。所以,用封装解决这个问题。
  72.                 System.out.println(acc1.vip);// true               
  73.         }
  74. }
复制代码
而在 Java 中是通过封装来完成保护内部成员的目标
2.2、封装的作用

封装是为了保护内部数据的安全:

  • 不盼望在外部类中随意访问类中的成员变量
  • 达到权限要求的才能访问。
  • 只是获取数据的时候。例如:单例模式。
  • 我们在程序设计的时候就追求“高内聚、低耦合”:


  • 高内聚:类的内部数据操纵细节自己完成,不允许外部干涉;
  • 低耦合:仅对外部袒露少量的方法用于使用。
2.3、封装的使用


  • 如何控制程序中的访问 ?
    通过给类中的成员(字段,方法,构造方法)添加访问权限修饰符来实现封装(访问控制)。
  • 什么是访问权限:简单的认为访问权限就是差别级别的人能够干差别级别的事,差别级别的人能看到的页面是差别的。
    例子:好比做一个系统,差别人登录进去的访问权限不一样;
  • 访问权限修饰符:
    public      最大权限,被其修饰的成员,在任意目录下,都可以访问到 (全部类)
    protected  在同包类和子类中都可以访问
    默认不写    只能在同包类中访问
    private     只能在当前类中访问

  • 封装的步骤:

    • 将类的属性设置为 private,这样外部就不能直接访问。
    • 提供公共的 getter 方法用于获取属性值,通常是 public 的。
    • 提供公共的 setter 方法用于设置属性值,也是 public 的,并可以在此中添加逻辑检查。
    • 提供一个无参构造,有参构造根据需求确定是否要写。
    • 该类用 public 修饰。
    1. public class Account {// 5. 该类用 public 修饰
    2.         //1. 私有化成员变量(用 private 修饰成员变量)
    3.         private String name;
    4.        
    5.         private String pwd;
    6.        
    7.         // 4. 提供一个无参构造
    8.         public Account() {}
    9.        
    10.         // 有参构造根据实际需求,决定是否要写
    11.         public Account(String n, String p) {
    12.                 name = n;// 将局部变量赋值给成员变量
    13.                 pwd = p;       
    14.         }
    15.        
    16.         /**
    17.          *  2. 为每一个成员变量提供合理的 public void setName(String n) 方法
    18.          *         给成员变量name赋值方法
    19.          * @param n
    20.          */
    21.         public void setName(String n) {
    22.                 // 可以写判断条件
    23.                 name = n;// 将局部变量n赋值给成员变量 name
    24.         }
    25.                
    26.         public void setPwd(String p) { pwd = p; }
    27.        
    28.         /**
    29.          * 2. 为每一个成员变量提供合理的        public String getName() 方法
    30.          * 获取成员变量 name 的值
    31.          * @return
    32.          */
    33.         public String getName() {
    34.                 // 可以写判断条件
    35.                 return name;// 直接返回成员变量 name
    36.         }
    37.        
    38.         public String getPwd() { return pwd; }       
    39. }
    复制代码
    1. /**
    2. *        Account 测试类
    3. *        封装的引入
    4. */
    5. public class AccountTest {
    6.         public static void main(String[] args) {
    7.                 // 创建Account对象,调用无参构造
    8.                 // Account acc1 = new Account();
    9.                 // 给 acc1 成员变量赋值
    10.                 /*
    11.                  * 因为 private 修饰成员变量后,不能在其他类中使用了。
    12.                 acc1.name = "小七";
    13.                 acc1.pwd = "6969";
    14.                 */
    15.                 // 使用有参构造赋值
    16.                 Account acc1 = new Account("小七", "6969");
    17.                
    18.                 // 打印acc1成员变量的值
    19. //                System.out.println(acc1.name);// 因为 private 修饰成员变量后,不能在其他类中使用了。
    20. //                System.out.println(acc1.pwd);
    21.                
    22.                 // 因为封装了,所以只能调用:public 返回值 getXxx() 获取成员变量的值
    23.                 String name = acc1.getName();// acc1 调用 getName 方法获取成员变量 name 的值
    24.                 String pwd = acc1.getPwd();// acc1 调用 getPwd 方法获取成员变量 pwd 的值
    25.                 // 打印上面获取的值
    26.                 System.out.println(name);
    27.                 System.out.println(pwd);
    28.                
    29.                 // 当需要修改创建好的对象的成员变量值,用 set 方法赋值
    30.                 acc1.name("小八");       
    31.                 String name2 = acc1.getName();
    32.                 System.out.println(money2);               
    33.         }
    34. }
    复制代码
    2.4、 封装的注意事项


    • 不是只有 private 才叫封装,private 只是最大限度的封装而已。
    • get 和 set 方法都是只能获取大概赋值一个成员变量,**不能 **set(String n, double m, boolean v) 赋值3个成员变量。
    • 单一职能原则:功能最小化,不要想着一个方法写完全部的功能,因为代码复用率高。
    2.5、封装的好处


    • 增强安全性:隐藏数据和方法的实现细节,防止外部直接访问,降低因错误使用而导致的风险。
    • 提高复用性:封装后的代码更轻易被其他程序或模块复用,因为它们的实现细节对于使用者来说是透明的。
    • 便于维护:封装使得代码修改时影响范围局限,提高了代码的可维护性。

三、this关键字

this 的概念:
​        this 指代当前对象,即,哪个对象调用就指代哪个对象
3.1、this 的使用

1.   解决局部变量和成员变量的二义性【set 方法和有参构造中形参跟成员变量同名差别义】
  1. public Account(String name,String pwd) {
  2.         // 要解决二义性问题,就需要用到this,加上this,就会直接从成员变量位置找name
  3.         this.name = name;
  4.         this.pwd = pwd;
  5. }
复制代码
1.   本类中构造方法之间的相互调用,但是必须是构造方法内的第一句。
  1. package cn.itsource.task.topic02;
  2. public class People {
  3.     private String name;
  4.     private boolean sex;
  5.     private int age;
  6.     private int weight;
  7.     public People(){
  8.     }
  9.     public People(String name, boolean sex, int age, int weight){
  10.         this(name, sex, age);
  11.         this.weight = weight;
  12.     }
  13.     public People(String name, boolean sex, int age){
  14.         this(name, sex);
  15.         this.age = age;
  16.     }
  17.     public People(String name, boolean sex){
  18.         this(name);
  19.         this.sex = sex;
  20.     }
  21.     public People(String name){
  22.         this.name = name;
  23.     }
  24.     public String getName() { return name; }
  25.     public void setName(String name) { this.name = name; }
  26.     public boolean isSex() { return sex; }
  27.     public void setSex(boolean sex) { this.sex = sex; }
  28.     public int getAge() { return age; }
  29.     public void setAge(int age) { this.age = age; }
  30.     public int getWeight() { return weight; }
  31.     public void setWeight(int weight) { this.weight = weight; }
  32. }
复制代码
四、构造方法和set方法的区别



  • 构造方法可以为多个成员变量赋值,set只能对一个进行赋值;
  • 构造方法由JVM主动调用,set必要手动调用;
  • 构造方法针对同一个对象只能调用一次,set方法针对同一个对象可以调用多次;
  • 构造方法用于给变量赋值,set可以给变量赋值大概修改值;
  • 构造可以使代码更加轻便,set方法灵活性更高。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用多少眼泪才能让你相信

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表