首页 技术 正文
技术 2022年11月15日
0 收藏 437 点赞 4,629 浏览 4359 个字

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:

 // Understanding problem without static variable
class Student{
int stuNo;
String name;
String college="ITS";
}

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

 //Program of static variable
class Student8{
int rollno;
String name;
static String college ="ITS"; Student8(int r,String n){
rollno = r;
name = n;
}
void display (){System.out.println(rollno+" "+name+" "+college);} public static void main(String args[]){
Student8 s1 = new Student8(111,"Karan");
Student8 s2 = new Student8(222,"Aryan"); s1.display();
s2.display();
}
}
Output:111 Karan ITS
222 Aryan ITS

看下实际内存分配情况:

关于Java中的static关键字

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

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

 class Counter{
int count=0;//will get memory when instance is created Counter(){
count++;
System.out.println(count);
} public static void main(String args[]){ Counter c1=new Counter();
Counter c2=new Counter();
Counter c3=new Counter(); }
}
Output:1
1
1

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

 class Counter2{
static int count=0;//will get memory only once and retain its value Counter2(){
count++;
System.out.println(count);
} public static void main(String args[]){ Counter2 c1=new Counter2();
Counter2 c2=new Counter2();
Counter2 c3=new Counter2(); }
}
Output:1
2
3

2)静态方法

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

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

一个静态方法的栗子:

 //Program of changing the common property of all objects(static field).
class Student9{
int rollno;
String name;
static String college = "ITS"; static void change(){
college = "BBDIT";
} Student9(int r, String n){
rollno = r;
name = n;
} void display (){System.out.println(rollno+" "+name+" "+college);} public static void main(String args[]){
Student9.change(); Student9 s1 = new Student9 (111,"Karan");
Student9 s2 = new Student9 (222,"Aryan");
Student9 s3 = new Student9 (333,"Sonoo"); s1.display();
s2.display();
s3.display();
}
}
Output:111 Karan BBDIT
222 Aryan BBDIT
333 Sonoo BBDIT

静态方法的第二颗栗子:

 //Program to get cube of a given number by static method
class Calculate{
static int cube(int x){
return x*x*x;
} public static void main(String args[]){
int result=Calculate.cube(5);
System.out.println(result);
}
}

静态方法的两个注意点:

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

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

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

3)静态代码块

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

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

栗子:

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

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

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

 class A3{
static{
System.out.println("static block is invoked");
System.exit(0);
}
}
Output:static block is invoked (if not JDK7)

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

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

4)静态内部类

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

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

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

 class TestOuter1{
static int data=30;
static class Inner{
void msg(){System.out.println("data is "+data);}
}
public static void main(String args[]){
TestOuter1.Inner obj=new TestOuter1.Inner();
obj.msg();
}
}
Output:data is 30

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

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

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

 // Internal class generated by the compiler
import java.io.PrintStream;
static class TestOuter1$Inner
{
TestOuter1$Inner(){}
void msg(){
System.out.println((new StringBuilder()).append("data is ")
.append(TestOuter1.data).toString());
}
}

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

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

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

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,941
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,465
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,280
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,094
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,728
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,765