实例解析Java关于static的作用

概述

只要是有学过Java的都一定知道static,也一定能多多少少说出一些作用和注意事项。如果已经对static了如指掌的请点击关闭按钮,看下去也只是浪费您宝贵时间而已。这篇随笔只是个人的习惯总结。

为什么需要static?

有时候我们并不想去new一个对象,只是单纯的想要调用一个函数,并且希望这个函数不会与包含它的类的其他对象有所关联。说得通俗点,即使没有创建对象,也能通过类本身来调用函数。

static静态变量

被static修饰的变量属于类变量,通过字面意思就说明了这个变量的归属(类),与之相对的是没有被static修饰的成员变量,也称为实例变量,说明这个变量是属于某个具体的对象。

public class StaticDemo
{
 private static int i = 50;

 private int j = 60;

 public static void main(String[] args) {
 StaticDemo staticDemo = new StaticDemo();
 StaticDemo staticDemo1 = new StaticDemo();
 //即使创建两个对象,也都指向同一存储空间
 System.out.println(staticDemo.i);
 System.out.println(staticDemo1.i);
 //改变值
 staticDemo.i = 52;
 System.out.println(staticDemo1.i);
 staticDemo.j = 65;
 staticDemo1.j = 70;
 System.out.println(staticDemo.j);
 System.out.println(staticDemo1.j);
 }

}

输出

50
50
52
65
70

通过上面的实例,我们很快看出他们的区别

  1. 静态变量是属于类的,只有一份存储空间,是类之间共享的,牵一发而动全身,一处变,处处变。
  2. 实例变量属于实例对象,创建几次对象,就有几份的成员变量(拷贝)。

static修饰的静态函数

说到静态函数,就不得不提Java另一个关键词this,指的是当前的引用。意思是调用这个函数的对象,这意味着和static修饰的函数水火不容。被static修饰的函数,不能出现this关键字,否则便会报错。

去掉this,分别调用i或者j,会发现静态函数调用非静态资源时出错。这是为什么?从JVM加载机制角度来说,静态资源(被staitc修饰)是类在初始化的时候就加载的,而非静态资源是new的时候加载的。类的初始化是早于new的,加载了say()的函数时,它并不认识 j 这个成员变量,但对于非静态函数来说,当它加载时,静态资源已经加载完毕,所以它是认识 i 这个静态资源的。我们总结一下static修饰函数时的特点

  1. 静态函数不能引用非静态资源;
  2. 非静态函数可以引用静态资源;
  3. 静态函数可以相互调用(只要引入所在包即可);
  4. 静态函数没有this,因为它不依附于任何对象。

现在,我们也能知道main函数为什么必须是static的,因为程序在执行main函数时候,没有创建任何对象,只是通过类名来访问。

构造函数是不是静态函数?

《Java编程思想》提到“即使没有显示地使用static关键字,构造器实际上也是静态方法”。我至今不能确认构造器是不是静态函数,个人更偏向于不是。原因待会再阐述,先看个实例

public class StaticTest
{
 private static int i;

 private int j;

 public StaticTest(int i,int j){
 this.i = i;
 this.j = j;
     say1()
 }

 public void say1()
 {
 System.out.println("you age is" + i);
 System.out.println("you age is" + j);
 }

 public static void main(String[] args)
 {
 StaticTest staticTest = new StaticTest(4,5);
 StaticTest staticTest1 = new StaticTest(10,69);
 System.out.println(staticTest.i);
 System.out.println(staticTest.j);
 System.out.println(staticTest1.i);
 System.out.println(staticTest1.j);

 }
}

输出

you age is4
you age is5
you age is10
you age is69
10
5
10
69

实例中,确实改变了 i 的值,也符合静态资源的定义,只有一份存储空间。但构造器里用了this,与我前文所说的static属于类,不属于任何对象,this属于当前引用对象互相矛盾,并且构造函数还可以调用实例函数。一脸懵逼,这也是让我感到困惑并且认为构造函数不是静态函数的地方。如有周知,留言解惑,感谢。

静态块与非静态块

private static int i;
static
    {
        i = 5;
    }

静态块是static的重要应用之一,无函数名、作用域、返回值以及参数,静态代码块与静态变量和静态函数一样,不论类被调用多少次,该区域代码只在类初始化时第一次时执行一次,并且严格按照静态资源的定义顺序执行加载,与静态函数区别在于一个主动一个被动。

{
        System.out.println("我是静态块.");
  }

非静态块,同样无函数名,作用域,返回值以及参数,非静态代码块会在每次类被调用或者被实例化时执行。

实例

public class StaticTest extends Father
{
 public StaticTest()
 {
 System.out.println("我是StaticTest的构造函数");
 }

 {
 System.out.println("我是StaticTest的非静态块");
 }

 static
 {
 System.out.println("我是StaticTest的静态块");
 }

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

class Father
{
 public Father()
 {
 System.out.println("我是Father构造函数");
 }

 {
 System.out.println("我是Father非静态块1");
 }

 {
 System.out.println("我是Father非静态块2");
 }

 static
 {
 System.out.println("我是Father静态块");
 }

}

输出

我是Father静态块
我是StaticTest的静态块
我是Father非静态块1
我是Father非静态块2
我是Father构造函数
我是StaticTest的非静态块
我是StaticTest的构造函数
我是Father非静态块1
我是Father非静态块2
我是Father构造函数
我是StaticTest的非静态块
我是StaticTest的构造函数

加载顺序 :父类静态块 > 子类静态块 > 父类非静态块 > 父类构造函数 > 子类非静态块 > 子类构造函数

静态代码块以及非静态代码块都会在构造函数前执行,首次访问时,静态代码块会在非静态代码块前执行。

改变main函数

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

输出

我是Father静态块
我是StaticTest的静态块

静态代码块在类加载时自动执行,非静态代码块是在创建对象时自动执行的代码,不创建对象不执行该类的非静态代码块。

静态导入

静态导入是jdk5引入的新特性,有时我们在实际应用中,并不需要整个jar包都导入,而只是想使用某部分函数。提高代码的阅读性,更好的理解程序。

import static java.lang.System.out;

public class StaticTest
{
 public static void main(String[] args)
 {
 out.println("import static测试");
     System.out.println("import static测试");
 }
}

输出

import static测试
import static测试

会发现,两者输出是没有区别的,但是我们少写了System. 虽然允许这么使用,但在实际开发中,我很少发现有同事这么做,主要是不利于理解,但好处是如果频繁用这个类,可以少很多的类名。

===============================================================

如发现错误,请及时留言,lz及时修改,避免误导后来者。感谢!!!

(0)

相关推荐

  • Java中static变量作用和用法详解

    前言 static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享. 只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们.因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象. 用public修饰的static成员变量和成员方法

  • 基于Java class对象说明、Java 静态变量声明和赋值说明(详解)

    先看下JDK中的说明: java.lang.Object java.lang.Class<T> Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class tha

  • Java基础教程之static五大应用场景

    前言 static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构.上一个章节我们讲了final关键字的原理及用法,本章节我们来了解一下static关键字原理及其用法. 一. static特点 static是一个修饰符,通常用于修饰变量和方法,如开发过程中用到的字典类数据都会用到static来修饰,工具类方法,如Dateutils,Stringutils这类工具方法也会用到static来修饰,那么除了这两种最

  • 浅谈Java中static和非static的区别

    关于static和非static变量的区别 1. static 修饰的变量称为类变量或全局变量或成员变量,在类被加载的时候成员变量即被初始化,与类关联,只要类存在,static变量就存在.非static修饰的成员变量是在对象new出来的时候划分存储空间,是与具体的对象绑定的,该成员变量仅为当前对象所拥有的. 2. static修饰的变量在加载的时候先于main方法加载在内存中的数据共享区-------方法区,而非static的变量在加载的时候,是要创建变量才加载在堆内存中的. 3. 一个stat

  • 学习Java的static与final关键字

    static:(静态修饰符)面向对象中static修饰的内容是隶属于类,而不是直接隶属于对象的,所以static修饰的成员变量一般称作类成员变量,而static修饰的方法一般称作类方法. 分类: 1.static变量,也叫作静态变量或者类变量.另一种是没有被static修饰的变量,叫实例变量. 2.static方法,也叫作静态方法或者类方法,静态方法中不能定义静态变量,实例方法也不能. 3.static代码块,静态块中,可以访问静态变量,调用静态方法. 注意事项: 1.static不依附于任何对

  • Java中static静态变量的初始化完全解析

    静态变量初始化顺序 1.简单规则 首先先看一段最普遍的JAVA代码: public class Test { public static Test1 t = new Test1(); public static int a = 0; public static int b; public static void main(String[] arg) { System.out.println(Test.a); System.out.println(Test.b); } } class Test1

  • Java static(静态变量)和私有化功能与用法分析

    本文实例讲述了Java static(静态变量)和私有化功能与用法.分享给大家供大家参考,具体如下: 1.static作用主要有两方面:其一,当希望类中的某些属性被所有对象共享,则就必须将其声明为static属性:其二,如果一个类中的方法由类名调用,则可以将其声明为static方法. 2.需要注意的是,非static声明的方法可以去调用statci声明的属性和方法:但是static声明的方法不能调用非static类型的声明的属性和方法. 3.static方法调用static变量 public c

  • 利用反射获取Java类中的静态变量名及变量值的简单实例

    JAVA可以通过反射获取成员变量和静态变量的名称,局部变量就不太可能拿到了. public class Test { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub //获取所有变量的值 Class clazz = Class.forName("com.qianmingxs.ScoreTable"); Field[] fields = clazz.g

  • Java中this,static,final,const用法详解

    一.this 用类名定义一个变量的时候,定义的应该只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法,那们类里面是够也应该有一个引用来访问自己的属性和方法纳?JAVA提供了一个很好的东西,就是 this 对象,它可以在类里面来引用这个类的属性和方法. Java关键字this只能用于方法方法体内.当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this.因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现t

  • java中静态变量和实例变量的区别详细介绍

    运行效果: 控制台效果: ================================================== 代码部分 ================================================== /hello_test/src/com/b510/test/StaticTest.java 复制代码 代码如下: /**  *   */ package com.b510.test; /**  * 在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例

随机推荐