零基础 “入坑” Java--- 九、类和对象(二)


面向对象有三大基本思想:封装、继承、多态。 在类和对象阶段,我们先来了解一下封装。

一、封装

1.何为封装

封装即:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口用来和对象进行交互。

对于这段晦涩难懂的解释,我们举个例子来说明一下:在我们使用电脑主机时,我们只需插入U盘即可读取U盘内容,但是在主机内部,却需要经过一系列很复杂的操作。我们可以将封装简单理解为:套壳屏蔽细节。

2.初识封装

我们先来定义一个学生类:

class Student {
    public String name; //姓名
    public int age; //年龄
    public void show() {
        System.out.println("姓名:" + this.name + " 年龄:" + this.age);
    }
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.name = "小王";
        student.age = 20;
        student.show();
    }
}

此时这个类中有两个被 public 修饰的成员变量,一个成员方法,代码可以正常运行。

但是当我们将成员变量的修饰符换为 private 时,main方法中的name和age就都变红了(如下图),此时再次运行,程序就会报错。这是因为:被private修饰之后,代表此变量只能在当前类中使用。
在这里插入图片描述

此时,name和age就相当于已经被我们封装上了,当我们想在类外使用name和age时,就需要使用Getter和Setter:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们在空行单击鼠标右键,选择生成,再选择Getter和Setter,根据需要选择并生成方法,当我们在类外需要使用被封装的变量时,就可以调用生成的方法:

class Student {
    private String name; //姓名
    private int age; //年龄
    public void show() {
        System.out.println("姓名:" + this.name + " 年龄:" + this.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 Test {
    public static void main(String[] args) {
        Student student = new Student();
        //调用生成的方法
        student.setName("小王");
        student.setAge(20);
        student.show();
    }
}

在类中,一般情况下我们将成员变量设置为private,成员方法设置为public。


在这里插入图片描述
对于访问修饰限定符一共有四种:public我们可以广泛使用,private我们只能在当前类中使用;而对于剩下的两个,我们先来了解一下包是什么。

3.封装之包

在Java中,包是对类、接口等封装机制的体现,是一种对类或者接口等很好的组织方式。 包还有一个作用:在同一个工程中允许存在相同名称的类,只要在不同的包中即可。
在这里插入图片描述
在这里插入图片描述

3.1 导入包中的类

Java中提供了很多现成的类供我们使用,如:

import java.util.Arrays;
import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[] array = {1,2,3,4,5};
        System.out.println(Arrays.toString(array));
    }
}

在这里插入图片描述
但并不建议采用简写的方式,可能会导致冲突情况的产生。


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

这段代码不能正常运行,是因为util和sql中都存在Date类,这会导致歧义,编译出错。这种情况下,就需要使用完整的类名:

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
    //完整书写格式:
        java.util.Date date = new java.util.Date();
    }
}

此时代码可以正常运行。


我们还可以使用 import static 导入包中的静态方法和变量,对于这一点了解即可,使用很少。

3.2 再谈访问修饰限定符

在这里插入图片描述
学习完包,我们再来理解这个图片:default即默认权限,当不写访问修饰限定符时,都是默认为default。default因为其访问范围特点,也叫包访问权限。(何为protected我们以后再介绍。)

封装小结:
1.何为封装:对类中的成员通过private关键字进行隐藏,只对类外提供公开的接口(如Getter和Setter)。
2.封装的意义:隐藏类的实现细节,提高安全性。

二、深入static

class Student {
    private String name; //姓名
    private int age; //年龄
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public int classroom; //班级
}
public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("小王", 18);
        s1.classroom = 310;
        Student s2 = new Student("小李", 17);
        s2.classroom = 310;
        Student s3 = new Student("小刘", 19);
        s3.classroom = 310;
    }
}

我们依旧使用学生类举例:先定义一个学生类,再实例化三个对象,依次为这三名学生的班级进行赋值,将他们分配到一个班级:
在这里插入图片描述
既然三名学生在一个班级,那么我们对代码进行修改:

class Student {
    private String name; //姓名
    private int age; //年龄
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static int classroom; //班级
}
public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("小王", 18);
        Student s2 = new Student("小李", 17);
        Student s3 = new Student("小刘", 19);
        Student.classroom = 310;
    }
}

在这里插入图片描述
在Java中,被static修饰的成员,称为静态成员或者类成员,其不属于某个具体的对象,是所有对象所共有的。 既可以通过对象访问,也可以通过类名访问,但推荐使用类名访问。

静态成员变量存储在方法区中,其生命周期伴随类(随类的加载而创建,随类的结束而销毁)


静态成员不能直接调用非静态成员,所以在静态方法中不能使用this,但是可以通过对象的引用间接调用:

class Student {
    private String name; //姓名
    public void show() {
        System.out.println("嘻嘻");
    }
    public static void test() {
        System.out.println("哈哈");
        //通过对象的引用调用 √
        Student student = new Student();
        student.name = "小王";
        student.show();
        //直接调用 ×
        //name = "小王";
        //show();
    }
}

在学习构造方法时我们知道:构造方法的作用就是对 对象中的成员变量进行初始化;但是,静态成员变量一般不会放在构造方法中进行初始化。

静态成员变量的初始化有两种方式:就地初始化 和 静态代码块初始化。

就地初始化即:在定义时直接设定初始值:

class Student {
    public static int classroom = 310; //班级
}

静态代码块初始化:什么是代码块呢???

三、代码块

使用"{}"定义的一段代码称为代码块。 代码块又可分为:普通代码块、构造代码块、静态代码块、同步代码块(先不学)。

1.普通代码块

普通代码块即:定义在方法中的代码块:

    public static void main(String[] args) {
        //普通代码块
        {
            int x = 10;
            System.out.println(x);
        }
        //代码块内的变量不能在代码块外使用
        System.out.println(x);
    }

2.构造代码块

构造代码块即:定义在类中的代码块(无访问修饰限定符)。也叫:实例代码块。构造代码块常用于初始化实例成员变量(非静态成员变量)。

class Student {
    public String name;
    public int age;
    //构造代码块
    {
        this.name = "小王";
        this.age = 20;
        System.out.println("构造代码块");
    }
    //无参构造方法
    public Student() {
        System.out.println("无参构造方法");
    }
    public void show() {
        System.out.println("姓名:" + this.name + " 年龄:" + this.age);
    }
}
public class Test_dmk {
    public static void main(String[] args) {
        Student student = new Student();
        student.show();
    }
}

运行结果为:
在这里插入图片描述
由此可得出:构造代码块先于构造方法执行。

3.静态代码块

使用static定义的代码块称为静态代码块,常用于初始化静态成员变量:

class Student {
    public String name;
    public int age;
    public static int classroom;
    //构造代码块
    {
        this.name = "小王";
        this.age = 20;
        System.out.println("构造代码块");
    }
    //静态代码块
    static {
        classroom = 310;
        System.out.println("静态代码块");
    }
    //无参构造方法
    public Student() {
        System.out.println("无参构造方法");
    }
    public void show() {
        System.out.println("姓名:" + this.name + " 年龄:" + this.age);
    }
}
public class Test_dmk {
    public static void main(String[] args) {
        Student student = new Student();
        student.show();
    }
}

运行结果为:
在这里插入图片描述
由此可得出:静态代码块先于构造代码块,先于构造方法执行。

但是当我们实例化两个对象时,会发现"静态代码块"只输出了一次。

我们总结一下:

1.无论实例化多少对象,静态代码块都只会执行一次。
2.静态成员变量是类的属性,在类加载时就会为其开辟空间并初始化(静态代码块在类加载时就会执行)。
3.当一个类中有多个静态代码块,编译器会根据静态代码块的顺序依次执行。
4.构造代码块只有在实例化对象时才会执行(通过new关键字实例化对象)。

四、对象的打印

在静态代码块的例子中,我们使用自己写的show方法打印成员变量。在Java中,有一个便捷的方法可以帮助我们完成这个任务,就是重写toString方法:
在这里插入图片描述
在这里插入图片描述
我们在空行单击鼠标右键,选择生成,再选择toString,选择需要显示的成员变量,就会生成如下图的方法:
在这里插入图片描述
当我们没有重写toString方法时,因为student是引用类型,所以存储的值为地址:

        Student student = new Student();
        System.out.println(student);

但当我们重写toString方法后,再次运行这段代码,打印的结果就是toString方法中返回值的形式。


Ending。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值