详解java中的static关键字

Java中的static关键字可以用于修饰变量、方法、代码块和类,还可以与import关键字联合使用,使用的方式不同赋予了static关键字不同的作用,且在开发中使用广泛,这里做一下深入了解。

静态资源(静态变量与静态方法)

被static关键字修饰的变量和方法统一属于类的静态资源,是类实例之间共享的。被static关键字修饰的变量、方法属于类变量、类方法,可以通过【类名.变量名】、【类名.方法名】直接引用,而不需要派生一个类实例出来。

静态资源分类存放的好处

JDK把不同的静态资源放在了不同的类中而不是把所有的静态资源放在一个类里面,这样做主要有3点好处:

1.不同的类有自己的静态资源,就可以实现静态资源分类。比如,和数学相关的静态资源就放在了java.lang.Math中,和日历相关的静态资源就放在java.util.Calendar中,将组织形式固定为【类>静态资源】,使得代码的逻辑结构变得清晰。

2.因为静态资源的组织形式固定为了【类>静态资源】的形式,也就有效避免的静态资源在全局重名的问题。比如在A类中有一个name属性,B类中也有一个name属性,如果放在一起会重复,但是分类放开则不会重复了,因为实际上这两个属性的全名是A.name和B.name。

3.分类有助于避免因为静态资源都放在一个类中导致该类体积过大的问题,方便了管理与协同维护。

静态资源容易混淆的三个点

静态资源的知识点比较简单,但是还是有三点比较容易混淆:静态方法能不能引用非静态资源?静态方法能不能引用静态资源?非静态方法能不能引用静态资源?要弄明白这三个问题,就要先了解静态资源在JVM中的加载机制。

实际上,虽然说静态资源是属于类的,但在JVM中却是独立于类的存在。因为从JVM类加载机制的角度来讲,静态资源是类初始化的时候加载的,而非静态资源则是派生类的时候才加载的。类的初始化早于类的派生(new)。比如,在Class.forName("xxx")方法中,就是初始化了一个类,但是并不是派生出一个实例,而只是加载了这个类中的静态资源。因此对于一个静态资源来说,它是不可能知道一个类中有哪些非静态资源的。但是对于非静态资源来说就不一样了,由于它是派生实例之后才产生的,因此属于类的这些东西它都能识别得到。至此,上面三个问题的答案已经呼之欲出了:

1.静态方法能不能引用非静态资源?答案是不能,非静态资源是派生实例之后才产生的,对于在初始化阶段就存在的静态资源来说,根本识别不到。

2.静态方法能不能引用静态资源?答案是可以,因为静态资源都是在类初始化的时候一同加载的,自然都能互相识别得到。

3.非静态方法能不能引用静态资源?答案是可以,因为非静态方法就是实例方法,在派生类实例之后产生,而静态资源已经在类初始化的时候已经存在了,自然能在引用静态资源的时候成功识别。

静态块

静态块也是static关键字的重要应用之一,作用是初始化一个类的时候做特定的操作。和静态变量、静态方法同样,静态块里面的代码只会执行一次,且只在初始化类的时候执行。静态块同样很简单,只有三个小细节要特别提及:

静态资源的加载顺序是严格按照静态资源的定义顺序来加载的。

public class A
{
  private static int a = B();

  static
  {
    System.out.println("进入A类的静态块");
  }

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

  public static int B()
  {
    System.out.println("进入A类静态变量a.B()静态方法中");
    return 1;
  }
}

在这里,因为静态变量a的定义顺序在静态块之前,因此在a先被初始化的时候静态方法B先于静态块被调用执行,打印的结果是:

进入A类静态变量a.B()静态方法中
进入A类的静态块

静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问。

public class A
{
  static
  {
    c = 3;
    System.out.println(c);
  }

  private static int c;
}

上面这段代码会在第6行报错:Cannot reference a field before it is defined。这个特性理解起来可能比较奇怪,个人的理解是给静态方法赋值并不是实时的,Java遇到赋值语句的时候会先将这些个赋值语句缓存起来,等所有静态资源都识别完成之后再统一进行赋值。

静态代码块是严格按照父类静态代码块->子类静态代码块的顺序加载的,且只加载一次。

public class A
{
  static
  {
    System.out.println("A类的静态代码块");
  }

  public A()
  {
    System.out.println("A类的构造器");
  }
}
public class B extends A
{
  static
  {
    System.out.println("B类的静态代码块");
  }

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

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

上面代码的结果是:

A类的静态代码块
B类的静态代码块
A类的构造器
B类的构造器
A类的构造器
B类的构造器

静态内部类

一般情况下,static是关键字是不能用于修饰类的,只有在该类是内部类的情况下才能使用static修饰,且只能修饰一个,这样的内部类被称为静态内部类(匿名内部类)。静态内部类只有在一些特殊的场景中才能用得上,比如像线程池ThreadPoolExecutor中的四种拒绝机制CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy就是静态内部类。

与import关键字联合使用

import static是JDK1.5之后的新特性,这两个关键字联合使用可以指定导入某个类中的指定静态资源,并且不需要使用类名.资源名,可以直接使用资源名。

import static java.lang.Math.*;

public class A
{
  public static void main(String[] args)
  {
    System.out.println(sin(2.2));
  }
}

这么写意味着导入了java.lang.Math包下的所有静态资源,因此在main函数里就可以直接使用sin(2,2)而不需要使用Math.sin(2,2)了。另外使用这种语法要特别注意的是,这里要写import static java.lang.Math.*,最后的【.*】不可少,有了这两个字符才意味着导入的是Math下的所有静态资源,写成import static java.lang.Math是有问题的。当然,我们也可以指定只导入某个静态资源,比如只导入Math下sin这个方法而不导入Math下的所有静态资源。

import static java.lang.Math.sin;

public class A
{
  public static void main(String[] args)
  {
    System.out.println(sin(2.2));
  }
}

使用import static这样的语法可以有效简化一些操作,比如在频繁使用Math类下静态资源的地方可以少写很多【Math.】,但是这样却降低了代码的可读性,因为这样就模糊了该静态资源的来源,弱化了分类的概念。

以上就是详解java中的static关键字的详细内容,更多关于java static关键字的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java静态static关键字原理详解

    这篇文章主要介绍了Java静态static关键字原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 static关键字既可以修饰成员变量,也可以修改成员方法,修饰的成员变量和成员方法可以直接通过类名调用,也可以通过对象调用(其实即使是通过对象调用,也会被翻译成类名调用),建议通过类名调用. 成员方法用static修饰后,就成为了静态方法,静态方法不属于对象,而是属于类. 注意事项: 1.静态方法中不能使用this,因为this指的是当前对象

  • 详解Java基础篇--面向对象1(构造方法,static、this关键字)

    面向对象,面向过程的区别.拿下五子棋来说: 面向过程分析: 开始游戏 黑棋先走 绘制画面 判断输赢 轮到白棋 绘制画面 判断输赢 返回步骤2 输出结果 面向对象分析: 黑白双方,双方行为是一模一样的 棋盘系统,负责绘制画面 规则系统,判断犯规.输赢 传统的面向过程编程是思考问题的解决步骤,这种思维方式适用于问题规模较小时.可是当问题规模大,要求程序有更好的可扩展性,能更快速地查错时面向对象设计思想就能体现出其优势.面向对象更接近人类地自然思维方式,将现实世界中的事物抽象为对象和对象的方法. 面向

  • JAVA面试题 static关键字详解

    问题 面试官Q1:请说说static关键字,你在项目中是怎么使用的? static 关键字可以用来修饰:属性.方法.内部类.代码块: static 修饰的资源属于类级别,是全体对象实例共享的资源: 使用 static 修饰的属性,静态属性是在类的加载期间初始化的,使用类名.属性访问 案例说明 ①修饰成员变量 package com.ant.param; public class StaticFieldDemo { public static void main(String[] args) {

  • 浅谈Java中static关键字的作用

    static关键字主要有两种作用: 第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关. 第二,实现某个方法或属性与类而不是对象关联在一起 具体而言,在Java语言中,static主要有4中使用情况:成员变量.成员方法.代码块和内部类 (1)static成员变量: Java类提供了两种类型的变量:用static关键字修饰的静态变量和不用static关键字修饰的实例变量.静态变量属于类,在内存中只有一个复制,只要静态变量所在的类被加载,这个静态变量就会被分配空间,因此就可以被使

  • Java中的static关键字全面解析

    static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题.以下是本文的目录大纲: 一.static关键字的用途 二.static关键字的误区 三.常见的笔试面试题 若有不正之处,希望谅解并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin05

  • 谈Java static关键字的用法与好处

    本文针对Java static关键字的使用方法进行汇总,供大家参考,具体内容如下 1.对于static关键字的使用的时候对于修饰变量的时候,它相当于一个全局变量: 2.对于static修饰一个函数的时候他是在类被加载的时候首先会被类加载,并且只能加载一次,并且这个方法可以不需要通过实例进行调用例如: mystatic.java package study; public class mystatic { public static int sta=0; public int st=0; //st

  • java多线程关键字final和static详解

    这篇文章主要介绍了java多线程关键字final和static详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 final关键字 1.final关键字在单线程中的特点: 1)final修饰的静态成员:必须在进行显示初始化或静态代码块赋值,并且仅能赋值一次. 2)final修饰的类成员变量,可以在三个地方进行赋值:显示初始化.构造代码块和构造方法,并且仅能赋值一次. 3)final修饰的局部变量,必须在使用之前进行显示初始化(并不一定要在定义是

  • 详解java中的static关键字

    Java中的static关键字可以用于修饰变量.方法.代码块和类,还可以与import关键字联合使用,使用的方式不同赋予了static关键字不同的作用,且在开发中使用广泛,这里做一下深入了解. 静态资源(静态变量与静态方法) 被static关键字修饰的变量和方法统一属于类的静态资源,是类实例之间共享的.被static关键字修饰的变量.方法属于类变量.类方法,可以通过[类名.变量名].[类名.方法名]直接引用,而不需要派生一个类实例出来. 静态资源分类存放的好处 JDK把不同的静态资源放在了不同的

  • 详解Java中使用externds关键字继承类的用法

    理解继承是理解面向对象程序设计的关键.在Java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类).在Java中不允许多继承. (1)继承 class Animal{ void eat(){ System.out.println("Animal eat"); } void sleep(){ System.out.println("Animal sleep"); } void breathe(){ System.o

  • 详解c++中的 static 关键字及作用

    注:若没有特指是 静态成员时,默认都是普通成员: 1 类中的普通成员 类中的成员变量 和 成员函数 是分开存储的.其中, 1)每个对象都有独立的成员变量:成员变量可以存储在 栈空间.堆空间.全局数据区: 2)所有对象共享类的成员函数:成员函数 只能存储在 代码段: 2 类中的静态成员(static) 类中的静态成员 1.用 static关键字 修饰: 2.可以用 类名::成员名 访问 静态成员: 3.静态成员 属于 整个类: 4.静态成员 是所属类的成员,其它类不能访问: 5.静态成员的内存分配

  • 详解Java中的final关键字

    1 修饰属性或者变量 无论属性是基本类型还是引用类型,作用都是变量里面存放的"值"不可变 经常和static关键字一起使用,作为常量 1 基本类型,变量放的是实实在在的值,如1,"abc"等 2 引用类型,变量放的是个地址,所以用final修饰引用类型变量指的是它里面的地址不能变,即它只能指向初始时指向的那个对象,而不关心指向的对象内容的变化 所以修饰的变量必须被初始化 public static final String LOAN = "loan&quo

  • 详解java中的synchronized关键字

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 二.然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块.

  • 详解Java中的final关键字的使用

    final含义 final是Java中的一个保留关键字,可以声明成员变量.方法和类.一旦你将引用声明为final类型,你将不能再改变这个引用了.编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误. final变量 凡是对成员变量或者本地变量(在方法中的或者代码块中的变量称为本地变量)声明为final的都叫做final变量.下面是final修饰变量的例子: final int constValue = 1; // constValue = 2; The final local v

  • 详解Java中static关键字和内部类的使用

    目录 一. static 关键字 1. static修饰成员变量 2. static修饰成员方法 3. static成员变量的初始化 二. 内部类 1. 实例内部类 2. 静态内部类 3. 局部内部类 4. 匿名内部类 一. static 关键字 在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的. 1. static修饰成员变量 static修饰的成员变量,称为静态成员变量 [静态成员变量特性]: 不属于某个具体的对象,是类的属

  • 详解Java中static关键字的使用和原理

    目录 概述 定义和使用格式 类变量 静态方法 调用格式 静态原理图解 静态代码块 概述 关于 static 关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的.也就是说,既然属于类,就可以不靠创建对象来调用了. 定义和使用格式 类变量 当 static 修饰成员变量时,该变量称为类变量.该类的每个对象都共享同一个类变量的值.任何对象都可以更改 该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作. 类变量:使用 static关键字修

  • 详解JAVA中static的作用

    1.深度总结 引用一位网友的话,说的非常好,如果别人问你static的作用:如果你说静态修饰 类的属性 和 类的方法 别人认为你是合格的:如果是说 可以构成 静态代码块,那别人认为你还可以: 如果你说可以构成 静态内部类, 那别人认为你不错:如果你说了静态导包,那别人认为你很OK: 那我们就先在这几方面一一对static进行总结:然后说一些模糊的地方,以及一些面试中容易问道的地方: 1)static方法 static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方

  • 详解java中static关键词的作用

    在java中,static是一个修饰符,用于修饰类的成员方法.类的成员变量,另外可以编写static代码块来优化程序性能:被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问. static关键词的作用 1.静态成员变量的语法特定 2.静态函数的语法特定 3.静态代码块的语法特定 定义静态成员变量 Person.java class Person{ static int a; } 按照以前可以这么调用 public class Test1{

随机推荐