《JavaSE》---13.<面向对象系列之(附:static关键字及final关键字)>

目录

系列文章目录

前言

一、static修饰成员变量

1.1简单描述:

1.2用static修饰的好处:

1.3属于类而不属于对象

1.4如何访问更加合理:

1.5按static的修饰来分类

小结:

二、static修饰成员方法

2.1简单描述:

2.2访问静态成员方法

2.2.1代码示例:

2.2.2输出结果:

2.3在静态成员方法中不能直接调用普通成员方法

2.3.1代码示例

静态成员方法不能直接调用普通成员方法的原因

如何在静态成员方法中调用普通成员方法

代码示例:

2.3.2输出结果

2.4在普通成员方法中可以直接调用静态成员方法

2.5同理不能在静态成员方法中用this.去引用普通成员变量

代码示例:

代码示例:

小结:

三、 static修饰代码块

3.1代码块的概念及分类

3.1.1代码块的概念

3.1.1代码块的分类

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

3.2.1构造块的概念

3.2.2构造块的作用与用法

3.3 ③静态代码块

3.3.1静态代码块的概念,作用,书写位置

3.3.2静态代码块的用法

3.4总结

执行顺序:

四、继承中代码的执行顺序(加上代码块)

五、static成员变量初始化

六、final关键字


系列文章目录

第一章 Java 类和对象

第二章 Java 封装

第三章 Java 继承

第四章 Java 多态

附:static关键字及final关键字

附:this和super


前言

本篇博客主要讲解Java基础语法中的

面向对象系列之

static关键字final关键字,

1.static关键字修饰成员变量、简述、好处及如何访问。

2.static关键字修饰成员方法、如何调用static修饰的成员方法。

3.static关键字修饰代码块、及代码块的概念、用法。

4.final关键字修饰基本数据类型、引用数据类型、成员变量、成员方法、类的意义。


      大家好,本人是普通一本的在校大学生一枚,目前在学习java。之前也学了一段时间,但是没有发布博客。本人现在已经大二结束了,开学就大三了,时间过的真的很快。我会利用好这个暑假,来复习之前学过的内容,并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区进行讨论!!!

      喜欢我文章的兄弟姐妹们可以点赞,收藏和评论我的文章。喜欢我的兄弟姐妹们以及也想复习一遍java知识的兄弟姐妹们可以关注我呦,我会持续更新滴,并且追求完整。
望支持!!!!!!一起加油呀!!!!

语言只是工具,不能决定你好不好找工作,决定你好不好找工作的是你的能力!!!!!

学历本科及以上就够用了!!!!!!!!!!!!!!!!!!!!!!!!!!!!


一、static修饰成员变量

1.1简单描述:

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

当static修饰成员变量时,这个成员变量将不再属于对象,而是属于类。依赖于类,而不再依赖于对象,需要用类名去引用来访问到这个变量。而不再用实例化出来的对象去引用来访问。此时这个变量在类被加载的时候就被创建出来。(虽然也可以通过对象去引用,这样合法,能编译通过但是不合理,不建议这样写代码)

1.2用static修饰的好处:

当我们想要被实例化的每个对象都有一个共同的变量,存放相同的值。我们就不需要去给每个对象的这个变量去赋值。而是通过类去赋值,这样每个实例化出来的对象都可以拥有这样值。简化了我们代码的书写。

例如:

我们定义一个学生类。我们的每一个学生都在14班。此时就可以用static去修饰这个成员变量了。只需要初始化一次,而每个被实例化出来的对象都可以去用类名.去访问到这个变量。

1.3属于类而不属于对象

我们知道对象是存储在JVM中的堆区的。当被static修饰后,这样变量是存放在方法区的。此时每一个被实例化出来的对象都共用这一份被static修饰的,存放在方法区的变量。也就是说这个成员变量将不再属于对象了。而是属于这个类。

1.4如何访问更加合理:

通过类名去引用。不需要实例化对象。也可以访问。如下代码示例分析

class Stu{
//非静态成员变量/普通成员变量
    public String name; //学生姓名
    public String gender; //学生性别
    public short age; //学生年龄
    public double score; //学生分数
//静态成员变量
    public static int classRoom; //学生班级


    //成员方法
    public void DoClass(){
        System.out.println(name + "在上课");
    } //
    public void DoHomework(){
        System.out.println(name + "在做家庭作业");
    }
    public void Exam(){
        System.out.println(name + "在考试");
    }
}

public class Test {
    public static void main(String[] args) {
        Stu.classRoom = 14;
        System.out.println("学生班级:"+Stu.classRoom);

        System.out.println("-----------------------");
        Stu student1 = new Stu();//new一个对象后,
//我们发现用student1也可以去访问到这个变量,但是会出现警告
        System.out.println("班级:"+student1.classRoom);
//这样做是可以编译通过,但是不合理。不建议这样去写代码
    }
}

输出结果:

学生班级:14
-----------------------
班级:14 

我们创建了一个学生类。我们假设我们要实例化的学生对象都在同一个班级14班。因此我们用static去修饰classRoom。由于用static修饰的成员变量不再属于对象。因此我们不需要再去实例化一个对象也可以访问到这个成员变量。

但是我们发现。new一个对象后,用student1去引用。虽然出现警告但也可以去访问到这个变量,
这样做是可以编译通过,但是不合理。因为这样变量是属于类的,不再属于对象,假设用对象去引用我们一般认为这样变量是属于这个对象的。显然classRoom不属于它。因此不建议这样去写代码
 Stu.classroom这样去访问。才是最合理的

1.5按static的修饰来分类

①静态成员变量:也叫做类变量。由static修饰的成员变量我们称之为静态成员变量。是属于类的,不依赖于对象,用类名去引用访问,类被加载时,这个变量就被创建出来。

②非静态成员变量:也叫做普通成员变量。没有被static修饰的成员变量我们称之为非静态成员变量。是属于对象的,用对象去引用访问。对象被实例化出来。这个变量才被创建出来。

小结:

1. static修饰的成员变量 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
2. static修饰的成员变量既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
3. static修饰的成员变量是存储在方法区当中的
4. 生命周期伴随类的一生 ( 即:随类的加载而创建,随类的卸载而销毁 )
5.static修饰的成员变量称之为静态成员变量,也叫作类变量。没有被static修饰的成员变量称作非静态成员变量,也叫做普通成员变量。

二、static修饰成员方法

2.1简单描述:

了解了用static修饰的成员变量之后,一通百通。

static修饰其他代码时也是类似的道理。用static修饰的成员方法,我们称之为静态成员方法。也叫做类方法。此时这个成员方法也将属于类而不再属于对象。类似的道理,我们用类名.去引用这个成员方法。(用对象去引用也是合法但是不合理)

我们就不再去像成员变量那样详细去解释每一个点了,因为都是类似的,我们直接看

2.2访问静态成员方法

2.2.1代码示例:

class Stu{
    //成员变量
//普通成员变量
    public String name; //学生姓名
    public String gender; //学生性别
    public short age; //学生年龄
    public double score; //学生分数
//静态成员变量
    public static int classRoom; //学生班级


    //成员方法
    //普通成员方法
    public void DoClass(){
        System.out.println(name + "在上课");
    } //
    public void DoHomework(){
        System.out.println(name + "在做家庭作业");
    }

    //静态成员方法
    public static void Exam(){
        System.out.println( "所有学生都在考试");
    }
}

public class Test {
    public static void main(String[] args) {
        Stu.Exam();
        System.out.println("-----------------------");
        Stu student1 = new Stu();//new一个对象后,我们发现用student1也可以去访问到这个静态方法,但是会出现警告
        student1.Exam();//这样做是可以编译通过,但是不合理。不建议这样去写代码
    }
}

2.2.2输出结果:

所有学生都在考试
-----------------------
所有学生都在考试

类似的静态成员方法我们用类名Stu.去访问。虽然我们实例化出来的对象,也能访问到,但是不建议这样写。

 小结:

当成员方法加了static之后,调用这样方法不再需要对象去调用。而是通过类名去引用。不再依赖于对象。而不加static的方法需要我们用对象的引用才能访问到。

2.3在静态成员方法中不能直接调用普通成员方法

如下面的代码示例!

我们知道如果是非静态成员方法,我们可以直接在其中一个成员方法中去调用另一个成员方法,只需要写出对应的方法名和传入相应的参数即可。但是在静态成员方法中就不能这样直接调用普通成员方法了

2.3.1代码示例

静态成员方法不能直接调用普通成员方法的原因

 我们可以看到这样写会编译报错。因为普通成员方法是依赖对象的。而静态成员方法不依赖于对象。因此在类被加载时,静态成员变量就会被创建出来,而普通成员变量只有在类被实例化为对象时才被创建出来,因此这两者是矛盾的。当类被加载时,还没有对象被实例化时,又如何去调用那个还没有产生的普通成员方法呢!!!因此这样的写法是错误的。

如何在静态成员方法中调用普通成员方法

因为只有类被实例化后产生了对象才有了普通成员变量和方法,因此我们需要实例化一个对象,再用对象去调用,才能在静态成员方法中去调用普通成员方法。

代码示例:

class Stu{
    //成员变量
    //普通成员变量
    public String name; //学生姓名
    public String gender; //学生性别
    public short age; //学生年龄
    public double score; //学生分数
    //静态成员变量
    public static int classRoom; //学生班级


    //成员方法
    //普通成员方法
    public void DoClass(){
        System.out.println(name+"在上课");
    } //
    public void DoHomework(){
        System.out.println(name + "在做家庭作业");
    }

    //静态成员方法
    public static void Exam(){
        Stu student1 = new Stu();
        student1.name="李华";
        student1.DoClass();
        System.out.println( "所有学生都在考试");
    }
}

public class Test {
    public static void main(String[] args) {
        Stu.Exam();
    }
}

2.3.2输出结果

李华在上课
所有学生都在考试

我们需要在静态成员方法中new一个对象,再用这样对象去引用这个普通的成员方法,才能成功的在静态成员方法中调用普通成员方法。

小结:

在静态成员方法不能直接调用普通成员方法,如果需要调用就必须在静态成员方法中去new一个对象。再通过当前对象的引用去调用才可以。

2.4在普通成员方法中可以直接调用静态成员方法

 这是因为在调用普通成员方法时,静态成员方法早已被创建好了,因此当然可以直接调用喽。

2.5同理不能在静态成员方法中用this.去引用普通成员变量

代码示例:

 我们看到普通成员方法中就可以用this去调用其他成员变量,而在静态方法中不能通过this去调用其他成员变量。这样原因与不能调用普通成员方法同理,普通成员变量也是依赖于当前对象的。

如果非要去引用这个成员变量,只有通过类实例化出来的对象才能去引用这个成员变量。

代码示例:

小结:

1.static修饰的成员方法,称之为静态成员方法,也称作类方法, 不属于某个具体的对象。没有被static修饰的成员方法称之为普通成员方法
2. static修饰成员方法的 可以通过对象调用,也可以通过类名. 静态方法名 (...) 方式调用,更推荐使用类名.来调用。
3.  不能在静态方法中直接访问任何非静态成员方法,如果需要访问,必须在静态方法中实例化一个对象,通过这个对象去访问。
4.  不能在静态方法中直接访问任何非静态成员变量,如果需要访问,必须在静态方法中实例化一个对象,通过这个对象去访问。
5.可以在普通成员方法中调用普通成员方法和静态成员方法。

三、 static修饰代码块

3.1代码块的概念及分类

3.1.1代码块的概念

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

3.1.1代码块的分类

根据代码块定义的位置以及关键字,又可分为以下四种:

①普通代码块(用法非常少见不讲了)
②构造块(实例代码块)
③静态块(静态代码块)
④同步代码块(涉及多线程相关知识)

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

3.2.1构造块的概念

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

书写位置:实例代码块所处的位置在方法的外面,类的里面,与实例成员变量(普通成员变量)处于同一等级。

3.2.2构造块的作用与用法

作用:一般用来初始化普通成员变量

代码示例:

class Stu{
    //成员变量
    //普通成员变量
    public String name; //学生姓名
    public String gender; //学生性别
    public short age; //学生年龄
    public double score; //学生分数
    //静态成员变量
    public static int classRoom = 14; //学生班级

//实例代码块
    {
        this.name = "李华";
        this.gender = "男性";
        this.age = 18;
        this.score = 100;
        System.out.println("实例代码块1");

    }


    //成员方法
    //普通成员方法
    public void DoClass(){
        Exam();//在普通成员方法中可以直接调用静态成员方法
        DoHomework();
        System.out.println(this.name+"在上课");
    } //
    public void DoHomework(){
        System.out.println(this.name + "在做家庭作业");
    }
    public void toShow(){
        System.out.println("学生姓名:" + this.name);
        System.out.println("学生性别:" + this.gender);
        System.out.println("学生年龄:" + this.age);
        System.out.println("学生分数:" + this.score);
    }

    //静态成员方法
    public static void Exam(){
        System.out.println("学生在考试");
    }
}

public class Test {
    public static void main(String[] args) {
        Stu student1 = new Stu();
        student1.toShow();
        student1.DoClass();
    }
}

输出结果:

实例代码块1
学生姓名:李华
学生性别:男性
学生年龄:18
学生分数:100.0
学生在考试
李华在做家庭作业
李华在上课

在实例代码块中可以用this直接给实例成员变量进行赋值,来达到初始化的目的。

再者我们发现在实例代码块中我们输出了“实例代码块1”这段文字。理论上在main方法中。我们并没有调用这个实例代码块。那么这个实例代码块是何时被执行的呢?

我们将实例代码块放在类的最下面。再来输出试试

class Stu{
    //成员变量
    //普通成员变量
    public String name; //学生姓名
    public String gender; //学生性别
    public short age; //学生年龄
    public double score; //学生分数
    //静态成员变量
    public static int classRoom = 14; //学生班级

    //成员方法
    //普通成员方法
    public void DoClass(){
        Exam();//在普通成员方法中可以直接调用静态成员方法
        DoHomework();
        System.out.println(this.name+"在上课");
    } //
    public void DoHomework(){
        System.out.println(this.name + "在做家庭作业");
    }
    public void toShow(){
        System.out.println("学生姓名:" + this.name);
        System.out.println("学生性别:" + this.gender);
        System.out.println("学生年龄:" + this.age);
        System.out.println("学生分数:" + this.score);
    }

    //静态成员方法
    public static void Exam(){
        System.out.println("学生在考试");
    }

    //实例代码块
    {
        this.name = "李华";
        this.gender = "男性";
        this.age = 18;
        this.score = 100;
        System.out.println("实例代码块1");
    }
}

public class Test {
    public static void main(String[] args) {
        Stu student1 = new Stu();
        student1.toShow();
        student1.DoClass();
    }
}

输出结果:

实例代码块1
学生姓名:李华
学生性别:男性
学生年龄:18
学生分数:100.0
学生在考试
李华在做家庭作业
李华在上课

我们发现实例代码块依然是最先被执行的。因此无关在类中实例代码块的位置,它都是最早被执行的。


3.3 ③静态代码块

3.3.1静态代码块的概念,作用,书写位置

概念:使用static定义的代码块称为静态代码块

作用:同理,静态代码块一般用于初始化静态成员变量。

书写位置:静态代码块所处的位置在方法的外面,类的里面,与静态成员变量处于同一等级。

3.3.2静态代码块的用法

在下面的代码中,不仅有静态代码块,还加了上面的实例代码块,不仅如此,我还添加了构造方法。如果又看不懂的也没有关系,你只需要看静态代码块部分就行了。

代码示例:

class Stu{
    //成员变量
    //普通成员变量
    public String name; //学生姓名
    public String gender; //学生性别
    public int age; //学生年龄
    public double score; //学生分数

    //静态成员变量
    public static int classRoom ; //学生班级

    //实例代码块
    {
        this.name = "李华";
        this.gender = "男性";
        this.age = 18;
        this.score = 100;
        System.out.println("实例代码块1");
    }

    //静态代码块
    static {
        classRoom = 14; //静态代码块初始化
        System.out.println("静态代码块1");
    }

    //构造方法
    public Stu(String name, String gender, int age, double score) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.score = score;
        System.out.println("构造方法1");
    }

    //成员方法
    //普通成员方法
    public void DoClass(){
        Exam();//在普通成员方法中可以直接调用静态成员方法
        DoHomework();
        System.out.println(this.name+"在上课");
    } //
    public void DoHomework(){
        System.out.println(this.name + "在做家庭作业");
    }
    public void toShow(){
        System.out.println("学生姓名:" + this.name);
        System.out.println("学生性别:" + this.gender);
        System.out.println("学生年龄:" + this.age);
        System.out.println("学生分数:" + this.score);
        System.out.println("学生班级" + Stu.classRoom);
    }

    //静态成员方法
    public static void Exam(){
        System.out.println("学生在考试");
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println(Stu.classRoom);
        Stu student1 = new Stu("LiHua","man",12,99.9);
        student1.toShow();
        System.out.println("-----------------------");
        Stu student2 = new Stu("ZhangWei","man",11,100);
        student2.toShow();
    }
}

输出结果:

静态代码块1
14
实例代码块1
构造方法1
学生姓名:LiHua
学生性别:man
学生年龄:12
学生分数:99.9
学生班级14
-----------------------
实例代码块1
构造方法1
学生姓名:ZhangWei
学生性别:man
学生年龄:11
学生分数:100.0
学生班级14

如果只看静态代码块的部分,我们发现,它成功的给静态变量classRoom初始化,我们还成功的打印出了这个变量。当然了,我写了这么多代码,除了静态代码块的用法,还想去总结一些别的东西。

比如我们发现,

①分割线后面并没有打印静态代码块;

②并且实例代码块new了一个新对象后,再次被执行了;

③静态代码块位于实例化代码块后面但是却比实例化代码块先执行;

④实例化代码和构造方法都对普通成员变量进行了初始化,但是打印出来的是构造方法初始化的结果。

⑤没有实例化对象依然最先打印出了静态代码块

⑥实例化对象之后才打印出了实例化代码块

这是因为(不是没写完,是在3.4的总结里一一对应了上述问题哦!)

3.4总结

1.静态代码块不管生成多少个对象,它只会执行一次。

2.实例代码块每生成一个对象,就会被执行一次。

3.静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的,比实例化代码块,构造方法执行的早。

4.实例代码块比构造方法更早执行,因此最终的值是被构造方法初始化的

5.静态代码块不依赖于对象的产生。不管有没有对象,只要有类静态代码块都会被执行

6.实例化代码块依赖于对象的产生,只有对象产生了,实例化代码块才会被执行

执行顺序:

静态代码块 > 实例代码块(构造快) > 构造方法

备注:

如果有多个静态代码块,那么就按书写的顺序执行

如果有多个实例化代码块,那么就按书写的顺序执行


四、继承中代码的执行顺序(加上代码块)

我们已经知道

① 静态代码块先执行,并且只执行一次,在类加载阶段执行

② 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行

那么加上继承的关系后,又是怎样的执行顺序呢?

父类的静态代码块 > 子类的静态代码块 > 父类的实例代码块 > 父类构造方法 > 子类的实例代码块 > 子类的构造方法

注意:

第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行,静态代码块只执行一次,它用于初始化静态成员变量。因为它是依赖于类的,因此只需要执行一次就能让每个对象都拥有它的值。


五、static成员变量初始化

注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
①可以在类外,直接进行初始化赋值
②若被private修饰,可以使用Getter and Setter进行初始化
这两种初始化方式就不细说了,注意有以下两种。

5.1 就地初始化

就地初始化指的是:在定义时直接给出初始值,如下如所示。也就不详细说了,我们主要看用静态代码块进行初始化。

5.2 静态代码块初始化

在本章3.3.2我们就讲到了静态代码块初始化

六、final关键字

2.1、final修饰变量


1.final修饰普通变量

final修饰普通变量,会使这个变量变为常量,不能再被更改。

2.final修饰引用变量

final修饰引用变量,会使这个引用变量中存的地址(哈希值),不能被更改。也就是不能让它指向新的空间。如:

final int[] array1 = {1,2,3,4,5}; 不能修改array1中存的这个空间的地址(哈希值),但是可以修改这个空间里存的数据。


2.2、final修饰方法

修饰方法:表示该方法不能被重写


2.3、final修饰类

修饰类:表示此类不能被继承

我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承.

  • 37
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

祁思妙想

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

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

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

打赏作者

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

抵扣说明:

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

余额充值