JAVA static关键字(静态变量和静态方法) 作用理解

首先提一个问题,为什么static关键字有静态一说??

下面我举个例子:

我们定义一个学生类

  • 学生类Student这个模板中有姓名(name)、年龄(age)、学号(num)这些属性。

然后我们实例化三个对象:

  • 第一个学生对象:小明(name)、18(age)、001(num)、所在班级(1班)
  • 第二个学生对象:小红(name)、20(age)、002(num)、所在班级(1班)
  • 第三个学生:小王(name)、22(age)、003(num)、所在班级(1班)

在这个例子中,我们发现三个同学姓名年龄学号都不一样,但是他们都是一个班的同学。首先说明一下,定义一个类,就需要在内存里开辟一块空间,而类内部的属性都属于这个内存空间,那么当我们实例化的时候,又在每个对象中添加一个所在班级的属性,那为什么不将所在班级这个属性放在类中呢,而且这样做节省内存,一旦使用了static关键字,那么这个内容就不在属于对象自己,而是属于类,凡是本类的对象,都共享同一份,比如上面例子中的三个对象共享同一份name、age、num。静态,个人感受就是相对于对象来说,调用方法或者变量不需要实例化,在加载类的时候就已经被加载。

static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。简而言之:方便在没有创建对象的情况下来进行调用(方法/变量)


具体定义

在类当中,使用static修饰符的属性(成员变量)成为静态变量,或者称为类变量,常量称为静态常量,方法称为静态方法或者类方法,不论是静态变量还是静态方法,统称为静态成员,归整个类所有。

静态成员不依赖于对象,换句话说就是不依赖类的特定实例,被整个类所共享。也就是说,只要是static修饰的方法或者变量不需要依赖于对象进行访问,只要这个类被加载,JVM(Java虚拟机)就可以根据类名找到它们。

注意事项:

  • 1.static修饰的成员变量和成员方法属于改类。
  • 2.普通变量和方法从属于对象。
  • 3.静态方法不可以调用非静态成员,否则编译会报错。

成员变量

1.静态变量

  • 运行时,JVM只为静态变量分配一次内存,在加载类的过程中,完成静态变量的内存分配。
  • 在类的内部,可以在任何方法内直接访问静态变量。
  • 在其它类当中,可以通过类名访问改类中的静态变量。
静态变量在类中的作用:
  • 静态变量可以被类中所有的实例共享,因此静态变量可以作为实例之间所共享的数据,增加实例之间的交互性。
  • 如果所有的类都包含一个相同的属性,则可以把该属性定义为类的静态常量类型

2.实例变量

  • 每创建一个实例,JVM就会为实例变量分配一次内存。
  • 在类的内部,可以在任何方法内直接访问静态变量。
  • 在其它类当中,可以通过类名访问该类中的静态变量。

代码演示访问静态变量和实例变量:

public class demo01Static {
    // 使用static修饰过的变量,静态变量。
    public static String str1 = "shuyv";

    public static void main(String[] args) {
        // 实例变量
        String str2 = "dkl";

        // 直接访问静态变量和实例变量
        System.out.println("There are two names : " + str1 + " and " + str2);

        // 通过类名访问静态变量和实例变量
        String strone = demo01Static.str1+ " and " + str2;
        System.out.println("There are two names : " + strone);

        // 通过对象访问静态变量和实例变量
        demo01Static name = new demo01Static();
        name.str1 = name.str1 + " and " + str2;
        String strtwo = name.str1;
        System.out.println("There are two names : " + strtwo);
        
    }

}

三次输出的结果都是:
There are two names : shuyv and dkl

从运行结果来看,静态属性,在main方法中可以直接访问,也可以通过类名访问,还可以实例化对象来访问,总之,静态属性被一个类中的所有实例所共享。


3.静态方法和实例方法

与静态变量相似静态方法即是被static修饰的方法。
反之,实例方法即是没有被static修饰的方法。

静态方法和实例方法的区别:

  • 1.静态方法不需要通过实例化对象进行调用,因此在静态方法中不可以使用this关键字,也不可以直接访问所属类的实例变量和实例方法。
  • 2.在实例方法中可以直接访问所属类的静态变量、静态方法、和实例方法。

代码演示

public class demo02StaticMethod {

    // 定义静态变量
    public static int count = 1;

    // 定义实例方法method1
    public int method1() {
        count++;
        System.out.println("----------------------------------");
        System.out.println(count);  // 在实例方法中可以直接访问静态变量
        return count;
    }

    // 定义静态方法method2
    public static int method2() {
        count += count;
        System.out.println("----------------------------------");
        System.out.println(count);
        return count;
    }

    // 定义静态方法PrintCount
    public static void PrintCount() {
        count += 2;
        System.out.println("----------------------------------");
        System.out.println(count);
    }

    // 通过实例化对象来调用方法
    public static void main(String[] args) {
        demo02StaticMethod math = new demo02StaticMethod();
        System.out.println("实例方法method1的返回值为:" + math.method1());
        System.out.println("静态方法method2的返回值为:" + math.method2());
        demo02StaticMethod.PrintCount();    // 通过类名调用静态方法,打印count
    }

}

运行结果如下:

----------------------------------
2
method1的返回值为:2
----------------------------------
5
method2的返回值为:5
----------------------------------
7

通过上面代码举例,我们发现,首先count作为静态变量在整个类当中被共享,因此,在各个方法当中调用的值不同。在静态方法medthod2方法和PrintCount方法中是不可以调用非静态方法method1的,而在method1方法中可以调用静态方法medthod2和PrintCount方法的。

在访问非静态方法时,需要通过实例对象来访问,而在访问静态方法时,可以直接访问,也可以通过类名来访问,还可以通过实例化对象来访问。



静态代码块

静态代码块在Java中指的是 static{ } 代码块,主要用于初始化类,为类的静态变量赋值初始值,提升程序性能。

静态代码块的特点:

  • 1.静态代码块类似于一个方法,但是它不可以存在于任何代码块中
  • 2.静态代码块可以存在于类中的任何地方,类当中可以有多个静态初始化块。
  • 3.Java虚拟机在加载类时执行静态代码块,所以很多时候会将一些只需要执行一次的初始化操作都放在static代码块中进行。
  • 4.如果类当中包含多个静态代码块,则Java虚拟机将按它们在类中出现的次序依次执行,而且每个静态代码块只会被执行一次
  • 5.静态代码块和静态方法一样,不可以直接访问类的实例变量和实例方法,而需要通过类的实例化对象来访问

代码演示:

public class demo03StaticCode {

    public static int count = 0;    // 静态变量
	
	// 非静态代码块
    {
        count++;
        System.out.println("非静态代码块执行了");
        System.out.println("count:" + count);
    }

	// 静态代码块
    static {
        count++;
        System.out.println("---------------------------");
        System.out.println("静态代码块1: " + count);
    }
	
	// 静态代码块
    static {
        count++;
        System.out.println("---------------------------");
        System.out.println("静态代码块2: " + count);
    }

   public static void main(String[] args) {
        //int count01 = 11;
        System.out.println("---------------------------");
        demo03StaticCode sta1 = new demo03StaticCode();  // 实例化第一个对象
        System.out.println("---------------------------");
        demo03StaticCode sta2 = new demo03StaticCode(); // 实例化第二个对象
    }

}

运行结果为:

---------------------------
静态代码块1: 1
---------------------------
静态代码块2: 2
---------------------------
非静态代码块执行了
count:3
---------------------------
非静态代码块执行了
count:4

上述代码中的非静态代码块,是在创建对象的时候自动调用。不创建对象不执行该类的非静态代码块。代码域中定义的变量都是局部的,只有域中的代码可以调用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值