Java如何实现封装和包

 更新时间:2026年01月08日 09:31:39   作者:苏小瀚  
文章主要介绍了Java中的封装、访问修饰符、封装的好处、封装的步骤、包的概念、导入包、自定义包、常用的包、static关键字及其用法、代码块、对象的打印等内容

1. 什么是封装

封装就是对类里面的成员变量和成员方法进行隐藏,只能在所在类的范围内使用,只留下一些可以被外部访问的方法,供外部调用,隐藏方法实现的内部细节。

这就好比一台电视机,给你提供了一个遥控器供你使用,进行一系列操作,但是操作的内部细节你看不到,只是通过遥控器来实现功能。

2. 访问修饰符

Java当中是通过类和访问权限来实现封装的,类可以实现数据和封装的数据存储在一起,而访问修饰符则可以设置数据的访问权限。

访问权限范围有四个:private ,默认的, protected , public 。只有三个访问修饰符它们的访问权限也是不一样的。如图所示:

private修饰的属性和方法只能在类内部使用,不能在类外部直接使用。

3. 封装的好处

1.可以隐藏类内部的实现细节。

2.可以保证安全和合理,比如说要对属性设置值,可以在封装的类里面先判断设置的值是否合理,再考虑是否赋值。

4. 封装的步骤

1.对属性和方法进行私有化(只能在类里面使用,不能直接修改值)

2. 设置public的set方法实现对私有的属性的初始化。

3. 设置public的get方法获取成员变量的值。

举个Student类的例子:

class Student{
    private String name;
    private int age;
    private String stuNum;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

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

上面就是设置的两个公共方法一个设置成员变量的值,一个返回成员变量的值。

但是每个成员变量都要写过于麻烦,因此idea提供一种快捷方法,可以直接生成这两个方法:

1.鼠标在类内部右击找到下面的选项:

2. 找到下面选项: 

3. 把需要生成的成员变量选上,ok。 

这样就实现了间接访问成员变量。

但是为什么把属性设置成了私有还可以被外部间接访问呢?

因为,封装的属性和方法是为类内部的其他方法提供的,而设置的一些公共类的方法就可以被外部所访问,而这个方法又可以使用封装的属性和方法,这样既隐藏了封装的方法的内部细节,又可以通过公共方法给外部间接使用。

5. 包

5.1 什么是包

包本质上是对类的一种管理形式,包里面包含了很多的类,也就是说包相当于是一个文件夹,里面存放了很多的.Java文件,一个.Java文件对应一个类。

5.2 导入包中的类

这里我们可以用到import关键字进行导入包,也成为打包。例如:

import java.util.Arrays;

java.util就是包的名字,而Arrays就是类名。

当然我们也可以不导入包直接在代码中使用,如下:

        int[] a = new int[]{6,4,2,1};
        java.util.Arrays.sort(a);
        System.out.println(java.util.Arrays.toString(a));

但是这样书写太麻烦了,但是当两个包里面有相同名字的类都被使用的时候就需要这样去写。

当然还有一种写法是: *叫做通配符

import java.util.*;

不同的包里面可以有相同的类名,这两个类只是名字相同,但是作用不相同。 

这种方法可以导入包里面的全部类,但是不建议这样书写。因为有可能在两个包里面会有相同名字的类,这样书写就会导致冲突,编译器会报错。

在java.util包里面有一个Date的类,在java.sql包里面也有一个Date的类,如果书写成如下格式就会报错:

因为这样的话,在代码中使用时,编译器无法识别是哪一个包下面的类,所以遇到这种情况,只能用import导入一个类,另一个类则需要在使用的时候进行导入。如图:

import java.util.Date;

Date date = new Date();
java.sql.Date date1 = new java.sql.Date(10);

5.3 自定义包

在src文件下创建一个包:

包的命必须是字母,数字,点号,下划线,数字不能开头,不能包含关键字,一般都为小写。

一般公司命名是以 com.公司名.项目名.模块名 来命名的。

回车后就创建好了一个包:

 com是一级目录,abc是二级目录,www是三级目录。Test1是类。

Test1类里面代码如下:

package com.abc.www;

public class Test1 {
    public void test1() {
        System.out.println("haha");
    }
}

package是编译器自己生成的,为了声明该类在那个包里面。

下面我自己编写了一段代码。

如果要在其他类中调用自定义包里面的方法,就是如下图:

import com.abc.www.Test1;

public class Test {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.test1();
    }
}

这样就可以调用了,com.abc.www是包名,Test1是类名,test1是类里面的方法。

5.4 常用的包

  • java.lang    lang是基本包,默认引入的,不需要再导入。
  • java.util      系统提供的工具包,包含工具类。
  • java.net      网络开发用的。
  • java.awt   做Java的页面开发的。

6. static关键字

static是用来修饰成员的,被static修饰的成员叫做静态成员,也叫做类成员,表示该成员不属于任何一个对象的,而是所有对象共同包含成员。被static修饰的成员都存储在方法区中,我用下面的代码帮助大家理解:

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

    public Student(String name, int age, String stuNum) {
        this.name = name;
        this.age = age;
        this.stuNum = stuNum;
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("张三",18,"202311");
        Student student2 = new Student("李四",19,"202312");
    }
}

此时学生1和学生2这两个对象都在同一个班级,那么班级属性是两个对象都一样的,就可以被static修饰。

6.1 static修饰成员变量

当static修饰完成员变量后,该成员变量就属于类的变量,而不是方法的变量,此时该静态变量就不会在根据类的定义在堆区申请的对象的内存空间中了,而是在方法区中了。

如下图所示关系:

此时我们如何访问静态变量呢?

有两种方式:

Student student1 = new Student("张三",18,"202311");
//通过对象的引用来访问
student1.classNum = "1班";
//通过类名访问
Student.classNum = "1班";

第一种是通过对象的引用来访问,但是不建议使用,因为静态变量不在对象申请的内存中,在方法区中,属于类的变量。

第二种是通过类名.静态方法来访问。

注意:

  • 静态变量的访问不依赖于对象,不需要实例化对象,就可以直接访问。
  • 类变量存储在方法区中。
  • 类变量的生命周期是整个类的生命周期。
  • 静态变量是所有对象共享的,不存在于某个对象的空间里。

6.2 static修饰成员方法

static修饰成员方法后,成员方法变成静态成员方法,静态成员变量的访问不依赖于对象,属于类方法,存在于方法区,有两种访问方式:

class Student {
    public String name = "张三";
    public int age = 18;
    public String sex = "男";
    public static void print() {
        System.out.println("hehe");
    }
}
public class Test1 {
    public static void main(String[] args) {
        //方法一
        Student student = new Student();
        student.print();
        //方法二
        Student.print();
    }
}

方法一:是通过对象来访问,这种方法虽然不会报错,但是不建议使用,因为静态方法属于类方法,不依赖于对象。

方法二:直接通过类名访问,这种方法建议使用。

注意:

  • 静态方法里面不能使用this关键字,因为this关键字依赖于对象,而静态方法的访问不依赖于对象。
  • 静态方法不能直接访问非静态方法和非静态变量,但可以通过对象的实例化间接访问。
  • 非静态方法可以直接访问静态方法和静态变量,非静态方法依赖于对象,静态方法和静态变量不依赖于对象。
  • 不同类间访问静态方法或静态变量,通过类名.方法名或变量名访问。
  • 不同类间访问非静态方法或非静态变量,对象实例化后,通过对象来访问。
  • static不能修饰局部变量。

6.3 Static修饰成员变量初始化

静态成员方法初始化方法有四种:

  1. 通过就地初始化,也就是直接初始化值。
  2. 通过set方法初始化。
  3. 通过构造方法初始化。
  4. 通过静态代码块初始化

7. 代码块

代码块是指被{}包含的内容,一般情况下是用来对成员变量进行初始化的。分为三种:

7.1 普通代码块

这是定义在方法内的代码块:

    public static void main(String[] args) {
        //普通代码块
        {
            int a = 10;
            System.out.println(a);
        }
    }

7.2 构造代码块

定义在类里面的代码块,也叫做实例代码块。用来初始化非静态成员变量的,在实例化对象的时候执行:

class Student {
    public String name = "张三";
    public int age = 18;
    public static String sex = "男";
    //实例代码块
    {
        name = "李四";
        age = 20;
    }
}

7.3 静态代码块

定义在类里面的代码块,用来初始化静态成员变量的,在类加载的时候执行:

class Student {
    public String name = "张三";
    public int age = 18;
    public static String sex = "男";
    //静态代码块
    static {
        sex = "女";
    }
}

静态代码块只能初始化静态成员变量。因为非静态对象初始化依赖于对象。 

7.4 各种初始化

我们已经知道了 用构造方法来初始化成员变量,还有就地初始化成员变量,还有代码块初始化成员变量,代码块又分为静态代码块和实例代码块。

那它们的执行先后顺序又是怎样的呢?

  • 多个静态代码块或者多个实例代码块同时初始化,则是按照代码的先后顺序初始化。
  • 静态代码块是在类加载时执行的,而构造方法和实例初始化则是在实例化对象时执行的,所以静态代码块先执行,如果有静态变量就地初始化,会按照先后顺序进行执行,而实例初始化比构造方法先执行。
  • 一般成员变量的定义和初始化先写,在写其他的代码块或者方法。

执行顺序为:就地初始化->静态代码块->实例代码块->构造方法。

如果实例化多个对象时,由于类只会在第一次实例化对象时加载一次,也就是说静态代码块只执行一次,第二次实例化对象时,不执行静态代码块,只执行实例代码块和构造方法。

8. 对象的打印

如果想打印对象的属性也就是成员变量有什么快捷方式吗?

这里idea提供了一种快捷方式,生成toString方法来进行打印,相当于println方法调用valueof方法,valueof方法调用toString方法。:

class Student {
    public String name = "张三";
    public int age = 18;
    public String sex = "男";
    //打印成员变量的方法:
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

public class Test1 {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student);
    }
}

打印结果如下:

这样就可以实现快速打印对象的属性。

如果不写toString方法,默认打印的是地址。当然这种快捷方式不能生成静态成员变量。 

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java实现贪吃蛇大作战小游戏的示例代码

    Java实现贪吃蛇大作战小游戏的示例代码

    本文主要介绍了Java实现贪吃蛇大作战小游戏的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Springboot中spring-boot-starter-quartz的使用及说明

    Springboot中spring-boot-starter-quartz的使用及说明

    这篇文章主要介绍了Springboot中spring-boot-starter-quartz的使用及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • JAVA编程实现随机生成指定长度的密码功能【大小写和数字组合】

    JAVA编程实现随机生成指定长度的密码功能【大小写和数字组合】

    这篇文章主要介绍了JAVA编程实现随机生成指定长度的密码功能,可生成带有大小写和数字组合的随机字符串,需要的朋友可以参考下
    2017-07-07
  • Java中@RequiredArgsConstructor使用详解

    Java中@RequiredArgsConstructor使用详解

    这篇文章主要介绍了Java中@RequiredArgsConstructor使用的相关资料,@RequiredArgsConstructor是Lombok库提供的一个注解,用于自动生成一个包含所有final字段和非空字段的构造函数,需要的朋友可以参考下
    2025-05-05
  • Java操作IO对象流进行数据的读写

    Java操作IO对象流进行数据的读写

    这篇文章主要介绍了Java操作IO对象流进行数据的读写,本文通过例子逐步介绍了java如何操作IO流,和文字解析,需要的朋友可以参考下
    2021-07-07
  • Sprin中Bean的顺序使用及说明

    Sprin中Bean的顺序使用及说明

    这篇文章主要介绍了Sprin中Bean的顺序使用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • springboot增加注解缓存@Cacheable的实现

    springboot增加注解缓存@Cacheable的实现

    这篇文章主要介绍了springboot增加注解缓存@Cacheable的实现,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Springboot集成SSE实现单工通信消息推送流程详解

    Springboot集成SSE实现单工通信消息推送流程详解

    SSE简单的来说就是服务器主动向前端推送数据的一种技术,它是单向的,也就是说前端是不能向服务器发送数据的。SSE适用于消息推送,监控等只需要服务器推送数据的场景中,下面是使用Spring Boot来实现一个简单的模拟向前端推动进度数据,前端页面接受后展示进度条
    2022-11-11
  • MyBatis-Plus拦截器实现数据权限控制的方法

    MyBatis-Plus拦截器实现数据权限控制的方法

    MyBatis-Plus是一款基于MyBatis的增强工具,它提供了一些便捷的功能和增强的查询能力,数据权限控制是在系统中对用户访问数据进行限制的一种机制,这篇文章主要给大家介绍了关于MyBatis-Plus拦截器实现数据权限控制的相关资料,需要的朋友可以参考下
    2024-01-01
  • 详解Java9新特性中的模块化与反射机制

    详解Java9新特性中的模块化与反射机制

    Java9中的一个重大变化就是引入了模块化系统,这个系统使得Java应用程序的构建、发布和部署更加具有可控性和可重用性,与此同时,Java9还改进了反射机制,让它与模块化系统更好地配合,本文通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-06-06

最新评论