IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 浅谈static关键字,代码块,继承关系上的执行顺序。 -> 正文阅读

[Java知识库]浅谈static关键字,代码块,继承关系上的执行顺序。

一.static关键字

1.为什么要有static关键字?

之前我们在类中定义成员变量时,每个对象都会包含一份(称为实例变量),因为要使用这些信息来描述具体的对象。假如每个对象的某个属性相同时,那么这个属性大可不必在这个类所创建的每个对象中都存储一份,而是需要让所有对象来共享。在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,而是所有对象共享的。

2.如何使用static关键字?

1.static修饰成员变量

static修饰成员变量,称为静态成员变量(类成员),被放在方法区,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。

public class Person {
    public String name;
    public int age;
    public static String from = "China";
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static void main(String[] args) {
        Person person1 = new Person("zhangsan",12);
        Person person2 = new Person("lisi",12);
        Person person3 = new Person("wangwu",12);
        System.out.println(Person.from);
        //静态成员变量可以通过类名.变量名的方式直接访问
        System.out.println("=====================");
        System.out.println(person1.from);
        System.out.println(person2.from);
        System.out.println(person3.from);
        //也可以通过对象访问,但是from是三个对象共享的
    }
}

运行结果为:

事实上:

1.静态成员变量不属于某个具体的对象,是类的属性,所有对象所共享的,不存储在某个对象的空间中;

2.静态成员变量既可以通过对象访问,又可以通过类名访问,但一般我们推荐使用类名访问;

3.生命周期伴随类的一生,静态成员变量随着类的加载而创建,随类的卸载而销毁。?


2.static修饰成员方法

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

public class Person {
    public String name;
    public int age;
    public static String from = "China";
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static void announce(){
        System.out.println("我是中国人!");
    }
    public static void main(String[] args) {
        Person person1 = new Person("zhangsan",12);
        Person.announce();
        //通过类名.静态成员方法名来调用静态方法
        person1.announce();
        //通过对象名.静态成员方法名来调用静态方法,但不推荐这么做
    }
}

运行结果:

我们可以看出:

1.静态方法不属于某个具体的对象,而是一个类的方法;

2.可以通过对象调用静态方法但是不推荐这么做,我们应该更多的使用类名.静态方法名的方式来调用静态方法;

3.因为静态方法是属于类的不是属于对象的,所以没有隐藏的this引用参数,因此不能在静态方法中访问任何非静态的成员变量。?

4.静态方法中不能调用任何的非静态方法,因为非静态方法有this参数,而在静态方法中调用的时候无法传递this引用;

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

3.static成员变量初始化

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

1.就地初始化(在定义类时直接给出初始值

public class Person {
    public String name;
    public int age;
    public static String from = "China";
    //在定义类时直接给出初始值
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static void announce(){
        System.out.println("我是中国人!");
    }
    public static void main(String[] args) {
        System.out.println(Person.from);
    }
}

运行结果:

?2.静态代码块初始化

我们首先来说一下什么是代码块?

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

1.普通代码块;

2.构造代码块;

3.静态代码块;

4.同步代码块(多线程部分再谈)

1.普通代码块就是定义在方法中的代码块,例如:

public class Person {
    public static void main(String[] args) {
        {
            System.out.println("hahaha");
        }
        //普通代码块,直接使用{}定义;
        System.out.println("heiheihei");
    }
}

运行结果:

看运行结果好像普通代码块并没有什么用,事实上这种用法确实比较少见;

2.构造代码块:

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

例如:

public class Person {
    public String name;
    public int age;
    //实例成员变量
    {
        this.name = "zhangsan";
        this.age = 18;
    }
    //实例代码块
    public static void announce(){
        System.out.println("我是中国人!");
    }
    public static void main(String[] args) {
            Person person = new Person();
        System.out.println(person.age);
        System.out.println(person.name);
    }
}

运行结果:

注意:实例代码块优先于构造方法执行,?因为在编译完成后,编译器会将实例代码块中的代码拷贝到每个构造方法的第一条语句前。

3.静态代码块

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

例如:

public class Person {
    public String name;
    public int age;
    public static String from;
    //实例成员变量
    {
        this.name = "zhangsan";
        this.age = 18;
    }
    //实例代码块
    static{
        from = "中国";
        System.out.println("静态代码块执行!");
    }
    //静态代码块
    public static void announce(){
        System.out.println("我是中国人!");
    }
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
        Person person3 = new Person();
        System.out.println(Person.from);
    }
}

运行结果:

?可以看出我们在上段代码中new了三个Person对象但是静态代码块只执行了一次

注意:1.静态代码块不管生成多少对象,只会执行一次;

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

? ? ? ? ? ?3.如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后顺序依次合并,最终放在生成的<>方法中,该方法在类加载时调用,并且只调用一次。

? ? ? ? ? ?4.实例代码块只会在创建对象时执行,

例如:

public class Person {
    public String name;
    public int age;
    public static String from;
    //实例成员变量
    {
        this.name = "zhangsan";
        this.age = 18;
    }
    //实例代码块
    static{
        from = "中国";
        System.out.println("静态代码块执行!");
    }
    //静态代码块
    public static void announce(){
        System.out.println("我是中国人!");
    }
    public static void main(String[] args) {
        
    }
}

运行结果:

?我们在上端代码的main方法中如果什么都不做,Person类的静态代码块依旧执行!所以静态方法在构造对象之前就会执行

实例代码块,构造方法,静态代码块的执行顺序

看下面这段代码,我们对上述代码段都做出了标记

public class Person {
    public String name;
    public int age;
    public static String from;
    public Person() {
        System.out.println("构造方法执行!");
    }

    //实例成员变量
    {
        this.name = "zhangsan";
        this.age = 18;
        System.out.println("实例代码块执行!");
    }
    //实例代码块
    static{
        from = "中国";
        System.out.println("静态代码块执行!");
    }
    //静态代码块
    public static void announce(){
        System.out.println("我是中国人!");
    }
    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println(person1.age);
        System.out.println(person1.name);
    }
}

运行结果:

?

我们发现总是静态代码块先执行,实例代码块(构造代码块)次之,最后则是构造方法执行。

那么在继承中,这些代码执行的顺序又如何呢?我们来看下面这个例子

?
public class Person {
    public String name;
    public int age;
    public static String from;
    public Person() {
        System.out.println("父类构造方法执行!");
    }

    //实例成员变量
    {
        this.name = "zhangsan";
        this.age = 18;
        System.out.println("父类实例代码块执行!");
    }
    //实例代码块
    static{
        from = "中国";
        System.out.println("父类静态代码块执行!");
    }
    //静态代码块
    public static void announce(){
        System.out.println("我是中国人!");
    }

}
public class Student extends Person{
    public Student() {
        System.out.println("子类构造方法执行!");
    }
    {
        System.out.println("子类实例代码块执行");
    }
    static{
        System.out.println("子类静态方法执行!");
    }
}
public class Main {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

?

运行结果为:

就如执行结果所示,在继承关系中,各种代码的执行顺序为:

1.父类静态代码块执行
2.子类静态方法执行
3.父类实例代码块执行
4.父类构造方法执行
5.子类实例代码块执行
6.子类构造方法执行

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:22:29  更:2022-03-04 15:26:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:05:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码