java static关键字

static关键字用途

《Java编程思想》中讲到:
static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通关过类本身来调用static方法。这实际上正是static方法的主要用途。
简而言之:方便在没有创建对象的时候进行调用(方法/变量)
显然,被static关键字修饰的方法或变量不需要依赖对象来进行访问,只要类被加载了,就可以通过类名去进行访问。


(1)static变量
static变量又被称为静态变量,静态变量和非静态变量的区别:静态变量被所有对象共享,在内存中只有一个副本,当且仅当在类被初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。


(2)static方法
static方法又被称为静态方法,在静态方法中不能访问非静态成员变量和非静态成员方法,但非静态方法可以调用静态方法和静态成员变量。因为静态方法不依附任何对象,而非静态成员方法/变量都是必须依赖具体的对象才能够被调用的。
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。


(3)static代码块
static代码块的作用就是形成静态代码块以优化程序性能。static块可以置于类中任何地方,类中可以有多个static代码块。在类被初次加载的时候,会按照每个static代码块的顺序来执行每个static块,并且只会执行一次。

为什么说static块可以优化性能,那是因为static在类加载时只执行一次。

常见误区
  • static是否会改变类中成员的访问权限?

java中的static关键不会影响成员或方法的作用域,影响其作用域的只有private, public, protected这几个关键字。
访问权限

  • this能访问静态成员变量吗?
public class STATICAPP {
    static int  num = 3;

    public void printValue(){
        int num  = 33;
        System.out.println(this.num);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        STATICAPP sa = new STATICAPP();
        sa.printValue();    
    }
}
输出结果:3

this表示当前实例对象,和成员方法中的局部变量无关。

  • static能作用于局部变量吗?
    记住:static是不允许用来修饰局部变量的,Java语法规定
常见面试题

下面列举一些面试笔试中经常遇到的关于static关键字的题目,仅供参考,如有补充欢迎下方留言。
1.下面这段代码的输出结果是什么?

public class Test extends Base{

    static{
        System.out.println("test static");
    }
    public Test(){
        System.out.println("test constructor");
    }

    public static void main(String[] args) {
        new Test();
    }
}

class Base{

    static{
        System.out.println("base static");
    }

    public Base(){
        System.out.println("base constructor");
    }
}
base static
test static
base constructor
test constructor

开始执行时,首先要找到main方法,在执行main方法前,要首先加载Test类,当加载Test类时,发现它继承Base类,要首先加载Base类,这个时候发现Base类中存在static代码块,加载执行static块,加载Base完成后加载Test类,Test类中也存在static代码块,执行后开始执行main方法,首先调用Test父类的构造方法,然后调用Test自身的构造方法,就出现了上面的结果。


2.这段代码的输出结果是什么?

public class Test {
    Person person = new Person("Test");
    static{
        System.out.println("test static");
    }

    public Test() {
        System.out.println("test constructor");
    }

    public static void main(String[] args) {
        new MyClass();
    }
}

class Person{
    static{
        System.out.println("person static");
    }
    public Person(String str) {
        System.out.println("person "+str);
    }
}


class MyClass extends Test {
    Person person = new Person("MyClass");
    static{
        System.out.println("myclass static");
    }

    public MyClass() {
        System.out.println("myclass constructor");
    }
}
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

同样的道理,在执行开始,要先找到main方法,在执行main方法前,加载Test类,执行Test中的static块,然后执行main方法,new MyClass()之前先加载MyClass类,然后开始创建对象:因为MyClass继承Test类,所以要先初始化父类的成员变量(此时父类Test已经加载),因此会执行Test中的Person person = new Person(“Test”),此时还没有加载Person类,加载Person类执行Person类中static块,调用Person构造方法,实例化Person类,然后调用父类Test构造器,然后初始化自身,同样的道理,先初始化自己的成员变量,调用Person类的构造函数(此时Person已经加载过),最后执行MyClass的构造器。


3.这段代码的输出结果是什么?

public class Test {

    static{
        System.out.println("test static 1");
    }
    public static void main(String[] args) {

    }

    static{
        System.out.println("test static 2");
    }
}
test static 1
test static 2

参照上述的分析过程:在执行main方法前,加载Test类,顺序执行Test类中的static块


参考文献:
http://www.cnblogs.com/dolphin0520/p/3799052.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值