首页 > 其他分享 >封装

封装

时间:2024-08-01 10:06:40浏览次数:7  
标签:Java 变量 成员 访问 封装 方法 public

封装

1.封装的定义

在Java中,封装(Encapsulation)是面向对象编程(OOP)的四大基本特性之一(其他三个是继承、多态和抽象)。封装是一种将对象的属性(成员变量)和方法(成员函数)结合在一起,并隐藏对象的属性和实现细节,仅对外公开接口(即方法)来与对象进行交互的机制。

封装的目的主要有两个:

  1. 保护内部状态:通过封装,可以隐藏类的内部实现细节,使得外部无法直接访问对象的内部属性,从而保护对象的状态不被随意修改,保证对象数据的完整性和安全性。
  2. 提高模块间的独立性:通过封装,可以将类的内部实现与外界隔离,降低类之间的耦合度,使得各个模块之间相对独立,便于后续的维护和扩展。

在Java中实现封装,通常遵循以下原则:

  • 将类的属性私有化:通过将类的属性(成员变量)声明为private,可以限制外部代码对这些属性的直接访问。
  • 提供公共的访问方法:为私有属性提供公共的getter和setter方法(也称为访问器和修改器),以便外部代码通过这些方法来访问和修改对象的私有属性。
  • 在getter和setter方法中实现业务逻辑:可以在getter和setter方法中添加额外的逻辑来限制对属性的访问或修改,比如输入验证、日志记录等。
  • 使用final关键字限制修改:如果某个属性在创建对象后不应该被修改,可以将其声明为final,并在构造器中初始化。

下面是一个简单的封装示例:

public class Person {  
    // 私有属性  
    private String name;  
    private int age;  
  
    // 公共的构造器  
    public Person(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    // 公共的getter方法  
    public String getName() {  
        return name;  
    }  
  
    // 公共的setter方法  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    // 另一个公共的getter方法  
    public int getAge() {  
        return age;  
    }  
  
    // 另一个公共的setter方法,这里还可以添加验证逻辑  
    public void setAge(int age) {  
        if (age > 0 && age < 150) {  
            this.age = age;  
        } else {  
            System.out.println("Invalid age!");  
        }  
    }  
}

在这个例子中,Person类的nameage属性被声明为private,这意味着它们只能在Person类内部被访问和修改。外部代码需要通过getName()setName()getAge()setAge()这些公共方法来访问和修改这些属性。通过这种方式,Person类的内部实现被封装起来,外部代码无法直接访问其属性,只能通过提供的方法来进行交互。

2.访问修饰符

Java中的访问修饰符主要用于控制类、属性、方法和构造器等程序元素的访问级别,确保程序的封装性、安全性和可维护性。Java中有四种访问修饰符:privatedefault(也称为包访问权限)、protectedpublic

1. private

  • 定义private修饰符表示“私有的”,被private修饰的成员(属性、方法、内部类等)只能被其所在的类内部访问,外部类无法直接访问。
  • 使用场景:通常用于隐藏类的内部实现细节,防止外部直接访问或修改类的私有成员,确保类的封装性。

2. default(包访问权限)

  • 定义:当类、属性、方法或构造器没有显式地指定访问修饰符时,它们就具有默认的访问权限,即包访问权限。这意味着这些成员可以被同一个包中的其他类访问,但不能被其他包中的类访问。
  • 使用场景:在包内部实现类之间的紧密协作,同时限制外部包对类内部细节的访问。

3. protected

  • 定义protected修饰符表示“受保护的”,被protected修饰的成员可以被同一个包中的类访问,也可以被不同包中的子类访问。
  • 使用场景:当需要允许子类访问并可能重写父类的某些成员时,可以使用protected修饰符。这有助于实现继承和多态性。

4. public

  • 定义public修饰符表示“公开的”,被public修饰的成员可以被任何类访问,无论它们是否位于同一个包中。
  • 使用场景:当需要公开类的某些接口或方法给其他类使用时,可以使用public修饰符。这是实现接口和实现跨包协作的基础。

注意事项

  • 外部类(即顶级类)只能被publicdefault(无修饰符)修饰。
  • 访问修饰符不能修饰接口中的成员,因为接口中的成员默认就是public的。
  • 在使用访问修饰符时,应根据实际需要选择合适的修饰符,以确保程序的封装性、安全性和可维护性。

综上所述,Java的访问修饰符是面向对象编程中非常重要的概念,它们允许开发者精细地控制程序元素的访问级别,从而实现代码的封装和数据的隐藏。

3.Getter访问器与Setter修改器

在Java封装中,Getter和Setter方法是非常重要的组成部分,它们提供了一种安全的方式来访问和修改类的私有成员变量。封装是面向对象编程中的一个核心概念,它要求将类的内部实现细节隐藏起来,仅对外提供有限的接口(即公共方法)来进行交互。

Getter方法

Getter方法,也被称为访问器(Accessor)方法,用于返回类中私有成员变量的值。这些方法的命名通常遵循get后跟成员变量名的约定(对于布尔类型的成员变量,通常会使用is作为前缀)。

public class Person {  
    private String name;  
  
    // Getter方法  
    public String getName() {  
        return name;  
    }  
}

在上面的例子中,getName()方法是一个Getter方法,它返回Person类中私有成员变量name的值。

Setter方法

Setter方法,也被称为修改器(Mutator)方法,用于设置类中私有成员变量的值。这些方法的命名通常遵循set后跟成员变量名(首字母大写)的约定。

public class Person {  
    private int age;  
  
    // Setter方法  
    public void setAge(int age) {  
        this.age = age; // 使用this关键字来区分成员变量和参数  
    }  
}

在上面的例子中,setAge(int age)方法是一个Setter方法,它接受一个整数参数来设置Person类中私有成员变量age的值。注意,这里使用了this关键字来区分成员变量age和参数age

Getter和Setter方法的优点

  1. 封装:Getter和Setter方法提供了一种封装类中私有成员变量的方式,外部代码不能直接访问或修改这些变量,必须通过类提供的方法来进行。
  2. 数据验证:在Setter方法中,可以在设置成员变量之前进行数据验证,以确保数据的正确性和有效性。
  3. 灵活性:Getter和Setter方法允许在返回或设置成员变量之前执行额外的逻辑,如日志记录、安全检查等。
  4. 易于维护:当需要修改成员变量的内部实现时(例如,更改变量名或类型),只需修改Getter和Setter方法即可,而无需修改使用这些变量的外部代码。
  5. 支持链式调用:在某些情况下,Getter和Setter方法可以返回类的实例(对于Setter方法,这通常不是最佳实践,但对于某些特殊用途的类可能是有用的),从而支持链式调用。

总之,Getter和Setter方法是Java封装中不可或缺的一部分,它们提供了一种安全、灵活且易于维护的方式来访问和修改类的私有成员变量。

4.关键字

4.1.this

在Java中,this关键字是一个非常重要的引用变量,它指向当前对象的引用。this关键字在Java中有几个主要用途:

  1. 访问当前对象的成员变量
    当类的成员变量(字段)与方法的局部变量同名时,可以通过this关键字来访问类的成员变量,以区分它们。

    public class MyClass {  
        private int number;  
     
        public void setNumber(int number) {  
            this.number = number; // this.number 指的是类的成员变量  
        }  
     
        public int getNumber() {  
            return this.number; // 同样,使用this来明确访问成员变量  
        }  
    }
    
  2. 调用当前对象的构造器
    在构造器内部,可以使用this关键字来调用同一个类的另一个构造器。但是,这种调用必须是构造器中的第一条语句。

    public class MyClass {  
        private int number;  
     
        public MyClass() {  
            this(0); // 调用具有一个参数的构造器  
        }  
     
        public MyClass(int number) {  
            this.number = number;  
        }  
    }
    
  3. 返回当前对象的引用
    在某些情况下,this关键字可以返回当前对象的引用。这在实现链式调用时特别有用。

    public class MyClass {  
        private int number;  
     
        public MyClass setNumber(int number) {  
            this.number = number;  
            return this; // 返回当前对象的引用  
        }  
     
        public static void main(String[] args) {  
            MyClass obj = new MyClass().setNumber(10); // 链式调用  
        }  
    }
    

    注意:虽然可以在Setter方法中返回this以支持链式调用,但这并不总是最佳实践,因为它可能隐藏了方法的副作用,并可能导致代码难以阅读和维护。

  4. 区分当前对象和其他对象
    在需要区分当前对象和其他对象时,this关键字非常有用。虽然这种情况在方法参数或局部变量与成员变量同名时最为常见,但在其他上下文中也可能出现。

注意事项:

在静态方法中不能使用this
需要注意的是,this关键字只能在非静态方法中使用,因为静态方法是属于类的,而不是属于类的某个特定实例的。因此,在静态方法中,没有当前对象的概念,也就不能使用this关键字。

总结来说,this关键字在Java中用于访问当前对象的成员变量、调用当前对象的构造器(仅限构造器内部)、返回当前对象的引用,以及在需要区分当前对象和其他对象时作为引用变量。但是,它不能在静态方法中使用。

4.2.static

在Java中,static关键字是一个非常重要的修饰符,它可以应用于类成员(包括字段、方法和代码块)。当一个成员被声明为static时,它就不再属于类的任何特定实例,而是属于类本身。这意味着你可以在不创建类实例的情况下访问这些成员。

静态变量(Static Variables)

静态变量也称为类变量,它们被类的所有实例共享。无论创建了多少个类的实例,静态变量都只有一份拷贝。静态变量在类被加载到JVM时初始化,并且它们的值对所有实例都是可见的。

public class MyClass {  
    static int staticVar = 42; // 静态变量  
  
    public static void main(String[] args) {  
        System.out.println(MyClass.staticVar); // 无需创建实例即可访问  
    }  
}

静态方法(Static Methods)

静态方法也属于类,而不是类的实例。因此,它们可以在没有创建类实例的情况下被调用。静态方法不能访问类的非静态成员(变量和方法),因为非静态成员是依赖于类的实例的。

public class MyClass {  
    static void staticMethod() {  
        // 静态方法实现  
    }  
  
    public static void main(String[] args) {  
        MyClass.staticMethod(); // 无需创建实例即可调用  
    }  
}

静态代码块(Static Blocks)

静态代码块在类被加载到JVM时执行,且只执行一次。它们通常用于初始化静态变量或执行只需执行一次的静态初始化操作。

public class MyClass {  
    static {  
        // 静态代码块  
        System.out.println("静态代码块执行了");  
    }  
  
    public static void main(String[] args) {  
        // 当类被加载时,静态代码块会执行  
    }  
}

注意事项

  • 静态成员(变量和方法)属于类,而不是类的实例。
  • 静态方法不能访问类的非静态成员,因为非静态成员依赖于类的实例。
  • 静态成员可以通过类名直接访问,而无需创建类的实例。
  • 静态代码块在类加载时执行,且只执行一次。
  • 过度使用静态成员可能会导致代码难以测试和维护,因为静态成员的状态在类的所有实例之间共享,并且它们的生命周期与类本身相同。因此,在设计类时,应谨慎使用静态成员。

5.jar包

Jar包(Java Archive File)是Java平台中一种重要的文件格式,它允许将多个Java类文件、相关的元数据和资源(如图像、音频、配置文件等)打包成一个文件。这种打包方式不仅便于分发和部署Java应用程序或库,还使得Java应用的模块化更加容易实现。以下是关于Jar包的详细解析:

一、Jar包的基本概念

  • 定义:Jar包是Java Archive的缩写,是Java的一种文档格式,也是与平台无关的文件格式。
  • 本质:Jar包实质上是一种压缩文件,它采用了ZIP的压缩方式,但文件后缀被定义为.jar
  • 用途:Jar包通常用于将Java库、应用程序或模块分发给其他开发人员或部署到不同的环境中。

二、Jar包的结构

  • 主要内容:Jar包可以包含编译后的Java类文件(.class)、源代码文件(.java)、资源文件(如图像、音频、配置文件等)以及一个名为META-INF/MANIFEST.MF的清单文件。
  • 清单文件(MANIFEST.MF):这是Jar包中最重要的文件之一,它包含了Jar包的版本、创建者、类搜索路径(Class-Path)等信息。对于可执行Jar包,还会包含Main-Class属性,指明包含main方法的类,作为程序的入口点。

三、Jar包的创建方法

创建Jar包有多种方法,包括手动创建和使用工具(如Maven、Gradle或IDE内置的打包工具)自动创建。

  • 手动创建:通过JDK提供的jar命令工具,结合命令行参数来创建Jar包。例如,使用jar -cvf jar-file input-files命令,其中c表示创建新的归档文件,v表示在创建过程中生成详细输出,f指定归档文件的名称,input-files是要被打包的文件或目录。
  • 使用工具自动创建:在Maven或Gradle项目中,可以通过配置pom.xmlbuild.gradle文件来自动打包Jar包。IDE(如IntelliJ IDEA、Eclipse等)也提供了图形化界面来配置和生成Jar包。

四、Jar包的运行

对于可执行Jar包,可以直接使用java -jar jar-file命令来运行。此时,JVM会根据META-INF/MANIFEST.MF文件中的Main-Class属性来找到程序的入口点,并执行相应的main方法。

五、Jar包的优势

  • 便于分发和部署:将多个文件打包成一个文件,简化了分发和部署的流程。
  • 提高安全性:可以对Jar包进行数字签名,确保只有能够识别数字签名的用户才能使用里面的内容。
  • 模块化:有助于实现Java应用的模块化,使得不同模块之间的依赖关系更加清晰。

综上所述,Jar包是Java平台中一种非常重要的文件格式,它对于Java应用的开发、分发、部署和模块化都起到了重要的作用。

标签:Java,变量,成员,访问,封装,方法,public
From: https://www.cnblogs.com/tubby233/p/18336079

相关文章

  • 关于使用C#注入C++的封装DLL后打印内容乱码
    最近因需要,用C++写了个钩子的DLL,一切工作测试通过后,放到C#里使用P/Invoke调用,发现部分乱码,最后反复测试,才发现一个问题,原来SetWindowsHookEx这个函数,也是分A版和W版,最后换了就正常了,附上对比。。乱码[DllImport("user32.dll",SetLastError=true]publicstaticex......
  • 封装Vue 的 SVG 组件
    svg静态资源在assets下新建一个svg文件夹,用于存放svg图片svgIcon组件在components下新建一个文件夹,包含两个文件index.ts和SvgIcon.vuevue.config.jsmain.ts需要引入组件svgIcon使用**.vue<svg-icon iconClass="invite" className="iconicon-invite" /> *......
  • Java中的封装
    在Java中,封装(Encapsulation)是面向对象编程(OOP)的四大特性之一(其他三个是继承、多态和抽象)。封装主要用来隐藏对象的属性和实现细节,仅对外公开接口(方法),与对象交互只能通过这些接口进行。这样做的好处包括提高代码的安全性、灵活性和可维护性。如何进行简单封装1.使用访问修饰......
  • 使用C99 变长数组和和零长数组特性封装协议回复消息
    背景:主从机交互协议中,需要针对不同控制字封装回复消息接口。本文使用变长数组特性和零长数组特性对这类接口进行统一封装。 1#pragmapack(1)2typedefstruct{3uint8_tmagic;4uint8_tlen_H;5uint8_tlen_L;6uint8_tcmd;7uint8_t......
  • vue3 封装request请求
    vue3原生请求封装我这里用一个案例来解释需求:把vue3原生的静态页集成到vue2的若依项目并且可以访问vue2接口在vue3src下的utils下创建文件request.ts文件importaxiosfrom"axios";import{showMessage}from"./status";//引入状态码import{ElMess......
  • SqlSugar 多数据源的简单封装
    参考SqlSugar的官网文档,我自己封装了一个支持多数据库的UnitOfWork的SqlSugar封装类,直接使用SqlSugar的仓储操作如下:///<summary>///数据库实例基类///</summary>publicabstractclassBaseDbClient{///<summary>///获取数据库客户端实例......
  • 面向对象编程(2)——封装
    目录一、概念1.1主要特点1.2实例二、封装的内容2.1 属性(数据成员)2.2 方法(成员函数)2.3 实现细节2.4 类的依赖关系2.5示例2.5.1示例2.5.2解释三、原则与注意事项3.1 封装的原则3.2注意事项一、概念        封装(Encapsulation)是面向对象编程......
  • yii2代码封装
    1、批量更新某个字段/***@throwsCDbException*@throwsCException*updatexxxTablesetcolumn1=casepk*whenwhenData1thencaseData1*...*END*whereidin(1,2,3...)*/publicfunctionbatc......
  • 使用vite创建react项目并进行初始化(仓库、路由、封装)
    前言学的时候都是跟着教程进行创建,后面发现自己写项目的时候记不住需要做什么,所以现在写一篇来给自己总结一下。(后面忘了也不用翻视频了,直接照着抄答案)只写流程,没有理论。这是我写的习惯,只具备一定通用性,有需要可参考。创建项目npmcreatevite@latestHireSpherenpmins......
  • 使用pybind11封装c++的dll,供python调用
    用pip安装好pybind11 文件清单,都写在一个目录里//文件名:add.cppextern"C"doubleadd(doublein1,doublein2){returnin1+in2;}//文件名:sub.cppextern"C"doublesub(doublein1,doublein2){returnin1-in2;}//文件名:mul.cppextern"......