• 第九节:类和对象【三】【static、代码块、对象的打印】


    目录

    🥇1.什么是封装

    📘1.1封装的实现

    🎒2.static成员

    📒2.1 再谈学生类

    ​编辑

    📗2.2 static修饰成员变量

    2.3 static修饰成员方法

    📕2.4 static成员变量初始化

    🔲3. 代码块

    📙3.1 代码块概念以及分类

    📒3.2 普通代码块

    📘3.3 构造代码块

    📗3.4 静态代码块

    📁4. 对象的打印


     

    🌈上节课的封装我们学习了封装,让我们来回忆一下什么是封装!

    🥇1.什么是封装

    ✅对类的细节进行隐藏,提供功能公开的接口来进行和数据进行交互!!

    📘1.1封装的实现

    1. class Person {
    2. private String name;
    3. public int age;
    4. private void eat() {
    5. System.out.println("吃饭!");
    6. }
    7. public void show() {
    8. System.out.println(name+" "+age);
    9. }
    10. }
    11. public class Tesk {
    12. public static void main(String[] args) {
    13. Person person = new Person();
    14. /*person.name = "zhangsan";
    15. person.eat();*/ //error
    16. }
    17. }

    🔺name 、eat这两个方法都已经被封装起来了 ,使用private关键字进行了封装。此时,name的权限就变小了。他只能在当前类当中才能访问

    ❗❗❗特别注意:

    public----------哪里都可以访问

    default---------包访问权限

    private---------当前类中才能访问

    🎒2.static成员

    📒2.1 再谈学生类

    1. class Student {
    2. private String name;
    3. private int age;
    4. private String classRoom; //上课的教室
    5. public Student(String name, int age) {
    6. this.name = name;
    7. this.age = age;
    8. }
    9. public void doClass() {
    10. System.out.println("上课!");
    11. }
    12. }
    13. public class Tesk2 {
    14. public static void main(String[] args) {
    15. Student student1 = new Student("xiaowen", 10);
    16. Student student2 = new Student("xiaowen1", 20);
    17. Student student3 = new Student("xiaowen2", 15);
    18. System.out.println("fsfa");
    19. }
    20. }

    05e489f295984e31a06a0754d2e4a38b.png

    🙈假设三个同学是同一个班的,那么他们上课肯定是在同一个教室,那既然在同一个教室,就没必要每次都写出来,只需要一次即可

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

    那么就可以修改代码:

    private String classRoom;--------->private static String classRoom = "107java直播间";

    b1b3c53006874e049b5995b3397e0041.png

     ➡️现在就不显示classroom了,那么classroom就在方法区。

    📗2.2 static修饰成员变量

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

    1. class Student {
    2. public String name;
    3. public int age;
    4. public static String classRoom = "107java直播间"; //上课的教室
    5. public Student(String name, int age) {
    6. this.name = name;
    7. this.age = age;
    8. }
    9. public void doClass() {
    10. System.out.println("上课!");
    11. }
    12. }

    ✨当我们在输出的时候:

    1. public static void main(String[] args) {
    2. System.out.println(Student.classRoom);
    3. }

    静态的成员变量不属于对象,所以不用通过对象的引用来访问,直接可以通过类名就可以访问的

    🔺【静态成员变量特性】
    1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
    2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
    3. 类变量存储在方法区当中
    4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)

    📜此时我们举一个极端的例子:

    1. public static void main(String[] args) {
    2. Student student1 = null;
    3. System.out.println(Student.name);
    4. }

    此时这个代码就会空指针异常,student1不指向任何对象。但是name属于student这个对象的,就会产生空指针异常

    ✅修改为:

    1. public static void main(String[] args) {
    2. Student student1 = null;
    3. //System.out.println(Student.name);
    4. System.out.println(Student.classRoom);
    5. }

    因为classroom不属于任何对象,它的调用是通过类名来调用的。虽然引用等于null,无所谓,因为在类名调用的时候 . 前面其实就是一个类型,它的类型也是student。

    2.3 static修饰成员方法

    ➡️成员方法:静态成员方法/类方法、非静态成员方法

    1. //非静态成员方法
    2. public void doClass() {
    3. System.out.println("上课!");
    4. }
    5. //静态成员方法
    6. public static void func() {
    7. System.out.println("staticFunc()");
    8. }

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

    1. public class Tesk2 {
    2. public static void main(String[] args) {
    3. Student.func();
    4. }
    5. }

    1️⃣在静态方法内部,不能直接调用非静态的成员方法

    1. public class Tesk2 {
    2. public void mainStaticFunc() {
    3. }
    4. public static void main(String[] args) {
    5. mainStaticFunc();
    6. }
    7. }

    5c5920e3506444618d42ddd3bee44746.png 

    ✅如果想要调用非静态方法: 依赖于对象的引用

    1. public class Tesk2 {
    2. public void mainStaticFunc() {
    3. }
    4. public static void main(String[] args) {
    5. Tesk2 tesk2 = new Tesk2();
    6. tesk2.mainStaticFunc();
    7. }
    8. }

     2️⃣在静态方法内部,不能够直接使用非静态的数据成员(静态方法里边是不能调用this的)

    1. //静态成员方法
    2. public static void func() {
    3. System.out.println(this.name);//error
    4. System.out.println(name);//error
    5. }

    586d177770354f78b5300e59aa4a08a3.png

    只要是非静态的数据成员,都需要通过对象的引用才能调用

    1. public static void func() {
    2. Student student = new Student("BIT",18);
    3. System.out.println(student.name);
    4. }

    在普通的成员方法内部是可以调用静态方法的

    1. class Student {
    2. //非静态成员方法
    3. public void doClass() {
    4. func();
    5. }
    6. }
    7. public class Tesk2 {
    8. public static void main(String[] args) {
    9. Student.func();
    10. }
    11. }
    👉总结:
    🔺【 静态方法特性
    1. 不属于某个具体的对象,是类方法
    2. 可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者
    3. 不能在静态方法中访问任何非静态成员变量
    4. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用

    🌈建议:获取静态的成员变量或者是设置静态的成员变量,此时的方法最好是静态的,否则你要是非静态的,必须要实例化对象

    📕2.4 static成员变量初始化

    📖静态成员变量的初始化分为:

    1️⃣就地初始化:在定义时直接给出初始值

    public static String classRoom = "107java直播间";

    2️⃣默认初始化

    3️⃣可以通过提供get和set方法来进行初始化

    1. public String getName() {
    2. return name;
    3. }
    4. public void setName(String name) {
    5. this.name = name;
    6. }

    8b99c86a192442b7ab8d9c2d18f33191.png

     4️⃣通过代码块进行赋值,继续往后看 :) ~~~

    🔲3. 代码块

    📙3.1 代码块概念以及分类

    使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:
    普通代码块
    构造块(非静态代码块/实例化代码块)
    静态块
    同步代码块(后续讲解多线程部分再谈)

    📒3.2 普通代码块

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

    1. public class Main{
    2. public static void main(String[] args) {
    3. { //直接使用{}定义,普通方法块
    4. int x = 10 ;
    5. System.out.println("x1 = " +x);
    6. }
    7. int x = 100 ;
    8. System.out.println("x2 = " +x);
    9. }
    10. }
    11. // 执行结果
    12. x1 = 10
    13. x2 = 100

    📘3.3 构造代码块

    ➡️构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块构造代码块一般用于初始化实例成员变量

    1. class Student {
    2. public String name;
    3. public int age;
    4. public Student(String name, int age) {
    5. this.name = name;
    6. this.age = age;
    7. System.out.println("带有两个参数的构造代码块!");
    8. }
    9. //实例代码块
    10. {
    11. name = "caocao";
    12. System.out.println("构造代码块/非静态代码块/实例化代码块!->初始化非静态的数据成员");
    13. }
    14. }
    15. public class Tesk2 {
    16. public static void main(String[] args) {
    17. Student student1 = new Student("xiaowen", 10);
    18. System.out.println(student1.name);
    19. }
    20. }

    6226810d1a1f444ba015e85f474905ba.png

     1️⃣由此代码可知:在调用构造方法之前,先执行的是实例代码块(非静态代码块)

    2261270ac84b41f2aa0417d303663bb5.png

    由于在调用构造方法之前,先执行的是实例代码块,则最后打印不是caocao,而是xiaowen 

    可以简单认为,编译器编译好代码之后,会把非静态代码块拷贝到构造代码块的最前面

    2️⃣如果都是非静态的,那么看定义的顺序。谁在前,最后就是哪个值

    7dd9a150234b4968a65c44a50bcbee82.png

    📗3.4 静态代码块

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

    1. class Student {
    2. public String name;
    3. public int age;
    4. public static String classRoom = "107java直播间"; //上课的教室
    5. //实例代码块
    6. {
    7. name = "caocao";
    8. System.out.println("构造代码块/非静态代码块/实例化代码块!->初始化非静态的数据成员");
    9. }
    10. //静待代码块
    11. static {
    12. System.out.println("静态代码块--》初始化静态数据成员/ 提前准备一些数据");
    13. }
    14. //构造方法
    15. public Student() {
    16. System.out.println("不带参数的构造方法!");
    17. }
    18. }
    19. public class Tesk2 {
    20. public static void main(String[] args) {
    21. Student student1 = new Student();
    22. }

    2159abdd794249a29cd0db8422b3bf7e.png

     静态代码块先执行(大的角度--------先执行静态代码块、再执行非静态代码块、最后执行构造方法)

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

    📁4. 对象的打印

    1. public class Tesk {
    2. public static void main(String[] args) {
    3. Person person = new Person("zhangsan",10);
    4. person.setName("gaobo");
    5. System.out.println(person.getName());
    6. person.show();
    7. /*person.name = "zhangsan";
    8. person.eat();*/ //error
    9. }
    10. }
    11. public class Person {
    12. String name;
    13. String gender;
    14. int age;
    15. public Person(String name, String gender, int age) {
    16. this.name = name;
    17. this.gender = gender;
    18. this.age = age;
    19. }
    20. public static void main(String[] args) {
    21. Person person = new Person("Jim","男", 18);
    22. System.out.println(person);
    23. }
    24. }
    25. // 打印结果:day20210829.Person@1b6d3586

    ➡️如果想要默认打印对象中的属性该如何处理呢?答案:重写toString方法即可。

    1. public class Person {
    2. String name;
    3. String gender;
    4. int age;
    5. public Person(String name, String gender, int age) {
    6. this.name = name;
    7. this.gender = gender;
    8. this.age = age;
    9. }
    10. @Override
    11. public String toString() {
    12. return "[" + name + "," + gender + "," + age + "]";
    13. }
    14. public static void main(String[] args) {
    15. Person person = new Person("Jim","男", 18);
    16. System.out.println(person);
    17. }
    18. }
    19. // 输出结果:[Jim,男,18]

    ✨总结:

    对于你想输出一个对象的引用的值的时候,如果你没有自己写一个toS挺方法,那么就会调用Object这个类的方法。

    如果自己写了,就会调用自己的!!!

     

     

     

     

     

  • 相关阅读:
    security异常处理机制
    LitePal for Android
    Java入门-----基本语法
    大数据库练习题
    第四部分:Spdlog日志库的核心组件分析-logger
    前缀和题型总结 II :leetcode 1402、1310、1371、1171
    MySQL - 索引优化
    [Apple][macOS]没有原来的苹果设备接收验证码,怎么激活新的苹果设备(Macbook、iPhone之类)?
    【题解】金牌导航-高斯消元/Luogu P3232 游走
    【ARM Coresight 系列文章 3.5 - ARM Coresight -- JTAG-DP(JTAG Debug Port) 详细介绍】
  • 原文地址:https://blog.csdn.net/m0_72161237/article/details/127786300