Java中的封装

封装

前言

⾯向对象程序三⼤特性:封装、继承、多态封装是类和对象的阶段主要研究的属性,封装就相当于将一些东西放进一个封闭的空间中,我们可以使用它,但是无法看到里面的细节,就像电脑一样,我们可以让用户和计算机进行交互,不⽤关⼼内部核⼼部件,不用关系内部如何进行的,计算机外面有个壳子将里面的细节全部给隐藏了

封装:将数据和操作数据的⽅法进⾏有机结合,隐藏对象的属性和实现细节,仅对外公开接⼝来和对
象进⾏交互

private关键字

private修饰成员变量

被private修饰的成员变量只可以在当前类中使用

java 复制代码
class Student{
    //private修饰
    private String name;
    private int age;

    //成员方法一般采用的是public修饰
    public void eat(){
        System.out.println(name+"吃饭");
    }

}

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        //这里的age不可以通过这种方式被访问
        //student.age = 18;//这是错误的
        student.eat();
    }
}

因为这里的age在Student 类中被private修饰,只可以在这个类中使用,即使我们new了一个新的对象,也是无法访问和修改的,这是封装的作用,我们就不能访问了吗

这时候我们要手动创建set和get方法,创建接口来进行访问

java 复制代码
class Student{
    //private修饰
    private String name;
    private int age;

    //成员方法一般采用的是public修饰
    public void eat(){
        System.out.println(name+"正在吃饭");
    }
    //名字
    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 Test {
    public static void main(String[] args) {
        Student student = new Student();
        //赋值
        student.setName("zhang");
        student.setAge(18);
        //打印
        System.out.println(student.getAge());
        System.out.println(student.getName());

        student.eat();
    }
}

这里通过get和set方法来进行被private修改的成员变量

运行结果如下

这样写不是让代码复杂了吗,为什么还要这样写呢,下面我们说封装的好处

封装的好处

复制代码
1. 封装降低耦合度
封装可以降低各个对象之间的联系,这样对内部修改不会影响外部
2. 封装降低复杂性
封装将其里面的细节隐藏了,只提供接口供我们使用,使用变得简单
3. 封装提高安全性
封装将其内部细节隐藏,这样外部不容易修改内部,因此保护了内部

访问限定符

Java中主要通过类和访问权限 来实现封装:类可以将数据以及封装数据的⽅法结合在⼀起,主要通过访问权限限定符来确定权限,Java中提供了四种访问限定符

复制代码
这里的子类 和非子类是继承中的概念
public修饰的成员变量、成员方法表示是公开的,在所指定情况下均是可以正常访问的
private修饰的成员变量,只能在当前类中来使⽤
任意:默认权限,也就是包访问权限,是变量什么修饰符都不加,此时只能在包当中才能被访问
protected 修饰该类当中成员变量、成员⽅法等表⽰要么只能在同⼀个包中的类中进
⾏访问,要么在不同包中只能通过在继承关系上的⼦类对象来访问

static关键字

如果我们创建一个学生类,他们所在的都是同一班级,我们需要全部都要进行相同的赋值吗,这样就有点繁琐了,那如何解决呢

java 复制代码
class Student {
    public String name;
    public int age;

    public String classRoom;
}

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        student1.classRoom = "13class";

        Student student2 = new Student();
        student2.classRoom = "13class";
    }
}

Student类中定义的成员变量,每个对象中都会包含⼀份,但这里的班级是共享的,所以这里我们可以将班级存储在一个公共区域吗

因此Java中,被static修饰的成员,称之为静态成员 ,也可以称为类成员 ,其没有具体的对象,是所有对象所共享的,static关键字可以用来修饰成员变量和成员方法

static修饰成员变量

复制代码
静态成员变量
不属于某个具体的对象,是类的属性,类中所有对象共享的
访问:既可以通过对象访问,也可以通过类名访问,但⼀般更推荐使⽤类名访问
类变量存储在⽅法区当中,不存储在某个对象的空间中
⽣命周期伴随类的⼀⽣,随着类的加载而创造,类的消失而消失
静态成员变量⼀般不会放在构造⽅法中来初始化

静态成员变量的创建和初始化

上面的我们创建的Student类中,所有学生在同一班级,我们就用static来修饰班级

java 复制代码
class Student {
    public String name;
    public int age;
 
    public static String  classRoom = "13class";
}

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();

        Student student2 = new Student();
    }
}

我们这里将classRoom设置为静态变量并且在类中初始化了,这里我们成员变量的类型变了,还是像以前那样 对象名.变量名来访问吗

静态成员变量的访问

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

复制代码
//两种访问形式
对象名.静态成员变量
类名. 静态成员变量
java 复制代码
class Student {
    public String name;
    public int age;

    public static String  classRoom = "13class";
}

public class Test {
    public static void main(String[] args) {
        //通过类名来访问
        System.out.println(Student.classRoom);
        //通过对象名来访问
        Student student1 = new Student();
        System.out.println(student1.classRoom);

        Student student2 = new Student();
    }
}

运行结果如下

从结果上来看,我们是都可以访问,但是使用类名访问是最优的

因为static修饰的成员变量是被存放在方法区的,不是存储在某个对象的空间中

static修饰成员方法

Java中,被static修饰的成员⽅法称为静态成员⽅法,是类的⽅法,是所有对象共有的,不是特有的

复制代码
静态成员方法
不属于某个具体的对象,是类⽅法
访问:可以通过对象调⽤,也可以通过类名.静态⽅法名(...)⽅式调⽤
注意:不能在静态⽅法中访问任何⾮静态成员变量

静态成员方法的创建和使用

java 复制代码
class Student {
    public String name;
    public int age;
   //静态成员变量
    public static String  classRoom = "13class";

    //静态成员方法
    public static String getClassRoom() {
        return classRoom;
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        //类名来访问
        System.out.println(Student.getClassRoom());
        //对象名来访问
        System.out.println(student.getClassRoom());
    }
}

这里和静态成员变量一样都可以使用类名和对象名来访问,仍然是使用类名的访问最好

非静态成员方法可以访问静态成员变量和方法,而静态的成员方法只可以访问静态的

就像这里用静态的方法访问非静态 的age是无法访问的

因为⾮静态⽅法有this参数,在静态⽅法中调⽤时候⽆法传递this引⽤

所以这里会报错

非静态的是可以访问静态的变量和方法

java 复制代码
class Student {
    public String name;
    public int age;
   //静态成员变量
    public static String  classRoom = "13class";

    //静态成员方法
    public static String getClassRoom() {
    //修改一下班级
        Student.classRoom = "14class";
        return classRoom;
    }
    //非静态的成员方法
    public void test(){
    //原班级
        System.out.println(classRoom);
        //修改后的班级
        System.out.println(getClassRoom());
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        //使用对象来访问Student类中test方法
        student.test();
    }
}

这里我们创建一个非静态的test来访问静态成员变量和方法,都是可以的

运行结果如下

静态成员方法的初始化

静态成员变量⼀般不会放在构造⽅法中来初始化,有两种初始化方式,一种是就地初始化

java 复制代码
class Student {
    public String name;
    public int age;
   //静态成员变量
    public static String  classRoom = "13class";
}

就像这里的静态成员变量classRoom直接初始化了

还有一种是静态代码块初始化 ,那什么是代码块呢?

代码块

使⽤ { } 定义的⼀段代码称为代码块 ,根据位置和关键字的不同,可以分为四种代码块,普通代码块、构造代码块(实例代码块)、静态代码块、

同步代码块

普通代码块

就是定义在方法中的代码块

例如:

java 复制代码
public class Test {
    public static void main(String[] args) {
        {
            int a = 10;
            System.out.println(a);
        }
        int a = 100;
        System.out.println(a);
    }
}
复制代码
这里的a不是重定义,这里的a是两个不同的代码块,用{}中算一个代码块
所以这里不是错误的,是正确的

运行结果如下

构造代码块(实例代码块)

定义在类中的代码块 ,常用于初始化类中的非静态 的成员变量

实例代码块只有在创建对象以后才会执行

java 复制代码
//Student类
class Student{
    public String name;
    public int age;
    public String classRoom;

    //实例代码块
    {
        this.name = "zhang";
        this.age = 18;
        this.classRoom = "13class";
    }

    public void show(){
        System.out.println(name+" " + age+ " "+ classRoom);
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.show();
    }
}

运行结果如下

这里我们可以发现一个问题就是如果这里构造方法也会对其类中元素修改,那我们是先执行实例代码块,还是先执行构造方法呢?

我们来从下面这个例子看一下

java 复制代码
class Student{
    public String name;
    public int age;
    public String classRoom = "14class";

    //实例代码块    1
    {
        this.name = "zhang";
        this.age = 18;
        this.classRoom = "13class";
        System.out.println("实例代码块被执行了");
    }
    //2
    public Student(String name ,int age ,String classRoom){
        this.name = name;
        this.age = age;
        this.classRoom = classRoom;
        System.out.println("带三个参数的构造方法被执行了");
    }
    //3
    public void show(){
        System.out.println(name+" " + age+ " "+ classRoom);
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student("wang",20,"15class");
        student.show();
    }
}
复制代码
先执行实例代码块,进行初始化,然后执行构造方法
如果有普通方法,普通的方法最后执行,所以这里的结果是构造方法传入的结果

运行结果如下

实力代码块先执行,还是就地初始化先执行呢

java 复制代码
class Student{
    public int age = 16;

    {
        this.age = 17;
    }

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

如果他们调换顺序,结果却变了

所以他们是谁在上面先执行谁,他们都执行完以后,在执行构造方法

静态代码块

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

java 复制代码
class Student{
    public String name;
    public int age;
    public static String classRoom;
    //静态代码块
    static {
        classRoom = "13class";
    }
    //实例代码块
    {
        this.name = "zhang";
        this.age = 18;
    }
    //
    public Student(String name ,int age ){
        this.name = name;
        this.age = age;
    }

    public void show(){
        System.out.println(name+" " + age+ " "+ classRoom);
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student("wang",20);
        student.show();
    }
}

运行结果如下

但我们又又一个问题就是静态代码块、实例代码块、构造方法这三种那个先执行呢?

java 复制代码
class Student{
    public String name;
    public int age;
    public static String classRoom;
    //静态代码块
    static {
        classRoom = "13class";
        System.out.println("静态代码块被执行了");
    }
    //实例代码块
    {
        System.out.println("实例代码块被执行了");
    }
    //构造方法
    public Student( ){
        System.out.println("无参数的构造方法被执行了");
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
    }
}
复制代码
这里是先执行static静态代码块,然后执行实力代码块,最后执行构造方法

运行结果如下

但是我们要注意静态代码块只会执行一次

这里我们实例化了两个学生对象,但是从这里的结果看出静态代码只会执行一次

c 复制代码
执行顺序:
1.先执行static静态代码块(只会执行一次)
2.在执行构造代码块(实例代码块) 只有在实例化对象以后才会执行
3.在执行构造方法
4.在执行其他的方法
要注意就地初始化和构造代码块初始化对象是相同执行顺序,谁在上面先执行谁

到这里就结束了,希望对你有所帮助,欲知后事如何,请听下回分解

相关推荐
侠客行03175 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪5 小时前
深入浅出LangChain4J
java·langchain·llm
灰子学技术7 小时前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
老毛肚7 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎7 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
二十雨辰7 小时前
[python]-AI大模型
开发语言·人工智能·python
Doro再努力8 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Yvonne爱编码8 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚8 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
Daniel李华8 小时前
echarts使用案例
android·javascript·echarts