Java中的 static 关键字,确实是一个关键的字(key word),今天就来总结一下它的用法,说说为什么关键。

Java中的 static 关键字主要是用来做内存管理的。理解了这句话才能够比较深入地理解static。

static 可以修饰:

  1. 变量(所谓 class variable)
  2. 方法(所谓 class method)
  3. 代码块(所谓 block)
  4. 内部类(所谓 nested class)

凡是被 static 修饰的这四种元素,都属于class的元素,即类的,而不是类的实例的。

1) 静态变量

在声明变量的时候加上 static ,该变量即是静态变量。

  • 什么时候该用 static 来修饰变量呢?该变量被该类的所有实例所共享。
  • 静态变量在类被加载的时候初始化,且仅分配一次内存。

这样做的好处就是内存利用率高,看下下面两个demo:

  1. // Understanding problem without static variable
  2. class Student{
  3. int stuNo;
  4. String name;
  5. String college="ITS";
  6. }

假设这个"niubility my brother" 的学校有500000000个学生,那么当每一个学生被创建的时候,都会初始化学号、姓名、学校,每个学生都有自己的学号和姓名,这样做没问题;但是每个学生的college字段都相同,如果每次都声明一遍的话,是比较耗内存的。这里的college变量其实是被该类的所有实例所共享的,因此可以将它声明为 static 的。

  1. //Program of static variable
  2. class Student8{
  3. int rollno;
  4. String name;
  5. static String college ="ITS";
  6.  
  7. Student8(int r,String n){
  8. rollno = r;
  9. name = n;
  10. }
  11. void display (){System.out.println(rollno+" "+name+" "+college);}
  12.  
  13. public static void main(String args[]){
  14. Student8 s1 = new Student8(111,"Karan");
  15. Student8 s2 = new Student8(222,"Aryan");
  16.  
  17. s1.display();
  18. s2.display();
  19. }
  20. }
  1. Output:111 Karan ITS
  2. 222 Aryan ITS

看下实际内存分配情况:

静态变量分配在了方法区,堆中该类的所有实例共享方法区中的college。

再看一下下面这个栗子:Counter 类中声明了一个count变量,在构造函数中对其进行++操作,因为实例变量在对象被创建的时候分配内存,所有每一个对象都有一份自己的count副本,每个对象对各自count的++操作不会反应到其他对象上。

  1. class Counter{
  2. int count=0;//will get memory when instance is created
  3.  
  4. Counter(){
  5. count++;
  6. System.out.println(count);
  7. }
  8.  
  9. public static void main(String args[]){
  10.  
  11. Counter c1=new Counter();
  12. Counter c2=new Counter();
  13. Counter c3=new Counter();
  14.  
  15. }
  16. }
  1. Output:1
  2. 1
  3. 1

因为静态变量仅仅在类加载的时候分配一次内存,所以如果将count修饰为static,那么该类的所有对象将会共享该变量,每一个对象对count的操作都会反应到其他对象上。

  1. class Counter2{
  2. static int count=0;//will get memory only once and retain its value
  3.  
  4. Counter2(){
  5. count++;
  6. System.out.println(count);
  7. }
  8.  
  9. public static void main(String args[]){
  10.  
  11. Counter2 c1=new Counter2();
  12. Counter2 c2=new Counter2();
  13. Counter2 c3=new Counter2();
  14.  
  15. }
  16. }
  1. Output:1
  2. 2
  3. 3

2)静态方法

在声明方法的时候加上 static 关键字,即静态方法:

  • 静态方法属于类而不是对象。
  • 静态方法可以直接通过类名调用,而不需要创建类的对象。
  • 静态方法可以修改静态变量,而非静态方法不可以。

一个静态方法的栗子:

  1. //Program of changing the common property of all objects(static field).
  2. class Student9{
  3. int rollno;
  4. String name;
  5. static String college = "ITS";
  6.  
  7. static void change(){
  8. college = "BBDIT";
  9. }
  10.  
  11. Student9(int r, String n){
  12. rollno = r;
  13. name = n;
  14. }
  15.  
  16. void display (){System.out.println(rollno+" "+name+" "+college);}
  17.  
  18. public static void main(String args[]){
  19. Student9.change();
  20.  
  21. Student9 s1 = new Student9 (111,"Karan");
  22. Student9 s2 = new Student9 (222,"Aryan");
  23. Student9 s3 = new Student9 (333,"Sonoo");
  24.  
  25. s1.display();
  26. s2.display();
  27. s3.display();
  28. }
  29. }
  1. Output:111 Karan BBDIT
  2. 222 Aryan BBDIT
  3. 333 Sonoo BBDIT

静态方法的第二颗栗子:

  1. //Program to get cube of a given number by static method
  2. class Calculate{
  3. static int cube(int x){
  4. return x*x*x;
  5. }
  6.  
  7. public static void main(String args[]){
  8. int result=Calculate.cube(5);
  9. System.out.println(result);
  10. }
  11. }

静态方法的两个注意点:

  1. 静态方法不能操作非静态变量,也不能调用非静态方法。(这个可以这样理解:静态方法属于类,直接通过类名就可以调用,而此时可能没有任何实例,更谈不上操作实例变量和调用实例方法了。)
  2. 静态方法中不能使用 thissuper 关键字。(道理同上)
  1. class A{
  2. int a=40;//non static
  3.  
  4. public static void main(String args[]){
  5. System.out.println(a);
  6. }
  7. }
  1. Output:Compile Time Error

Q)为什么Java的main方法是static的?

Ans)为了使得在调用main方法之前不需要创建任何实例对象。

3)静态代码块

为什么要有这个东西?干嘛用呢?

  • 用来初始化静态变量。
  • 在类加载时,在执行main方法之前执行相关操作。

栗子:

  1. class A2{
  2. static{System.out.println("static block is invoked");}
  3. public static void main(String args[]){
  4. System.out.println("Hello main");
  5. }
  6. }
  1. Output:static block is invoked
  2. Hello main

Q)没有main方法的程序可以执行吗?

Ans)可以,在JDK1.7之前执行如下代码是可以的:

  1. class A3{
  2. static{
  3. System.out.println("static block is invoked");
  4. System.exit(0);
  5. }
  6. }
  1. Output:static block is invoked (if not JDK7)

但是在JDK1.7会报如下错误:

  1. Output:Error: Main method not found in class A3, please define the main method as:
  2. public static void main(String[] args)

4)静态内部类

被static修饰的类,并且处于某个类的内部。

  • 它可以访问外部类的静态成员,包括private成员。
  • 它不能访问外部类的非静态成员。(原因前面说过)

那么为什么要有静态内部类呢?看下面的栗子:

  1. class TestOuter1{
  2. static int data=30;
  3. static class Inner{
  4. void msg(){System.out.println("data is "+data);}
  5. }
  6. public static void main(String args[]){
  7. TestOuter1.Inner obj=new TestOuter1.Inner();
  8. obj.msg();
  9. }
  10. }
  1. Output:data is 30

main方法中创建了一个静态内部类的实例,并且调用了其msg() 方法。但是这里并没有创建外部类的实例,因为这里的Inner类是static的,并且可以访问外围类的static成员。如果把Inner之前的static去掉,那么这里要这样写:

  1. TestStaticInnerClass.Inner obj=new TestStaticInnerClass().new Inner();

需要先创建外一个部类实例,然后才能创建内部类实例。静态内部类不仅高效利用内存,而且使得代码简洁。下面是static 内部类编译后的样子:

  1. // Internal class generated by the compiler
  2. import java.io.PrintStream;
  3. static class TestOuter1$Inner
  4. {
  5. TestOuter1$Inner(){}
  6. void msg(){
  7. System.out.println((new StringBuilder()).append("data is ")
  8. .append(TestOuter1.data).toString());
  9. }
  10. }

上例中,如果msg() 方法也是静态的,那么内部类的实例也不需要创建了:

  1. class TestOuter2{
  2. static int data=30;
  3. static class Inner{
  4. static void msg(){System.out.println("data is "+data);}
  5. }
  6. public static void main(String args[]){
  7. TestOuter2.Inner.msg();//no need to create the instance of static nested class
  8. }
  9. }
  1. Output:data is 30

以上是关于Java 中 static 关键字的理解,参考了:http://www.javatpoint.com/

关于Java中的static关键字的更多相关文章

  1. (转)Java中的static关键字解析

    转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...

  2. Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  3. (转)Java中的static关键字解析

    转自http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: “sta ...

  4. Java中的static关键字解析 转载

    原文链接:http://www.cnblogs.com/dolphin0520/p/3799052.html Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到 ...

  5. Java中的static关键字解析(转自海子)__为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  6. Java中的static关键字

    写在前面: 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中static表示“全局”或“静态”的意思,用来修饰成员变量和成员方法,当然也可以修饰 ...

  7. java中的static关键字详解

    static对于我们这些初学者在编写代码和阅读代码是一个难以理解的关键字,也是大量公司面试题最喜欢考的之一.下面我就来就先讲述一下static关键字的用法和我们初学者容易误解的地方. static关键 ...

  8. 【Java学习笔记之十五】Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  9. 再议Java中的static关键字

    再议Java中的static关键字 java中的static关键字在很久之前的一篇博文中已经讲到过了,感兴趣的朋友可以参考:<Java中的static关键字解析>. 今天我们再来谈一谈st ...

随机推荐

  1. git学习笔记一

    一.概念理解 1.理解工作区和暂存区以及版本库 工作区我理解就是我们创建的程序所在的文件夹,比如test文件夹.其中有个.git文件,这个就是版本库,其中版本库中有个区域叫暂存区或叫索引. 截自廖雪峰 ...

  2. angularJs 指令的理解

    指令: 可以把指令理解成为特定的DOM 上运行的函数,指令扩展了这个元素的功能: 例如:ng-click--在DOM元素上绑定了一个click事件的监听,并在监听到事件时运行angular表达式 自定 ...

  3. android——handler机制原理

    在android版本4.0及之后的版本中多线程有明确的分工,子线程可以写所有耗时的代码(数据库.蓝牙.网络服务),但是绝对不能碰UI,想碰UI跟着主线程走,那么我们如何才能让主线程知道我们要对 UI进 ...

  4. radio相关

    radio 按钮组, name=”sex”. <input type="radio" name="sex" value="Male"& ...

  5. 同一个页面多个page之间的切换

    今天接触了JQ Mobile以下是本小白的理解(不怕大家笑话): 创建移动 web 应用程序的框架:适用于所有流行的智能手机和平板电脑: 将“写得更少.做得更多”这一理念提升到了新的层次:它会自动为网 ...

  6. PHPCMS与UCenter整合要点

    要点一: PHPCMS不能直接与UCenter整合,而是要经过 PHPSSO 适配,因此应用主URL应是 http://phpcms_url/phpsso_server 这种模式的. 要点二: 因为 ...

  7. 一个App完成入门篇-终结篇(八)- 应用收官

    经过以上几步的学习,我们终于来到最后一个步骤了,应用APP也接近尾声. 通过之前的几节教程,不知道您对使用DeviceOne开发一个应用是不是已经得心应手了,本节教程将教会大家如何在开发完成之后通过D ...

  8. 安装 Linux 时碰到的硬盘分区的陷阱及应对

    硬盘分区的陷阱及应对 之所以想到写这篇,是因为本人在折腾 Linux 系统的过程中,有多次掉入硬盘分区的陷阱的经历.最近几天,再一次掉入坑中,折腾了两天才从坑中爬出来.经过多方查询资料,终于弄明白了硬 ...

  9. Tomcat的目录结构

    bin:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat6.exe.tomcat6w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口启动T ...

  10. rem与px的转换

    rem与px的转换 引用自http://caibaojian.com/rem-and-px.html A-A+ 前端博客•前端开发教程•rem•3702View0 rem是相对于根元素<html ...