【JavaSE】-- 类和对象(2)

6. 封装


6.1 封装的概念

对于面向对象的语言来说 有几个比较重要的特征:封装、继承、多态。
这里有一个误区:这三个特征不是哪个语言的特征,而是面向对象的特征。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互.

6.2 访问限定符

访问权限用来控制方法或者字段能否直接在类外使用

No范围privatedefaultprotectedpublic
1同一个包的同一类
2同一个包中的不同类
3不同包中的子类
4不同包中的非子类

【说明:】

  • protected主要是用在继承中
  • default权限指:什么都不写时的默认权限
  • 访问权限除了可以限定类中成员的可见性,也可以控制类的可见性。
class Student {
   private String name;
   private int age;
   private String stuNum;


   // get  和  set方法
    //当成员变量被private修饰了之后  该成员变量只能在同一个包中的同一个类中被访问
    // 提供get 和 set方法 供给访问

    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 String getStuNum() {
        return stuNum;
    }

    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }


    //构造方法
    public Student(String name, int age, String stuNum) {
        this.name = name;
        this.age = age;
        this.stuNum = stuNum;
    }
}

public static void main(String[] args) {
    Student student = new Student("zhangsan", 11, "202320044118");
    System.out.println(student.getName());// zhangsan
    // System.out.println(student.name);//报错
}

6.3 封装拓展之包


6.3.1 包的概念

在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。

包的本质就是一个 文件夹 ,可以理解为包就是为了组织类的; 在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。

6.3.2 导入包中的类

Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类.

//导入一个包(方法1)
public static void main(String[] args) {
    java.util.Date date = new java.util.Date();
     // 得到一个毫秒级别的时间戳
    System.out.println(date.getTime());
}

但是这种写法比较麻烦一些, 可以使用 import语句导入包.

import java.util.Date;
// 或者写成
// import java.util.*;
// 但是这种写法并不推荐

public class Test {
    public static void main(String[] args) {
        Date date = new Date();
// 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
    }
}

更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况.

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
        Date date = new Date();
        System.out.println(date.getTime());
    }
}
// 编译出错
Error:(5, 9) java:Date的引用不明确
        java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配

在这里插入图片描述

6.3.3 自定义包

鼠标放在src上右键—new—package
在这里插入图片描述

包名采用小驼峰的写法,一般采用公司名的倒写形式(比如:com.baidu.www)

建完包之后 如果包名是一行的话:
在这里插入图片描述
打开文件路径:
在这里插入图片描述
在这里插入图片描述
src: 程序的默认包,程序在运行的时候默认是在Src这个包下面找可执行程序,去执行。

7. static成员


7.1 再谈学生类

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

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

    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 String getStuNum() {
        return stuNum;
    }

    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }

    public String getClassRoom() {
        return classRoom;
    }

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

public class Test {
    public static void main(String[] args) {
        Student student1 =
                new Student("zhansgan", 21, "551453666", "1103");
        Student student2 =
                new Student("lisi", 21, "1576632", "1103");
        Student student3 =
                new Student("wangwu", 21, "588556546565", "1103");

    }
}

实例化三个学生对象student1, student2, student3。每个对象都有自己特有的姓名、年龄、学号等信息。

假如这三个同学都是一个班的,那么他们一定在同一个教室上课。

之前在Student类中定义的成员变量,每个对象中都会包含一份(称之为实例变量),因为需要使用这些信息来描述具体的学生。而现在要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享。在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。

7.2 static修饰成员变量

public class Student {
    private String name;
    private int age;
    private String stuNum;
    private static String classRoom;
    //...
}

【静态成员变量特性】

  1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
  2. 既可以通过对象访问,也可以通过类名访问(合法但是不合理😉),但一般更推荐使用类名访问.
  3. 类变量存储在方法区当中,所有的对象共享。
  4. 静态成员变量的生命周期伴随类的一生,当类被加载的时候 静态成员变量就被加载了;类的卸载而销毁。

题目: 下面一段程序的输出结果是多少?
在这里插入图片描述

输出12

不管new多少个对象,从始至终只有一个count ,不管是通过哪一个对象访问的, 都是在对同一个count进行操作的。

7.3 static修饰成员方法

一般类中的数据成员都设置为private,而成员方法设置为public,那设置之后,Student类中classRoom属性如何在类外访问呢?

public class TestStudent {
  public static void main(String[] args) {   
    System.out.println(Student.classRoom);
  }
}
// 编译失败:
// Error:(10, 35) java: classRoom 在 extend01.Student 中是 private 访问控制

Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的。

public class Student{
    // ...
    private static String classRoom = "306";
    // ...
    public static String getClassRoom(){
        return classRoom;
    }
}
public class TestStudent {
    public static void main(String[] args) {
        System.out.println(Student.getClassRoom());
    }
}
输出:306

【静态方法特性】

  1. 不属于某个具体的对象,是类方法
  2. 可以通过对象调用,也可以通过类名.静态方法名(…)方式调用,更推荐使用后者
  3. 不能在静态方法中访问任何非静态成员变量
public static String getClassRoom(){
    System.out.println(this);
    return classRoom;
}
// 编译失败:Error:(35, 28) java: 无法从静态上下文中引用非静态 变量 this
public static String getClassRoom(){
    age += 1;
    return classRoom;
}
// 编译失败:Error:(35, 9) java: 无法从静态上下文中引用非静态 变量 age
  1. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用.
public static String getClassRoom(){
    doClass();
    return classRoom;
}
// 编译报错:Error:(35, 9) java: 无法从静态上下文中引用非静态 方法 doClass()

在静态方法中,是不能访问普通的非静态成员变量和方法的 普通的非静态成员变量是依赖于对象的 要通过对象的引用去访问 而静态的成员方法是通过类名调用的 所以在通过类名调用静态方法时,是传不了this的,this是当前对象的引用,传不了this,我们就不知道当前对象是什么都不知道。
除非我们在这个静态方法中new一个对象,通过这个对象的引用去访问。
所以在static的成员方法中,是不存在this的。

  1. 静态方法无法重写, 不能用来实现多态。

  2. 在普通的成员方法里面可以调用静态得成员变量和成员方法。


在这里插入图片描述
age是被static修饰的,所以age是不依赖于对象的,age不是在person对象里面的age,age是属于类的。
person=null;代表person是不指向于任何对象的。


为什么在一个方法内部不能定义一个静态的成员变量。
在这里插入图片描述
定义时,加上static就是类变量,定义在方法里面就是局部变量了,它挺有脾气的,它不同意。

7.4 static成员变量初始化

注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性.

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

1. 就地初始化
就地初始化指的是:在定义时直接给出初始值

public class Student {
    private String name;
    private int age;
    private String stuNum;
    private static String classRoom = "106";
    //...
}

8. 代码块


8.1 代码块概念以及分类

使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:

  1. 普通代码块(不太能用的到)
  2. 非静态代码块(实例代码块/ 构造代码块)
  3. 静态代码块
  4. 同步代码块(后续线程部分)

8.2 普通代码块

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

public class Main{
    public static void main(String[] args) {
        { //直接使用{}定义,普通方法块
            int x = 10 ;
            System.out.println("x1 = " +x);
        }
        int x = 100 ;
        System.out.println("x2 = " +x);
    }
}
// 执行结果
// x1 = 10
// x2 = 100

这种用法较少见

8.3 构造代码块

构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化类里面非静态的数据成员。构造代码块定义在类的里面,方法的外面。

public class Student {
    private String name;
    private int age;
    private String stuNum;
    private static String classRoom = "106";

//构造方法
    public Student(String name, int age, String stuNum, String classRoom) {
        this.name = name;
        this.age = age;
        this.stuNum = stuNum;
        this.classRoom = classRoom;
        System.out.println("构造方法被调用了....");
    }


//构造代码块
    {
        this.age = 100;
        System.out.println("构造代码块被调用了....");
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 =
                new Student("zhansgan", 21, "551453666", "1103");
    }
}
输出结果:
        构造代码块被调用了....
        构造方法被调用了....

和定义顺序没有关系,一定是先执行构造代码块,再执行构造方法。

8.4 静态代码块

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

public class Student {
    private String name;
    private int age;
    private String stuNum;
    private static String classRoom = "106";

    public Student(String name, int age, String stuNum, String classRoom) {
        this.name = name;
        this.age = age;
        this.stuNum = stuNum;
        this.classRoom = classRoom;
        System.out.println("构造方法被调用了....");
    }


    {
        this.age = 100;
        System.out.println("构造代码块被调用了....");
    }

    static {
        classRoom = "415";
        System.out.println("static{}......");
    }
}
public static void main(String[] args) {
    Student student1 =
            new Student("zhansgan", 21, "551453666", "1103");
}
输出结果:
     static{}......
     构造代码块被调用了....
     构造方法被调用了....

执行顺序和定义顺序无关,执行顺序:静态代码块—>实例代码块—>构造方法。


public static void main(String[] args) {
    Student student1 =
            new Student("zhansgan", 21, "551453666", "1103");
    System.out.println("==============");
    Student student2 =
            new Student("lisi", 21, "1576632", "1103");
}
输出结果:
        static{}......
	     构造代码块被调用了....
	     构造方法被调用了....
	     ==============
		 构造代码块被调用了....
		 构造方法被调用了....

可以看到当我们实例化两个学生对象的时候,静态代码块只执行了一次。

注意事项:

  1. 静态代码块不管生成多少个对象,其只会执行一次
  2. 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
  3. 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
  4. 实例代码块只有在创建对象时才会执行

静态代码块初识化静态数据成员,非静态代码块初始化非静态数据成员。

静态代码块中不会出现this.

10. 对象的打印

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

    public Student(String name, int age) {
        this.name = name;
        this.age = 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("zhangsan", 20);
        System.out.println(student);
    }
}

输出结果:Student@3b07d329

在这里插入图片描述
归根结底,程序在最后调用了一个toString()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_bxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值