这篇文章是关于Java static关键字的使用,主要会介绍以下的内容:
- static 的概念
- static的各种应用
- 总结
static 是什么
static 顾名思义是静态的意思。与this相对,static表示所修饰的部分是属于类本身所有的,不依赖与某个具体的实例。 而this上个博客已经讲了,可参考this的使用.this表示的是对调用方法的那个当前对象的引用,可以看做是类的实例的引用,依赖于具体的实例。所以这也就是《Java编程思想》里面说的
“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
在了解他使用之前,我们先思考一下,为什么我们需要使用staitc,一切都通过对象去调用不也可以吗?
这样做是可以,对象是可以调用实例变量,实例方法,类方法,类成员变量。但是这样真的好吗?我们有一些东西是不依赖具体对象。比如我们有一些工具类,如Math
,里面的cos,sin
这些都是客观存在,不会改变的。任何一个对象都不影响Math里面的任何东西,相反,像我们定义一个圆这个类,那么圆的半径,圆的面积显然是不同的圆 是不同的 这就不能用static。
好了,我们已经知道了static是什么,以及该什么时候去使用它,那我们我们都可以怎么用它呢?
static的用法
- static 变量
- static 方法
- static 代码块
static 变量
static变量就是静态的成员变量,所谓静态变量就是静态变量是归类本身所有,被所有对象所共享,在内存中只有一个副本。而非静态的就是每个对象所有,在内存中有多个副本,每个对象的副本互不影响。
比如我们常常自己定义或者是看源码中有很多常量,这些常量就是用final static修饰的。用static来修饰,让这个常量不需要new一个对象就能得到,非常的方便。例子如下:
/**
* Created by byhieg on 2016/6/20.
*/
public class CityFragment extends Fragment {
public static final String TAG = "CityFragment";
//省略其他代码
}
这样,我们就可以直接通过CityFragment.TAG
来得到TAG。
static 方法
static 方法和static 变量的使用目的是一致的,一般用来不通过创建对象来使用方法,用来做工具类的方法。如我们可以把处理字符串的操作的方法统一放到一个固定类里面,我们调用的时候,只需要通过类名.方法名
就可以,省去每次创建对象浪费的内存。比如下面的例子
/**
* Created by byhieg on 2016/6/20.
*/
public class StringUtils {
//根据输入的指定的字符,分割字符串
public static String[] splitString(String str,String regex) {
String [] result = str.split(regex);
return result;
}
//删除指定位置的字符串
public static String delPosOfString(String str, int[] pos) {
StringBuffer sb = new StringBuffer(str);
for(int i = 0 ; i < pos.length;i++) {
sb.deleteCharAt(pos[i]);
}
return sb.toString();
}
}
我们可以直接这么调用StringUntils.splitString(args1,args2)
下面,我们说一些用static 方法的注意事项。我们看一下下面的例子。
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static final String str = "byhieg";
public String error = "error";
public void test() {
System.out.println(str);
System.out.println(error);
}
public static void main(String[] args) {
System.out.println(test());
System.out.println(error);
System.out.println(str);
}
}
运行会出现下面的错误
Error:(13, 28) java: 无法从静态上下文中引用非静态 方法 test()
Error:(14, 28) java: 无法从静态上下文中引用非静态 变量 error
虽然我们举例用的Main方法,但他是static方法,使用的是统一的static语法规则。报错的原因是因为在静态方法中我们是无法调用非静态的成员变量和方法。因为非静态的方法和变量是依赖于对象创建,对象才能调用的。所以是不可以调用的。但是在非静态方法中,是可以调用全部,因为上文说了 静态的是归所有对象共享,非静态是省略了this才调用成功的。
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static final String str = "byhieg";
public String error = "error";
public void test() {
System.out.println(str);
System.out.println(error);
//此处省略了this 实际应该是this.test1(),this.error
//所以也是通过对象对调用的非静态的变量和方法
test1();
}
public void test1() {
System.out.println(str);
System.out.println(error);
}
public static void main(String[] args) {
new Main().test();
}
}
static 初始化块
在说明静态初始化块的时候,我们先了解一下什么是初始化块。当我们需要生成很多对象的时候,每次都需要执行构造方法,如果我们的构造方法中,有一些代码是不依赖参数的,我们就可以把这些代码提取出来,放到同一个地方。这个地方我们称之为初始化块。
初始化块允许定义很多个,执行顺序与书写的顺序有关,但实际没什么卵用,因为他是创建Java对象时隐式执行,且全部被执行,完全可以把他们放到一起去执行。初始化块的执行会先于构造器,这点很重要。
接下来,我们看一下static静态块,static静态块除了有静态块的优点以外,他还有static所带来的优点,即他在类初次被加载时执行,且只会执行一次。不会像普通代码块一样,每次对象创建时都会执行,这样我们可以把一些造成空间浪费的语句,放到静态初始化块中执行。比如下面的代码
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public Main() {
Integer a = new Integer(1024);
//省略其他初始化代码
}
}
每次在new一个新对象的时候,都会创建一个新的Integer对象。这样无疑浪费空间,这时我们就需要用静态代码块,把Integer a放进去,就可以保证只会初始化一次。如下:
/**
* Created by byhieg on 2016/6/20.
*/
public class Main {
public static Integer a;
static {
a = new Integer(1024);
}
public Main() {
//省略构造器其他代码
}
}
静态初始化块执行的顺序在普通初始化块执行之前,因为只有类被加载并初始化之后,我们才能创建类的的实例,但以后再创建的实例的时候就不会再执行静态初始化块了。
总结
static 是与类相关的一个关键字,所修饰的部分表明该部分是归类所有。比如static修饰变量就表明该变量是静态变量,被所有对象所共享,被类所拥有。static修饰方法,与变量时一致的,只是在静态方法中是不允许调用非静态的变量和方法。而静态代码块是比较特殊的存在,用来初始化一些共有的东西,在类被加载时只执行一次。