1、static介绍

static关键字一直是各大企业中面试常常会问到的问题,主要考察面试者的基础是否扎实,下面来介绍一下static关键字。

Java中static表示“全局”或者“静态”的意思,可以用来修饰成员变量、成员方法、代码块、内部类和导包。在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载了,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象,所以被static修饰的成员变量和成员方法可以直接使用类名调用。

class Person{
    private static int num=0;

    public Person() {
        num++;
    }

    public static void plus(){
        System.out.println(Person.num);
    }

    public static void main(String[] args) {
        new Person();
        new Person();
        Person.plus();
        plus();
    }
}
//结果:2、2

2、static变量

static修饰的成员变量称作静态变量,静态变量被所有的对象所共享,在内存中只有一个,它会随着类的加载而加载。

另外主要:static是不允许用来修饰局部变量

提到静态变量我们来看静态变量和非静态变量的区别:

静态变量(类变量):静态变量被所有的对象所共享,也就是说我们创建了一个类的多个对象,多个对象共享着一个静态变量,如果我们修改了静态变量的值,那么其他对象的静态变量也会随之修改。

非静态变量(实例变量):如果我们创建了一个类的多个对象,那么每个对象都有它自己该有的非静态变量。当你修改其中一个对象中的非静态变量时,不会引起其他对象非静态变量值得改变。

class Person{
    private static int num;
    private int num1;

    public static void main(String[] args) {
        Person p1 = new Person();
        Person p2 = new Person();

        Person.num=10;
        p1.num1=11;

        Person.num=100;
        p2.num1=111;

        System.out.println(Person.num);
        System.out.println(p1.num);
        System.out.println(p2.num);
        System.out.println(p1.num1);
        System.out.println(p2.num1);
    }
}

从运行结果来看,static变量的值是相同的,说明是共享的,而非静态变量他们的值则不相同,说明依赖于实例。虽然static修饰的变量它不依赖类特定的实例,但它毕竟也是类中的一个属性,也是可以通过类的实例来调用的,只不过属性的值是共享的而已。但是最好还是用类名调用

3、static方法

static修饰的成员方法称作静态方法,这样我们就可以通过“类名. 方法名”进行调用。由于静态方法在类加载的时候就存在了,所以它不依赖于任何对象的实例就可以进行调用,因此对于静态方法而言,是木有当前对象的概念,即没有this、super关键字的。因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。

并且由于独立于任何实例,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。举个简单的例子:

class Person{

    public static void main(String[] args) {
        Person p=new Person();
        p.show1();
    }

    public void show1(){
        System.out.println("非静态方法show1()...");
        show2();
        show3();
    }

    public static void show2(){
        System.out.println("静态方法show2()...");
        //这里编译会报错Non-static method 'show1()' cannot be referenced from a static context
        //show1();
    }
    public static void show3(){
        System.out.println("静态方法show3()...");
        show2();
    }
}

4、static代码块

被static修饰的代码块也叫静态代码块,会随着JVM加载类的时候而加载这些静态代码块,并且会自动执行。它们可以有多个,可以存在于该类的任何地方。JVM会按照它们的先后顺序依次执行它们,而且每个静态代码块只会被初始化一次,不会进行多次初始化。

示例:

public class Person{

    static {
        System.out.println("Person类静态块");
    }

    public Person() {
        System.out.println("Person类构造器");
    }

    public static void main(String[] args) {
        new Son();
        System.out.println("-------");
        new Son();
    }
}

class Son extends Person{
    static {
        System.out.println("Son类静态块");
    }

    public Son() {
        System.out.println("Son类构造器");
    }
}

运行结果:

从运行结果分析:首先运行main()方法,然后JVM就会加载类,因为Son类继承了Person类,所以会先加载父类Person类,再去加载子类Son。由于静态代码块会随着类的加载而加载,所以先输出父类中静态代码块内容"Person类静态块",然后输出子类中静态代码块内容"Son类静态块"。加载完类之后执行main()方法内容,先new了第一个Son实例,由于子类构造器中默认调用了super(),所以先输出父类构造器的内容,再输出子类构造器的内容。之后又new了第二个Son实例,却是输出的构造器的内容,说明static静态块只加载了一次。结论:静态代码块是先加载父类的静态代码块,然后再加载子类静态代码块,是随着类的加载而加载,而且只会加载一次。

补充:因为入口main()是个方法,也需要用类去调用,所以类的加载优先级>main()方法。

5、static内部类

static修饰内部类的用法很少,毕竟内部类用的就不是很多,一般在源码中才能看见。但是就是有这么一个特殊的用法是用static修饰内部类。普通类是不允许声明为静态的,只要内部类才可以,被static修饰的内部类可以直接作为一个普通类来使用,而不需先实例一个外部类。

static修饰内部类注意几点:

  • 静态内部类只能访问外部类的静态成员,否则编译会报错。
  • 不管是静态方法还是非静态方法都可以在非静态内部类中访问。
  • 如果需要调用内部类的非静态方法,必须先new一个OuterClass的对象outerClass,然后通过outer。new生成内部类的对象,而static内部类则不需要。

简单举例:

public class OuterClass {
    private static int num=6;
    // 静态内部类
    public static class InnerStaticClass{
        public void print() {
            System.out.println("静态内部类方法print()=="+num);
        }
    }
    //非静态内部类
    public class InnerClass{

        public void display(){
            System.out.println("非静态内部类方法display()=="+num);
            show();
        }
    }
    public void show(){
        System.out.println("外部类的show()方法=="+num);
    }

    public static void main(String[] args) {
        //非static对象实例
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass innerClass = outer.new InnerClass();
        innerClass.display();
        //static对象实例
        OuterClass.InnerStaticClass staticClass=new OuterClass.InnerStaticClass();
        staticClass.print();
    }
}

6、static导包

这个知识点非常的冷门,基本上很少的地方会用,我们只需要了解一下即可,用static修饰导包的格式是 import static  包名,static不能写在import前面,这样可以指定导入某个类中的指定静态资源,并且不需要使用类名.资源名,可以直接使用资源名。

来看一下案例:

import static java.lang.Math.*;

public class StaticTest {
    public static void main(String[] args) {
        System.out.println(sqrt(9));
        System.out.println(abs(-12));
    }
}
//结果:3、12

从上面的案例看出,使用import static我们导入了Math类下的所有静态资,所以我们就可以直接使用sqrt(9)、abs(-12)静态方法了。

这样在写代码的时候确实能省一点代码,但是会影响代码可读性,所以一般情况下不建议这么使用。

7、总结

static是非常重要的一个关键字,它的用法也很丰富,以下总结为:

①、static可以用来修饰成员变量、成员方法、代码块、内部类和导包。

②、用来修饰成员变量,将其变为静态变量,从而实现所有对象对于该成员的共享,通过“类名.变量名”即可调用。

③、用来修饰成员方法,将其变为静态方法,可以直接使用“类名.方法名”的方式调用,常用于工具类。

④、静态方法中不能使用关键字this和super 。

⑤、静态块用法,将多个类成员放在一起初始化,使得程序更加规整,其中理解对象的初始化过程非常关键。

⑥、静态代码块是先加载父类的静态代码块,然后再加载子类静态代码块,而且只会加载一次。

⑦、static修饰成员变量、成员方法、代码块会随着类的加载而加载。

⑧、静态导包用法,将类的方法直接导入到当前类中,从而直接使用“方法名”即可调用类方法,更加方便,但是代码的可读性降低。

夯实Java基础(七)——Static关键字的更多相关文章

  1. Java基础之static关键字的用法

    Java中的static关键字主要用于内存管理.我们可以应用static关键字在变量.方法.块和嵌套类中. static关键字属于类,而不是类的实例.        静态(static)可以是: 变量 ...

  2. Java基础系列--static关键字

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8477914.html 一.概述 static关键字是Java诸多关键字中较常使用的一个,从 ...

  3. 【Java基础】static关键字相关

    static关键字特点: 随着类的加载而加载. 优先于对象存在. 被所有对象共享 可以直接被类名调用. 使用注意: 静态方法只能访问静态成员. 但非静态成员可以访问静态成员. 静态方法中不能使用thi ...

  4. Java基础(十)--static关键字

    static关键字通常应用在字段.方法.静态块,还有冷门一点的内容:静态内部类.静态导入 static字段: static字段也就是静态变量,是属于类的,被所有的对象所共享,只有当类初次加载的时候保存 ...

  5. Java基础(二)-static关键字分析

    static关键字是我们在编程中经常会使用到的,但有些可能只知其然而不知其所以然.下面介绍static关键字的作用再通过例子结合说明. static关键字共有五种作用(先说明static所修饰的不会改 ...

  6. java基础 2 static关键字

    2. static关键字 变量:静态变量在内存中只存在一份,只在类第一次实例化时初始化一次,同时类所有的实例都共享静态变量,可以直接同过类名                    来访问他. 方法:静 ...

  7. 【Java基础】static关键字的理解

    修饰范围: 可以修饰成员变量和成员方法.静态的特点: A:随着类的加载而加载 B:优先于对象存在 C:被类的所有对象共享 这其实也是我们判断该不该使用静态的依据. 举例:饮水机和水杯的问题思考可通过类 ...

  8. 夯实Java基础系列4:一文了解final关键字的特性、使用方法,以及实现原理

    目录 final使用 final变量 final修饰基本数据类型变量和引用 final类 final关键字的知识点 final关键字的最佳实践 final的用法 关于空白final final内存分配 ...

  9. 094 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 04 static关键字(续)

    094 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...

  10. 093 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 03 static关键字(下)

    093 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...

随机推荐

  1. 如何使用 Docker 安装 Jenkins

    说在前面 本篇内容非常简单,仅讲述了如何快速在 Docker 上部署一个 Jenkins 实例,不涉及其他. 本文实验环境: 操作系统:Centos 7.5 Docker Version:18.09. ...

  2. 在eclipse中使用git创建本地库,以及托管项目到GitHub超详细教程

    关于安装git的教程,由于比较简单,并且网上教程特别多,而且即使不按照网上教程,下载好的windows版本git,安装时候一路默认设置就行. 安装好之后,在桌面上有git图标:右键菜单中有Git Ba ...

  3. Leetcode 195 Tenth Line

    Given a text file file.txt, print just the 10th line of the file. Example: Assume that file.txt has ...

  4. Bean property 'transactionManagerBeanName' is not writable or has an invalid set

    [2017-02-07 11:38:48,458]-[localhost-startStop-1]-[org.springframework.beans.factory.support.Default ...

  5. 解决Tomcat catalina.out 不断膨胀,导致磁盘占用过大的问题

    到服务器上看了一下任务中心的日志情况,膨胀的很快,必须采取措施限制其增长速度. 我们采用Cronlog组件对此进行日志切分,官网http://cronolog.org/一直未能打开,只能从其它地方寻找 ...

  6. Android开发-百度地图之电子围栏

    功能实现:根据经纬度创建一个坐标,判断该坐标是否在指定圆形覆盖范围内 两个计算方法,直接套用: /** * 地球半径 */private static double EARTH_RADIUS = 63 ...

  7. linux 不重启识别新添加的硬盘

    1.fdisk -l 看有没有新的磁盘 oebiotech@hadoop08:/media/nbc9$ sudo fdisk -l |grep sdl 2.查看主机总线 oebiotech@hadoo ...

  8. Java编程思想:利用内部类实现的工厂模式

    public class Test { public static void main(String[] args) { Factories.test(); } } /* 设计模式之禅中的工厂模式是这 ...

  9. 【基础算法-模拟-例题-金币】-C++

    原题链接:P2669 金币 这道题目完全是一道模拟题,只要按照题目中的加金币的算法和sum累加就可以很轻易得出最终答案. 说一下有一些点需要注意: 1.用i来计每天发的金币数,n来计已经拿了金币的天数 ...

  10. 远程调试出现DEP0600: 部署失败。无法通过新部署管道进行部署错误解决

    昨天我连接树莓派调试没问题,今天来的时候却总是出现DEP0600: 部署失败.无法通过新部署管道进行部署.错误 我怀疑是环境问题,然后发现蓝莓派上面没有远程调试监视器(MSVSMON.EXE)进程,怀 ...