面向对象三大特性之一:封装

1.封装的概念

面向对象的三大特性:封装、继承、多态。

什么是封装: 把类的细节进行隐藏,类外看不到这个数据。

2.访问限定符和包

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

这里说一下什么是同类、同包、不同包。

2.1那么包是什么呢?

①:自定义包

在java中包就是组织类的一种方式

概念:为了更好的管理类,把多个类收集在一起成为一组,成为软件包。例如

文件夹src就是idea的默认包,包里面放了main类和test类。

包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。

在同一个项目中可以存在相同名字的类,但是要在不同的包中 。例:

这样我们在src和demo01包下面都创建了Test类,编译器没有报错。

demo01属于我们的自定义包

注意:

  1. 1. 在文件的最上方加上一个package语句指定这是在哪个包中。

  1. 2.包名需要尽量指定成唯一的名字,通常会用公司的域名的颠倒形式(com.baidu.demo)

  1. 3.如果一个类没有package语句,则该类被放到默认包中。

  1. 4.包名要和代码路劲相匹配。

我们创建了一个com.xxx。code的包,在下面创建了一个test类,则在文件夹中可以找到,

②:import导入包

java中提供了很多的类给我们使用,例如:

我们通过java.util来导入里面的Date包,在通过创建的对象date来调用包里面的getTime

就可以获得一个时间戳。

这样写是不是很麻烦呢?

我们还可以在最上面来使用import来导入包。

这样我们在前面就不需要再写java.util了。

我们如果还要使用里面的Arrays里面的类怎么办呢?再写一个import java.util.Arrays吗

其实不用,我们可以写成java.util.* ,

*可以认为是通类符,可以充当包里的任何类。并不是说使用了*就是把包里面的类都导入了,而是使用哪个类导入哪个类。

这里要注意的是:一个类不一定只有一个,他可以再不同的包底下。例如Date

再util下有,再sql下面也有,如果我们使用了*,那么使用哪一个呢,编译器就搞不清楚了,就会报错

所以非必要情况我们一般不使用*。

还有一种是import static导入静态的包。

上面可以看出Math出现了多次,我们可以使用import static java.lang.Math.*

这样我们就不用一直写Math了。

2.2 修饰限定符

上面也看到了这张图,那么我们也已经讲过了包的概念,下面我们看看什么是同包不同类和不同包和同类

①:同类 private。

class Student {
    private String name;

    private int age;

    public void attendClass() {
        System.out.println(this.name + "再上课");
    }

    public static void main(String[] args) {
        Student student01 = new Student();
        student01.name = "zhangsan";
    }
}


public class Test01 {
    Student student01 = new Student();
    student01.name = "zhangsan"
}

根据代码块和上图可以看出,我们在Studeng类中创建了一个main方法,在main方法创建了一个对象

然后使用变量名 + . 来访问对象的属性。

可以成功生成,但是在test01类中却无法访问,这是因为成员变量属性被private修饰了,只能在同类中使用。

如果我们要在类外使用的话可以给他创建一个公开的接口。如:

    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;
    }

一个get接收属性,一个set设置属性,我们在类外调用这些方法即可。

可以看出我们调用set方法后成功的给类外的对象进行了赋值。

这就是private,只能在同类中调用,在不同类调用需要创建一个公共接口来给其他人使用。

②:同包 default

我们在Test2这个类中创建了一个默认变量age,根据图可以看出在同一个包中我们创建的对象可以正常访问,但是在不同的包下面无法访问。

这里要注意一点: 要使用不同包的类,要先使用import将包导进来。

③: 不同的包 public

这里就比较简单了,就是我们经常使用的public,表示就算是不同的包,不同的类也可以访问,相当于万

能钥匙,所有门都可以开。

3.static修饰的成员变量和成员方法

3.1:static修饰成员变量

我们继续来定义一个学生类变量。

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

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

    public void printStudent() {
        System.out.println("姓名: " + this.name + " 年龄: " + this.age + " 班级: " + this.classRoom);
    }
}

public class Test01 {
    public static void main(String[] args) {
        Student student = new Student("zhangsan", 18, "108");
        student.printStudent();
        Student student1 = new Student("lisi",19,"108");
        student1.printStudent();
    }

}

上面我们可以看出,班级都可以是一样的,我们能不能不输入班级,让他一直保持是108呢?

接下来就得用到我们的static了。比如:

我们将classRoom用static修饰之后,我们将他直接初始化,后面我们创建的对象不用给他赋值也可以使用。

static修饰的成员变量,称为静态成员变量,也可以称为类成员变量。

特性:

  • 不属于某个具体的对象,是所有对象所共享的,不存储在某个对象的空间中。

  • 既可以通过对象访问,也可以通过类名访问,一般通过类名访问。

  • 类变量存储在方法区中。

  • 生命周期伴随类的一生。

3.2 staatic修饰成员方法

一般来说,类的成员变量都是通过private修饰的,那么在加上static之后,我们要如何创建它的接口呢?

通过idea我们生成了两个获取和修改被static修饰后的类变量的方法。

那么被static修饰的方法有什么特性呢?

  • 与类成员一样,不属于某个具体的对象,属于类方法。

  • 可以通过对象调用,也能通过类名调用。

  • 不能再静态方法中访问任何非静态成员变量。(因为静态方法不依赖对象,不创建对象也可以使用,但是没被static修饰的变量却不能,所以不能放在类方法里面)

  • 静态方法中不能调用任何非静态方法(静态方法中有隐藏的this函数,再静态方法调用的时候无法调用this引用)

3.3static的初始化

①:就地初始化

即在创建的时候就给它赋值。例:

②:静态代码块初始化

那啥是代码块呢? 我知道你很急,但你先别急😂😂😂。马上见分晓

4.代码块

4.1概念

用{}定义的一段代码称为代码块。

4.2普通代码块

用{}直接定义,普通方法块

可以看到普通代码块也要遵循局部优先原则。

普通代码块的成员变量在外部访问不到。

4.3构造代码块

class Student {
    private String name;
    private int age;
   private static String classRoom = "108";

    {
        this.name = "张三";
        this.age = 18;
        System.out.println("构造代码块");
    }

    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 static String getClassRoom() {
        return classRoom;
    }

    public static void setClassRoom(String classRoom) {
        Student.classRoom = classRoom;
    }

构造代码块

定义在类内部的代码块称为构造代码块。也称为实例代码块。主要作用是用来初始化成员变量。

4.4静态代码块

使用static修饰的代码块称为静态代码块,主要用来初始化静态成员变量。

4.5代码块间的执行顺序

class Student {
    private String name;
    private int age;
   private static String classRoom;

    {
        this.name = "张三";
        this.age = 18;
        System.out.println("构造代码块");
    }

    static {
        Student.classRoom = "108";
        System.out.println("静态代码块");
    }

    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 static String getClassRoom() {
        return classRoom;
    }

    public static void setClassRoom(String classRoom) {
        Student.classRoom = classRoom;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("构造方法");
    }

    public void printStudent() {
        System.out.println("姓名: " + this.name + " 年龄: " + this.age + " 班级: " + Student.classRoom);
    }
}

public class Test01 {
    public static void main(String[] args) {
        Student student = new Student("zhangsan", 18);
        student.printStudent();
        Student student1 = new Student("lisi",19);
        student.printStudent();
    }

}

根据上面代码的运行结果我们可以得出,静态代码块是最先调用的,并且创建对象只会调用一次

其次是构造代码块,最后才是构造方法。我们在代码块中初始化的变量,如果在构造方法中给它赋值时,

初始化的变量便会改变。下面我们再看一下不给赋值的结果。

当我们使用不带参数的构造方法时,便会按我们初始化的数值来输出。

当我们有两个静态代码块呢?

根据上图我们可以得到静态代码块会按照顺序来进行执行,并且也只会执行一次。

注意:

  • 静态代码块不管生成多少对象,都只会执行一次

  • 静态成员变量是类的属性,因此实在jvm加载类时开辟空间并初始化的

  • 如果一个类中有多个静态代码块,再运行时,会按照顺序依次执行

  • 构造块只有在创建对象时才会执行

5.对象的打印

class Person {
    String name;
    String gender;
    
    int age;

    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    
    public void print() {
        System.out.println(this.name);
        System.out.println(this.gender);
        System.out.println(this.age);
    }
}
public class Main {
    
    public static void main(String[] args) {
        Person person = new Person("lisi","男",18);
        person.print();
    }
}

正常来说我们要输出对象里的成员属性,需要自己去创建一个print方法。

那么我们来看一下println方法是怎么实现的呢?

这里可以看出,println最后调用的是toString方法,那么我们是否可以通过重写toString方法来实现直接输出呢?

可以看到我们最后还是正常的输出了。

这就是对象的打印。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值