[java基础]java中static关键字
1.static概念
static是静态修饰符,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。
这样做有什么意义呢? 在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是有种情况例外,就是该成员是用static声明的(在这里所讲排除了类的访问控制),可以让用户不需要实例化对象就可以引用成员,java中有很多类声明为静态,最基本的有Integer.parseInt(),Float.parseFloat()等等用来把对象转换为所需要的基本数据类型。这样的变量和方法我们又叫做类变量和类方法。
static的使用范围为:静态类,静态方法,静态变量和静态块。
静态的成员变量与非静态的成员变量的区别:
1. 作用上的区别:
1) 静态的成员变量的作用共享一个数据给所有的对象使用。
2) 非静态的成员变量的作用是描述一类事物的公共属性。
2. 数量与存储位置上的区别:
1) 静态成员变量是存储方法区内存中,而且只会存在一份数据。
2) 非静态的成员变量是存储在堆内存中,有n个对象就有n份数据。
3. 生命周期的区别:
1) 静态的成员变量数据是随着类的加载(即类创建对象或第一次使用时)而存在,随着类文件的消失而消失。
2) 非静态的成员数据是随着对象的创建而存在,随着对象被垃圾回收器回收而消失。
静态函数要注意的事项:
1. 静态函数是可以调用类名或者对象进行调用的,而非静态函数只能使用对象进行调用。
2. 静态的函数可以直接访问静态的成员,但是不能直接访问非静态的成员。
原因:静态函数是可以使用类名直接调用的,这时候可能还没有存在对象,
而非静态的 成员数据是随着对象的存在而存在的。
3. 非静态的函数是可以直接访问静态与非静态的成员。
原因:非静态函数只能由对象调用,当对象存在的时候,静态数据老早就已经存在了,而非静态
数据也随着对象的创建而存在了。
4. 静态函数不能出现this或者super关键字。
原因:因为静态的函数是可以使用类名调用的,一旦使用类名调用这时候不存在对象,而this
关键字是代表了一个函数 的调用者对象,这时候产生了冲突。
静态的数据的生命周期:静态的成员变量数据是优先于对象存在的。
2.静态方法和静态成员
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,不能在方法中使用this,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
public class StaticMethod { public int age=10; public static String name ="Hello Static"; public void display() { System.out.println(age); System.out.println(name);//非静态方法可以访问静态变量 } public static void show() { //System.out.println(age);--静态方法中不能访问非静态变量 System.out.println(name); } public static void main(String[] args) { // TODO Auto-generated method stub StaticMethod.show(); //调用静态方法不用创建对象,直接调用即可 } }
(1)Java静态对象和非静态对象有什么区别?(参考:http://blog.csdn.net/zhandoushi1982/article/details/8453522)
比对如下:
静态对象 静态对象
拥有属性: 是类共同拥有的 是类各对象独立拥有的
内存分配: 内存空间上是固定的 空间在各个附属类里面分配
分配顺序: 先分配静态对象的空间 继而再对非静态对象分配空间,也就是初始化顺序是先静态再非静态.
(2)java静态对象到底有什么好处?
- 静态对象的数据在全局是唯一的,一改都改。如果你想要处理的东西是整个程序中唯一的,弄成静态是个好方法。 非静态的东西你修改以后只是修改了他自己的数据,但是不会影响其他同类对象的数据。
- 引用方便。直接用 类名.静态方法名 或者 类名.静态变量名就可引用并且直接可以修改其属性值,不用get和set方法。
- 保持数据的唯一性。此数据全局都是唯一的,修改他的任何一处地方,在程序所有使用到的地方都将会体现到这些数据的修改。有效减少多余的浪费。
- static final用来修饰成员变量和成员方法,可简单理解为“全局常量”。对于变量,表示一旦给值就不可修改;对于方法,表示不可覆盖。
(3)静态变量、静态方法和静态块
通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例。在成员的声明前面加上关键字static就能创建这样的成员。如果一个成员被声明为static,它就能够在它的类的任何对象创建之前被访问,而不必引用任何对象(跟类是否有static修饰无关)。
你可以将方法和变量都声明为static。static 成员的最常见的 例子是main( ) 。声明为static的方法有以下几条限制(main也是??): ·
- 它们仅能调用其他的static 方法
- 它们只能访问static数据
- 它们不能以任何方式引用this 或super(this涉及到对象,super 与继承有关)
示例:Static 块仅在该类被加载时执行一次。下面的例子显示的类有一个static方法,一些static变量,以及一个static 初始化块。
public class TestNew { 02. static int a = 3; 03. static int b; 04. static void meth(int x){ 05. System.out.println("x = "+x); 06. System.out.println("a = "+a); 07. System.out.println("b = "+b); 08. } 09. static { 10. System.out.println("static block initialized"); 11. b = a*4; 12. } 13. public static void main(String[] args) { 14. // TODO Auto-generated method stub 15. meth(42); 16. } 17.}
执行结果是:
static block initialized
x = 42
a = 3
b = 12
上述class TestNew的执行顺序是:首先static 块执行(打印一条消息),a被设置为3,最后b被初始化为a*4 成12。然后调用main(),main () 调用meth() ,把值42传递给x。3个println ( ) 语句引用两个static变量a和b,以及局部变量x 。
3.静态块(见代码块部分)
4静态内部类
一般情况下,java是不可以用static修饰类的。如果一定要用static修饰类的话,通常static修饰的是匿名内部类。
有时候,使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部类引用外围对象,为此,可以把内部类声明为static,以便取消产生的引用。
package StaticTest; public class StaticClass { public static class Pair //静态内部类的方法及成员变量可以是非静态的,但是静态内部类不能引用外部类的非静态的成员变量和方法 { private double first; private double second; public Pair (double first,double second) { this.first=first; this.second=second; } public double getFirst() { return first; } } public static Pair minmax(double[] values) { double min=Double.MAX_VALUE; double max=Double.MIN_VALUE; for(double v : values) { if(v<min) min=v; if(v>max)max=v; } return new Pair(min, max); } public static void main(String[] args) { StaticClass.Pair pair = StaticClass.minmax(new double[]{1.7,2.5,3.3,100}); //StaticClass不用创建对象,直接通过.引用内部类 } }
参考:http://blog.sina.com.cn/s/blog_605f5b4f0100zbps.html
在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。由于静态的内部类在定义、使用的时候会有种种的限制。所以在实际工作中用到的并不多。在开发过程中,内部类中使用的最多的还是非静态地成员内部类。不过在特定的情况下,静态内部类也能够发挥其独特的作用。
1)静态内部类的使用目的
在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。在某些特殊的情况下,少了这个静态内部类还真是不行。如在进行代码程序测试的时候,如果在每一个Java源文件中都设置一个主方法(主方法是某个应用程序的入口,必须具有),那么会出现很多额外的代码。而且最主要的时这段主程序的代码对于Java文件来说,只是一个形式,其本身并不需要这种主方法。但是少了这个主方法又是万万不行的。在这种情况下,就可以将主方法写入到静态内部类中,从而不用为每个Java源文件都设置一个类似的主方法。这对于代码测试是非常有用的。在一些中大型的应用程序开发中,则是一个常用的技术手段。为此,这个静态内部类虽然不怎么常用,但是程序开发人员还必须要掌握它。也许在某个关键的时刻,其还可以发挥巨大的作用也说不定。
2)静态内部类的使用限制
将某个内部类定义为静态类,跟将其他类定义为静态类的方法基本相同,引用规则也基本一致。不过其细节方面仍然有很大的不同。具体来说,主要有如下几个地方要引起各位程序开发人员的注意。
一是静态成员(包括静态变量与静态成员)的定义。一般情况下,如果一个内部类不是被定义成静态内部类,那么在定义成员变量或者成员方法的时候,是不能够被定义成静态成员变量与静态成员方法的。也就是说,在非静态内部类中不可以声明静态成员。(特殊情况:非静态内部类也可以定义静态成员但需要同时有final关键词修饰,静态方法鉴于无法用final修饰,仍必须是在静态内部类或者非内部类中定义。)
二是在成员的引用上,有比较大的限制。一般的非静态内部类,可以随意的访问外部类中的成员变量与成员方法。即使这些成员方法被修饰为private(私有的成员变量或者方法),其非静态内部类都可以随意的访问。但是如果一个内部类被定义为静态的,静态内部类的对象中不能访问外部类的非静态成员(包括成员变量与成员方法)。
三是在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。通常情况下,在一个类中创建成员内部类的时候,有一个强制性的规定,即内部类的实例一定要绑定在外部类的实例中。也就是说,在创建内部类之前要先在外部类中要利用new关键字来创建这个内部类的对象。如此的话如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。也就是说,普通非静态内部类的对象是依附在外部类对象之中的。但是,如果成员开发人员创建的是静态内部类,那么这就又另当别论了。通常情况下,程序员在定义静态内部类的时候,是不需要定义绑定在外部类的实例上的。也就是说,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。即在创建静态类内部对象时,通过“外部类.内部类 内部类对象名”,即可创建内部类对象。
从以上的分析中可以看出,静态内部类与非静态的内部类还是有很大的不同的。一般程序开发人员可以这么理解,非静态的内部类对象隐式地在外部类中保存了一个引用,指向创建它的外部类对象。如是否可以创建静态的成员方法与成员变量(静态内部类可以创建静态的成员而非静态的内部类不可以)、对于访问外部类的成员的限制(静态内部类只可以访问外部类中的静态成员变量与成员方法而非静态的内部类即可以访问静态的也可以访问非静态的外部类成员方法与成员变量)。
总之,静态内部类在Java语言中是一个很特殊的类,跟普通的静态类以及非静态的内部类都有很大的差异。作为程序开发人员,必须要知道他们之间的差异,并在实际工作中在合适的地方采用合适的类。不过总的来说,静态内部类的使用频率并不是很高。但是在有一些场合,如果没有这个内部静态类的话,可能会起到事倍功半的反面效果