static关键字

本文参考一些博客文章,感谢大佬们的分享,如有侵权,联系删除!

一、static的用途:

    1、static方法

          ①静态方法没有this,直接通过  类名.方法名 就可以访问,不依赖于任何对象访问

          ②静态方法里面不能调用非静态方法,也不能访问类的非静态成员变量;但是非静态方法里面可以访问静态方法和静态成员变量。

          ③在方法体里面不能使用static

          ④如果想在不创建对象的情况下调用某个方法,就使用static关键字修饰该方法

          ⑤静态方法也可以像普通方法一样通过对象调用

          ⑥示例代码:

      public static String str = "原始值";
      public String str1 = "2";
      /*测试静态方法Start*/
      public static void testStatic(){
            //static Stringstr1 = "1";  //编译报错
            //noStatic();     //编译报错
            System.out.println("测试static" + str);
            //System.out.println(str1);//编译报错
      }
      public void noStatic(){
            //static String str2 = "1";  //编译报错
            testStatic();
            System.out.println(str);
            System.err.println(str1);
      }

    2、static变量

          ①静态变量被所有的对象共享,在内存中只有一个副本,当且仅当在类初次加载时会被初始化。

          ②非静态变量是对象所拥有的,在创建对象的时候初始化多个副本,各个对象拥有的副本互不影响。

package test;
import java.sql.Date;
public class TestStatic {
      public static String str = "原始值";
      public String str1 = "2";
      public static void main(String[] args) {
            /*测试static静态变量Start*/
            TestStatic static1 = new TestStatic();
            System.out.println("通过   TestStatic.静态变量=" +  TestStatic.str + ";hashcode = " + TestStatic.str.hashCode());  
            System.out.println("通过   TestStatic的对象1.静态变量=" +  static1.str + ";hashcode = " + static1.str.hashCode());
            static1.str = "修改之后的值";
            System.out.println("获取修改后的静态变量    通过   TestStatic的对象1.静态变量=" + static1.str + ";hashcode = " + static1.str.hashCode());
            
            TestStatic static2 = new TestStatic();
            System.out.println("通过   TestStatic的对象2.静态变量=" +  static2.str + ";hashcode = " + static2.str.hashCode());
            System.out.println("通过   TestStatic.静态变量=" +  TestStatic.str  + ";hashcode = " + TestStatic.str.hashCode());
            /*测试static静态变量End*/
            
            /*测试非静态变量,与静态变量相比较Start*/
            TestStatic static3 = new TestStatic();
            System.out.println("通过对象调用非静态变量=" + static3.str1 +  "; hashcode = " + static3.str1.hashCode());
            static3.str1 = "str1修改之后的值";
            System.out.println("通过对象调用修改后的非静态变量=" +  static3.str1 + "; hashcode = " + static3.str1.hashCode());
            
            TestStatic static4 = new TestStatic();
            System.out.println("通过对象调用非静态变量=" + static4.str1 +  "; hashcode = " + static4.str1.hashCode());
            /*测试非静态变量,与静态变量相比较End*/
      }
}

    3、static代码块

        ①使用static写静态代码块,来优化程序性能。

        ②static代码块可以在类中的任意地方,一个类中可以有多个静态代码块,

        ③在类除此被加载的时候,会按照顺序来执行静态代码块,并只执行一次。

        ④static可以优化程序性能,看下面这个例子  :

package test;
import java.sql.Date;
public class TestStatic {
    public TestStatic(){
    }      
    /*测试静态代码块Start*/
    private Date birthday;
    public TestStatic(Date birthday){
        this.birthday = birthday;
    }
    boolean isBornBoomer() {
        Date startDate = Date.valueOf("1946");
        Date endDate = Date.valueOf("1964");
        return birthday.compareTo(startDate)>=0 &&  birthday.compareTo(endDate) < 0;
    }
}

                 上面这个例子判断了birthday日期是否在1946和1964之间,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,改为以下代码会更好:

package test;
import java.sql.Date;
public class TestStatic {
    //改为以下代码:
    private Date birthday;
    private static Date startDate,endDate;
    static{
        startDate = Date.valueOf("1946");
        endDate = Date.valueOf("1964");
    }
     
    public TestStatic(Date birthday) {
        this.birthday = birthday;
    }
     
    boolean isBornBoomer() {
        return birthday.compareTo(startDate)>=0 &&  birthday.compareTo(endDate) < 0;
    }
      /*测试静态代码块End*/

}

二、static关键字使用误区    

    1、static不会影响类中成员的访问权限

         在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。

   2、可以通过this访问静态成员变量,看下面一个例子: 

public class test {
      static int value = 33;
      public static void main(String[] args) {
            new test().printValue();
      }
      private void printValue(){
            int value = 3;
            System.out.println(this.value); //33
      }
}

        注意:

            ①this代表当前对象,上面例子通过new test()调用printValue(),当前对象就是通过new test()生成的对象。

          ②static成员变量是被对象所共有的,所以在 printValue中的this.value的是33;而printValue方法的局部变量value不可能与this关联。

         ③静态成员变量虽然独立于对象,但是也可以通过对象去访问,只要权限足够,所有的静态方法和静态成员变量都可以通过对象去访问。

 

    3、static不允许用来修饰局部变量,语法规定。

    4、static不允许用来修饰构造器,可以修饰内部类、内部抽象类和内部接口(不能修饰接口,只能修饰内部接口);不能姿势外部类、外部抽象类和外部接口。

 

三、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是程序的入口。

            ②但是在执行main方法之前必须先加载test类,加载test类的时候发现test类继承Base类,就先去加载Base类。

            ③加载Base类的时候发现Base类中有静态代码块,就执行了Base类中的static块。打印出base static

            ④Base类加载完之后继续加载test类,发现test类页游静态代码块,就执行test类中的静态代码块,打印出test static

            ⑤在加载完所有的类之后,就开始创建test对象,而创建对象时会先调用父类的构造器,然后再调用自身构造器。所以先打印出base constructor,再打印出test constructor 

 

    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

        以上代码执行过程:

            ①先加载test类,因此先执行test类中的静态代码块,输出test static。

            ②接着执行new MyClass(),此时需要先加载MyClass类,加载MyClass类时发现MyClass继承test,但是test已经加载完成,

            所以只加载MyClass类,加载MyClass类时就执行了MyClass中的static块,输出myclass static。

         ③加载完MyClass之后,通过MyClass构造器生成对象,而在生成对象时,必须先初始化父类的成员变量,就会执行Person person = new Person()

            因此会先加载Person类并执行Person类中的static块,输出person static。

         ④截止执行父类的构造器,完成父类的初始化,然后初始化自身因此会接着执行MyClass中的Person person = new 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

 

四、补充资料

    1、静态内部类(用的比较少):

        https://www.cnblogs.com/aademeng/articles/6192954.html

    2、静态导包(用的比较少):

        https://blog.csdn.net/zhangxichao100/article/details/56672844

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值