Java面向对象之——封装

news2024/12/23 23:45:23

文章目录

  • 前言
  • 一、封装的概念
  • 二、何为封装?
  • 三、封装拓展——包
    • 🍑1、包的概念
    • 🍑2、导入包中的类
    • 🍑3、自定义包
    • 🍑4、常见的包
  • 四、访问限定符
    • 🍑1、public修饰符
    • 🍑2、private修饰符
    • 🍑3、默认修饰符(缺省)
    • 🍑4、protected修饰符
  • 五、再谈封装
  • 六、static成员
    • 🍑1、再谈学生类——static的引入
    • 🍑2、static修饰成员变量
    • 🍑3、static修饰成员方法
    • 🍑4、静态方法特性
    • 🍑5、static成员变量初始化
  • 七、代码块
    • 🍑1、代码块概念以及分类
    • 🍑2、普通代码块
    • 🍑3、非静态代码块
    • 🍑4、静态代码块
    • 🍑5、执行顺序
  • 八、对象的打印
  • 九、拓展:不学后悔的IDEA技巧
    • 🍑1、快速生成构造方法
    • 🍑2、快速生成Setter和Getter接口方法
    • 🍑3、快速生成重写
  • 总结


前言

我们知道Java是一门面向对象的语言,对于面向对象的程序有三大特性:封装、继承、多态。我们上期了解了类和对象,在类和对象阶段,主要研究的就是封装特性。

一、封装的概念

举个例子:我要看电视,只需要按一下开关和换台就可以了。有必要了解电视机内部的结构吗?有必要碰碰显像管吗?制造厂家为了方便我们使用电视,把复杂的内部细节全部封装起来,只给我们暴露简单的接口。让用户可以与电视机进行交互即可。


二、何为封装?

何为封装呢?简单来说就是套壳屏蔽细节。封装的理念是高内聚、低耦合。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合是仅暴露少量的方法给外部使用,尽量方便外部调用。

要了解封装就需要了解访问权限,要了解访问权限需要了解包,那么下面我们就先来讲一下——Java包


三、封装拓展——包

🍑1、包的概念

在面向对象体系中,提出了一个软件包的概念,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。包(package)相当于文件夹对于文件的作用。用于管理类、用于解决类的重命名问题。

🍑2、导入包中的类

Java 中已经提供了很多现成的类供我们使用。例如Date类:可以使用 java.util.Date; 表示导入 java.util 这个包中的 Date类。Arrays类:可以使用import java.util.Arrays;表示导入java.ulil这个包中的Arrays类。

📝方式1:写全路径导入

public class Test3 {
    public static void main(String[] args) {
        java.util.Date date=new java.util.Date();
    }
}

虽然这样也可以导入,但是这种写法比较冗余,不建议。
📝方式2:使用import导入

import java.util.Date;
public class Test3 {
    public static void main(String[] args) {
        Date date=new Date();
    }
}

📝方式3:使用 import 包路径. * 导入包中的其他类,
需要注意的是:这种导入方式不是将包中的所有类都导入进来,而是需要谁就导入谁。

import java.util.*;
public class Test3 {
    public static void main(String[] args) {
        Date date = new Date();
    }
}

虽然这样也可以导入包中的类,但是我们更建议显式的指定要导入的类名,指定类名可以使导入类更清楚明确。

当我们这样导入,也可能出现冲突的情况。如:java.util包和java.sql包下都有Date类,如果我们使用这种导入方式,会导致编译器不知道应该从哪个包中导入Date类,将会报错。

📝方式4:使用import static导入包中静态的方法和字段。
这种导入方式了解即可,不建议使用。

import static java.lang.Math.*;
public class Test3 {
    public static void main(String[] args) {
        double x = 30;
        double y = 40;

// double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        //省略类名Math
        double result = sqrt(pow(x, 2) + pow(y, 2));
        System.out.println(result);
    }
}

🍑3、自定义包

基本规则

  • 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  • 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.zijie.demo1 ).
  • 包名要和代码路径相匹配. 例如创建 com.zijie.demo1 的包, 那么会存在一个对应的路径 com/zijie/demo1 来存储代码.
  • 如果一个类没有 package 语句, 则该类被放到一个默认包中.

注: 如果在源文件中没有定义包,那么类、接口、枚举和注释类型文件将会被放进一个无名的包中,也称为默认包。学了包之后,写项目时都要加包,尽量不要使用默认包!

下面就演示一下在IDEA中创建包:



🍑4、常见的包

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包。(集合类等) 非常重要
  6. java.io:I/O编程开发包。

四、访问限定符

Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:

注解:

  1. protected主要是用在继承中,继承部分详细介绍
  2. default权限指:什么都不写时的默认权限
  3. 访问权限除了可以限定类中成员的可见性,也可以控制类的可见性

目前来说,我们就先介绍public、private、默认修饰符:

🍑1、public修饰符

public修饰的成员在哪里都能访问,它的权限是四种修饰符中最大的。这里就不过多展示了。

🍑2、private修饰符

🍑3、默认修饰符(缺省)

🍑4、protected修饰符

------------------ (继承部分讲解)------------------


五、再谈封装

上面提到:封装是对类细节的隐藏,提供公开接口来进行和数据的交互。通过搭配上述的修饰符这一特点体现的更为明显。
📝如:对学生类使用private进行封装

class Student {
    //属性
    private String name;
    private int age;
    //方法
    public void show() {
        System.out.println("姓名:"+name+" 年龄:"+age);
    }

    //构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //交互接口
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

public class Test2 {
    public static void main(String[] args) {
        Student student =new Student("张三",20);
        student.show();

        student.setName("李四");
        student.setAge(18);
        System.out.println(student.getName());
        System.out.println(student.getAge());
    }
}


通过这个例子,我们或许可以看到到封装在类中的体现,通过使用private对Student中成员进行隐藏,在提供一些对外的接口如,setName、getName等实现对外的交互。如需要对封装的成员进行操作,调用接口方法即可。


六、static成员

🍑1、再谈学生类——static的引入

学生有属性:姓名,年龄,身高,体重……这里仅以姓名年龄属性举例:

class Student {
    //属性
    public String name;
    public int age;

    //构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Test2 {
    public static void main(String[] args) {
        Student student1=new Student("张三",17);
        Student student2=new Student("李四",18);
        Student student3=new Student("王五",19);
    }
}

现在假设这三个同学是来自于同一个班级的,那么我们能否加一个普通成员变量来统一保存学生的班级信息呢?答案显然是不行的。为了实现这种功能,于是引出了static关键字。

之前在Student类中定义的成员变量,每个对象中都会包含一份(称之为实例变量),因为需要使用这些信息来描述具体的学生。而现在要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享。在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。

🍑2、static修饰成员变量

static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。

学习了static关键字之后我们可将成员变量分为:

1、静态成员变量(类变量)
2、非静态成员变量(普通成员变量)

我们再回到之前的问题,现在我们想要统一保存学生的班级信息只需要添加一个static修饰的成员变量即可:

class Student {
    //属性
    public String name;
    public int age;
    public static String classRome="软件1班";  
    //构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Test2 {
    public static void main(String[] args) {
        Student student1=new Student("张三",17);
        Student student2=new Student("李四",18);
        Student student3=new Student("王五",19);
        //使用类和对象都可以访问static修饰的成员变量
        System.out.println(Student.classRome);
        System.out.println(student1.classRome);
    }
}

此时我么再次调试:


结合代码功能、运行和调试足以说明【静态成员变量】具有以下特性:

  1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
  2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
  3. 类变量存储在方法区当中
  4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)


🍑3、static修饰成员方法

一般类中的数据成员都设置为private,而成员方法设置为public,那设置之后,Student类中classRoom属性如何在类外访问呢?这里就引出了静态方法。Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的。

学习了static关键字之后我们将成员方法分为:

1、静态成员方法(类方法)
2、非静态成员方法(普通成员方法)

class Student {
    //属性
    private String name;
    private int age;
    private static String classRome="软件1班";
    
    public static String getClassRome() {
        return classRome;
    }

    public static void setClassRome(String classRome) {
        Student.classRome = classRome;
    }
}

public class Test2 {
    //使用静态方法访问静态变量
    public static void main(String[] args) {
        System.out.println(Student.getClassRome());
        Student.setClassRome("软件2班");
        System.out.println(Student.getClassRome());
    }
}

🍑4、静态方法特性

  1. 不属于某个具体的对象,是类方法
  2. 可以通过对象调用,也可以通过类名。静态方法名(…)方式调用,更推荐使用后者。
  3. 不能在静态方法中直接访问任何非静态成员变量,无法传递this引用。
class Student {
   public int age;
}

public class Test2 {
    //在静态方法中不能直接访问非静态方法
    public static void main(String[] args) {
        //System.out.println(this.age);//不能使用this引用
    }
}
  1. 静态方法中不能直接调用任何非静态方法,因为非静态方法有this参数,在静态方法中无法传递this引用。
class Student {
    public void test() {
        System.out.println("test()");
    }
}
public class Test2 {
    //在静态方法中不能直接访问非静态方法
    public static void main(String[] args) {
//        Student.test();//错误
        //在静态方法中访问非静态方法只能new对象
          Student stu1=new Student();
          stu1.test();
    }
}
  1. 普通成员方法内部是可以使用静态的成员方法和成员变量的。
class Student {
   private static int age=10;
   private static String name="张三";
   
   private static void print() {
       System.out.println("test()");
   }
   
   public void test() {//这样写是可以的,不会报错
       Student.age=10;
       Student.name="李四";
       Student.print();
   }
}

🍑5、static成员变量初始化

(1)默认初始化

class Student {
   public static int age;//默认赋值为0
   public static String name;//默认赋值为null
}

同普通成员变量,如果静态成员变量创建时不赋初值,将被赋默认值。赋默认值规则同普通成员变量。

(2)就地初始化

class Student {
   public static int age=10;
   public static String name="张三";
}

像上面这种,在定义时直接给出初始值的赋值方式为就地初始化。

(3)使用构造方法初始化

class Student {
   public static int age;
   public static String name;

   public Student(int a,String n) {
       age=a;
       name=n;
   }
}

虽然使用构造方法也可以给静态变量赋值,但是静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性,而静态变量是所有对象共享的,每次new对象时都把static变量改了是不合适的。
(4)使用Setter方法

class Student {
   public static int age;
   public static String name;
   
   public static void setAge(int age) {
       Student.age = age;
   }

   public static void setName(String name) {
       Student.name = name;
   }

(5)使用静态代码块初始化
静态代码块是什么?我们接着往下看


七、代码块

🍑1、代码块概念以及分类

使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:普通代码块构造块静态块同步代码块(后续讲解多线程部分再谈)

🍑2、普通代码块

普通代码块,是指定义在方法中的代码块。

//这是一个main方法
    public static void main(String[] args) {
        { //直接使用{}定义,普通方法块
            int x = 10;
            System.out.println("x1 = " + x);
        }
    }

🍑3、非静态代码块

非静态代码块也叫实例代码块、构造块,是定义在类中的代码块(不加修饰符)。构造代码块一般用于初始化非静态实例成员变量。

class Student {
   public int age;
   public String name;

    //构造代码块,实例化成员变量
   {
       age=10;
       name="李四";
   }
    public void show() {
        System.out.println("年龄:"+age+" 姓名:"+name);
    }
}
public class Test2 {
    public static void main(String[] args) {
        Student student1=new Student();
        student1.show();
	}
}

补充:

  1. 如果都是非静态的,那么定义顺序谁在后最后赋值结果就是哪个值。
  2. 可以简单认为,编译器编译好代码之后会把非静态代码块的东西放到构造方法的最前面。

🍑4、静态代码块

使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。

class Student {
    private String name;
    private String gender;
    private static String classRoom;

    // 静态代码块
    static {
        classRoom = "软件1班";
        System.out.println("I am static init()!");
    }

    public static void main(String[] args) {
        //静态代码块的加载不依赖于对象
        System.out.println(Student.classRoom);
        //静态代码块只执行1次
        Student s1 = new Student();
        Student s2 = new Student();
    }
}

注意事项:

  1. 静态代码块不管生成多少个对象,其只会执行一次
  2. 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
  3. 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
  4. 实例代码块只有在创建对象时才会执行

🍑5、执行顺序

1. 静态代码块先执行,并且只执行一次,在类加载阶段执行。
2. 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后执行构造方法。

class Demo {
    public String name;
    public int age;
    //构造方法
    public Demo(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("构造方法执行");
    }
    //实例代码块
    {
        System.out.println("实例代码块执行");
    }
    //静态代码块
    static {
        System.out.println("静态代码块执行");
    }
}

public class Test {
    public static void main(String[] args) {
        Demo demo=new Demo("张三",20);
        System.out.println("===========分隔线===========");
        Demo demo2=new Demo("李四",18);
    }
}


八、对象的打印

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        Student student=new Student("张三",18);
        System.out.println(student);
    }
}

当我们使用println打印时,如果直接将student引用作为参数传入println(student),我们能得到引用指向对象中的属性值吗?答案是不能的。我们将得到如下图的数值:

如果想要println默认打印对象中的属性该如何处理呢?答案:重写toString方法即可。也就是说对于你想输出一个对象的引用的值的时候,如果你没有自己写一个toString方法,那么就会调用Object这个类的方法,如果自己实现了,就调用自己的:

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

	//String方法重写
    @Override//这个是注解,注解有很多种,这只是其中1种
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", gender='" + age + '\'' +
                '}';
    }
    
    public static void main(String[] args) {
        Student student=new Student("张三",18);
        System.out.println(student);
    }
}

补充:对于上述提到的,方法重写以及Object的相关知识后期博客会详细介绍。


九、拓展:不学后悔的IDEA技巧

🍑1、快速生成构造方法

🍑2、快速生成Setter和Getter接口方法

🍑3、快速生成重写

IDEA中也有一个快速重写toString的技巧

其实使用IDEA还可以实现很多便捷的操作,大家可以在使用中慢慢摸索。


总结

本期主要探讨了面向对象三大特性之一的封装,重点介绍了Java包的概念、引入了静态属性static、详细介绍了Java中的三种代码块、最后拓展了一下IDEA中的小技巧,本章篇幅较长,笔者尽量做到句句重点,如有不足,敬请斧正。我们下期再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/30901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件产品确认测试包括哪些方面

1.技术方面 确认测试又称有效性测试,是在模拟的环境下,运用黑盒测试的方法,验证被测软件是否满足需求规格说明书列出的需求。 确认测试的目的是向未来的用户表明系统能够像预定要求那样工作。经集成测试后,已经按照设计把所有的模…

Docker 下 jitsi-meet 视频服务器 安装部署

一、参考网站 官网文档地址:Self-Hosting Guide - Docker | Jitsi Meet 二、Docker 版本 三、安装部署 3.1、下载并解压缩安装包 地址:Release stable-8044: release jitsi/docker-jitsi-meet GitHub CSDN地址:docker-jitsi-meet-stab…

visdom安装及使用

目录1. 安装visdom的流程2. 使用流程1. 安装visdom的流程 重点参考链接:visdom安装出现Downloading scripts, this may take a little while然后就不动了 先去到github直接下载了visdom的压缩包:https://github.com/fossasia/visdom然后将visdom-maste…

第七章 数学 6 AcWing 1593. 整数分解

第七章 数学 6 AcWing 1593. 整数分解 原题链接 AcWing 1593. 整数分解 算法标签 数学 数论 DP 背包问题 思路 类似AcWing 12. 背包问题求具体方案 把n看成背包的容积N 因为n最多不超过400,然而p进制最少为2 所以物品的价值最大可以取到20(因为20^2 400) 所以…

Python读取CSV文件,数值精度丢失

Excel保存为csv以后,大数值的列,会把转换为科学计数法,而且后边几位都会被转为0. 搞了很多方法,最后直接安装 openpyxl 组件 和 pandas, 读取Excel文件就行了。 data pd.read_excel("C:/work/20221111AI/cleaned_data_noTi…

第二章 计算机算术

数据表示决定了计算机所执行操作的类型,数据从一个位置传到另一个位置的方法, 以及对存储元件的特性要求。浮点运算是非常重要的,因为它的实现决定了计算机执行复杂图形变换和图像处理的速度, 而且浮点运算对计算的准确度也有很重…

高通平台开发系列讲解(mm-camera篇)MM-CAMERA框架

文章目录 一、Camera软件位置1.1、开源代码1.2、专有源码二、摄像头前端(Camera Frontend)2.1、整体框架2.2、 Camera HAL与mm-camera交互沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要介绍高通平台mm-camera代码框架。 一、Camera软件位置 QTI 针对 An…

Flink 状态编程

状态编程有状态算子状态的管理状态的分类按键分区状态(Keyed State)支持的结构类型代码实现状态生存时间(TTL)算子状态(Operator State)基本概念和特点状态类型代码实现广播状态(Broadcast Stat…

DFP 数据转发协议应用实例 .与其它厂商 LoRA 设备匹配

DFP 数据转发协议应用实例 5.与其它厂商 LoRA 设备匹配 DFP 是什么? 稳控科技编写的一套数据转发规则, 取自“自由转发协议 FFP(Free Forward Protocol)” ,或者 DFP(DoubleF Protocol)&#xf…

【优化求解】粒子群算法求解仓库成本控制优化问题【含Matlab源码 1577期】

⛄一、粒子群算法简介 1 引言 自然界中的鸟群和鱼群的群体行为一直是科学家的研究兴趣所在。生物学家Craig Reynolds在1987年提出了一个非常有影响的鸟群聚集模型,在他的仿真中,每一个个体都遵循:避免与邻域个体相撞:匹配邻域个体…

基于JAVA的网上图书商城参考【数据库设计、源码、开题报告】

数据库脚本下载地址: https://download.csdn.net/download/itrjxxs_com/86427643 主要使用技术 Struts2HibernateJSPCSSJSMysql 功能介绍 系统有五类用户,分别是:会员用户,商品管理员,订单管理员,会员管…

【MSSQL】SQL SERVER导入中文乱码问题解决

公司最近承接了一个项目,甲方现使用旧版SiteServer框架(以下简称“SiteCMS”)作为门户网站,使用的数据源是SQL Server。 现在需要对SiteCMS进行升级,在升级时数据库和数据库结构也需要同时更新,其中数据库…

硬件顶配、数字先行,路特斯重塑「智能座舱」

诚然,在车联网的高度普及、5G技术的铺开以及汽车产业融合的大势下,传统单一驾驶与乘坐功能的汽车座舱正在被颠覆,更高级、更智能的“智能座舱”应运而生。 从行业发展态势来看,大屏多屏已经是智能汽车的基本操作,智能…

【网络安全】——逻辑漏洞之短信轰炸漏洞

作者名:Demo不是emo 主页面链接:主页传送门创作初心:舞台再大,你不上台,永远是观众,没人会关心你努不努力,摔的痛不痛,他们只会看你最后站在什么位置,然后羡慕或鄙夷座右…

程序的环境

文章目录[TOC](文章目录)前言一、程序环境分类二、翻译环境1.总体流程2.编译2.1预编译2.2编译2.3汇编3.链接三、运行环境总结前言 我们平时在编译器上编写代码,然后运行代码,最后得到程序的运行结果。这让我们不经好奇:程序在电脑中到底经过…

Java常用设计模式

前言 设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF)的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分别为创建型模式、结构型模式和行为型模…

物联网漏洞利用整体情况

物联网 威胁分析漏洞篇物联网威胁分析—漏洞篇 引言 本章将从漏洞利用角度对物联网威胁进行分析。首先,我们分析了 NVD和 Exploit-DB中的物联网 年度漏洞及利用 1 变化趋势;之后统计了绿盟威胁捕获系统捕获到的物联网漏洞利用的整体情况;最…

【算法笔记(五)】排序算法

算法笔记(五) 排序算法算法笔记(五)前言一、冒泡排序1.什么是冒泡排序2.实际需求3.代码实现二、选择排序1.什么是选择排序2.需求规则三.插入排序1.了解插入排序2.需求规则3.代码实现四.希尔排序1.什么是希尔排序2.需求规则3.代码实现五.快速排序1.什么是快速排序2.需求规则3.代…

静态代理和动态代理

静态代理和动态代理代理模式代理模式的主要优缺点:优点:缺点:代理模式的编写要点静态代理实现步骤静态代理方式的弊端动态代理:动态代理的实现步骤:代理模式 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的…

Javascript 基础知识学习

Javascript 基础知识学习 参考自:https://www.w3cschool.cn/javascript/ javascript 简介 JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。 JavaScri…