1.static引入

  通常来说,当创建一个类是,就是在描述那个类的对象的外观与行为。除非用new创建那个类的对象,否则实际并未获取任何对象。当执行new来创建对象时,数据存储空间才被分配,七方法才供外界调用。

  但是有两种情况是上述方法无法解决的。一种是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象。甚至根本就不创建对象。另一种是,希望某种方法不与包含他的类的任何对象关联在一起。也就是说没有创建对象,也能调用这个方法。

  static可以满足这两方面需求。声明一个static时,就意味着这个域或方法不会与包含它的那个类的任何对象关联在一块,即使未创建这个类的任何对象也可以调用其static方法。

2.static基本用法

  (1)只须将static关键字放在定义之前,就可以将字段或者方法设定为static,如下

class Test{
static int i = 1;
}

现在即使创建两个Test对象,Test.i也只有一份存储空间,这两个对象共享一个i。如下

Test i1 = new Test();
Test i2 = new Test();

这里i1.i 与i2.i指向同一块存储空间,因此具有相同的值1。

  (2)引用static变量有两种方法,之前的是一种,也可以用下面的方式直接用。注意这对于非static的成员是不行的。

  

Test.i ++;

这里使用类名引用static变量的首选方式。这是因为强调了变量的static结构,而且在某些情况下他还为编译器进行优化提供更好机会。

3.static方法

  类似的逻辑可以应用到静态方法中,既可以像其他方法一样,通过一个对象来引用某个静态方法,也可以通过特殊的语法形式clasName.method()加以引用。定义形式如下

class Test2{
static void test(){
Test.i ++;
}
}

使用时可以用对象调用调用,如

 Test2 t2 = new Test2();
t2.test();

或者直接用类对其递调用。如:

Test2.test();

因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

  另外记住,即使没有显示地声明为static,类的构造器实际上也是静态方法。

4.static误区

(1)static关键字会改变类中成员的访问权限吗?

这里不要将java中的static与C/C++中的static关键字混淆了,与C/C++中的不同,java关键字不会影响到变量或方法的作用域,在java中能影响到访问权限的只有private、public、protect。

(2)能通过this访问静态成员变量么?

对于静态方法来书没有this,那么下面代码的结果是什么?

public class Main{
static int value = 33;
public static void main(String[] args)throws Exception{
new Main().printValue();
} private void printValue(){
int value = 3;
System.out.println(this.value);
}
}

结果是

33

这里主要考察this和static的理解(this的用法详见java中this关键字)。this代表当前对象,通过new Main()来调用printValue的话,当前对象就是通过new Main()生成对象,而static变量是被所有对象所享有的,因此在printValue中this.Value的值毫无疑问是33.在printValue内部的value是局部变量,根本不可能与this相连,所以输出结果是33.这里永远记住:静态成员虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问。

(3)static可以作用与局部变量么?

在C/C++中static是可以作用于局部变量的,但是在java中切忌:static是不允许用来修饰局部变量。这是java语法规定。

5.常见笔试面试题

1.下面代码的结果是什么?

public class StaticTest extends Base{

    static{
System.out.println("test static");
} public StaticTest(){
System.out.println("test constructor");
} public static void main(String[] args) {
new StaticTest();
}
} class Base{ static{
System.out.println("base static");
} public Base(){
System.out.println("base constructor");
}
}

结果是

base static
test static
base constructor
test constructor

分析下,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。

(2)下面程序的结果是什么?

public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
} public Test() {
System.out.println("test constructor");
} public static void main(String[] args) {
new MyClass();
}
} class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
} class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
} public MyClass() {
System.out.println("myclass constructor");
}
}

结果是

test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

分析下,首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。

(3)下面代码的输出结果是什么?

public class Test {

    static{
System.out.println("test static 1");
}
public static void main(String[] args) { } static{
System.out.println("test static 2");
}
}

结果是

test static 1
test static 2

分析下,虽然在main方法中没有任何语句,但是还是会输出,原因上面已经讲述过了。另外,static块可以出现类中的任何地方(只要不是方法内部,记住,任何方法内部都不行),并且执行是按照static块的顺序执行的。

本文参考:

《java编程思想》

http://www.cnblogs.com/dolphin0520/p/3799052.html

以上就是static的简单基本用法。总结如是。

最新文章

  1. linux 查看目录所在的分区
  2. SQL Server里的文件和文件组
  3. monit 监控并自动重启服务
  4. Leetcode 166. Fraction to Recurring Decimal 弗洛伊德判环
  5. 让你分分钟读懂CPU架构及芯片厂商
  6. uva 1368
  7. DTD约束文件
  8. UVA 11294 Wedding
  9. 关于通过bindService启动的service,在unbindService后service是否继续运行的讨论
  10. static作用——The static effect
  11. (转)iOS Wow体验 - 第二章 - iOS用户体验解析(2)
  12. UltraEdit激活方法
  13. jstack Dump
  14. node.js面向对象实现(二)继承
  15. PythonStudy——Python 中Switch-Case 结构的实现
  16. css position[转
  17. Kosaraju算法学习
  18. Failed to execute operation: No such file or directory(systemctl enable iptables.service)
  19. java 接口默认修饰符
  20. SqlServer日期时间函数

热门文章

  1. ES6 随记(3.1)-- 字符串的拓展
  2. Centos6.5下ElasticSearch1.4.4的安装
  3. HBase-修改表结构
  4. web.xml里报错:Multiple annotations found at this line:
  5. Mfc 建立窗口线程
  6. hdu 1695 GCD 莫比乌斯
  7. linux(centos)安装Maven
  8. 结合两张表person和address
  9. asp.net 锚点
  10. python中常用的文件和目录操作(二)