0. 前言  

static是Java中的重要的一个点。也是面试的时候经常被问到的点,如果理解不够很容易给面试官语言基础不扎实的印象。本文从static方法、static内部类、static变量、以及static代码块四个角度分别解析static关键字。转载请注明出处为SEU_Calvin的博客

 

1.  static方法

《Java编程思想》里有这么一句话——“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”

static方法一般称作静态方法,由于静态方法不依赖于任何对象、仅通过类名就可以进行访问,前提是类被加载。也因此在静态方法中不能访问类的非静态成员方法/变量,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用,如果通过类名调用静态方法,而该方法内部有非静态变量,此时对象都还没有创建,就会产生错误,因此Java设置了这样的限制。当然反过来,在非静态成员方法中是可以访问静态成员方法/变量的。

我们最常见的static方法就是main方法,另外还有,即使没有显示地声明为static,类的构造器实际上也是静态方法。

还有就是需要注意,如果你没必要访问对象外部,那么就把你的方法成为静态方法,因为它会比实例方法更快的调用(后者为了实现多态需维护一个虚拟函数导向表)。

2.  static内部类

静态内部类和非静态内部类是我们在开发中都经常用到的,那么两者之间到底有什么不同呢?

这里主要总结一下两者的区别,顺便提出在使用static内部类时需要注意的一些性质:

(1)内部静态类不需要有指向外部类的引用,但非静态内部类需要持有对外部类的引用。这也是很多非静态内部类经常默认Android Activity外部类的引用,从而间接导致内存泄漏的原因。

(2)非静态内部类能够访问外部类的静态和非静态成员,显然一个非静态内部类不能脱离外部类实体被创建,而静态类不能访问外部类的非静态成员,它只能访问外部类的静态成员。这一点和上面static方法的性质类似。

3.  static变量

同样介绍静态变量和非静态变量的区别:

静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问。

需要注意的是,不论是static方法还是static变量,通过类名直接调用时,也会判断该方法/变量是否被修饰为private,如果是,仍然是无法获取到的,这说明static关键字无法改变成员的访问权限。

4.  static代码块

首先看看下面程序会输出什么呢?

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

虽然在main方法中没有任何语句,但是还是会输出"test static 1"、"test static 2",static块可以置于类中的任何地方,只要不是方法内部,类中也可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

根据只会执行一次的特性,静态代码块可以用以优化程序性能。实例如下:

class Person{
private Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBirthdaySuitable() {
Date startDate = Date.valueOf("1990");
Date endDate = Date.valueOf("1999");
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) <= 0;
}
}

这个实例用于判断该Person是否是90后孤寡老人。每次isBirthdaySuitable()被调用的时候,都会生成startDate和endDate两个对象,造成了空间浪费,使用static静态块优化如下:

class Person{
private Date birthDate;
private static Date startDate,endDate;
//一次性的初始化操作放在static代码块中进行
static{
startDate = Date.valueOf("1990");
endDate = Date.valueOf("1999");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBirthdaySuitable () {
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) <=0;
}
}

5.  static代码块的执行顺序

先看看下面程序会输出什么?

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");
}
}

我们来分析一下这段代码的执行过程:

(1)首先加载Test类,因此会先执行Test类中的static块。

(2)接着执行main函数中的newMyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载过了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。

(3)在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Personperson = new Person(),而Person类还没有被加载,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化。

(4)最后初始化MyClass,因此会先接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。

Java技术——Java中的static关键字解析的更多相关文章

  1. [ 转载 ] Java基础4--Java中的static关键字解析

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

  2. Java中的static关键字解析

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

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

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

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

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

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

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

  6. 【转】Java中的static关键字解析

    一.static关键字的用途 在<Java编程思想>P86页有这样一段话: “static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没 ...

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

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

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

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

  9. 【搬运工】——Java中的static关键字解析(转)

    原文链接:http://www.cnblogs.com/dolphin0520/p/3799052.html static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大 ...

随机推荐

  1. "BLAME" is out.

    The latest feature animation film "BLAME" is watchable on the Netflix. Rendering was done ...

  2. AIDL基本使用

    1.概述 Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务.这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架 Android Bin ...

  3. java中带图片按钮的大小设置

    在java部分需要用到图形界面编程的项目中,经常会使用图片设置对按钮进行美化,但是使用时会出现一个很麻烦的问题,那就是按钮的大小默认按照图片的大小来显示,这大大降低了界面的美观程度: 按照方法: JB ...

  4. spring拦截器(interceptor)简介

    1. 拦截器用途 (1)拦截未登录用户直接访问某些链接 (2)拦截日志信息 (3)拦截非法攻击,比如sql注入 2. 涉及jar.类 (1)spring-webmvc.jar (2)HandlerIn ...

  5. wordpress安装后访问博客只显示文字的解决办法

    按着网上的教程,买了腾讯云服务器,上面的镜像已经安装好WordPress了.但是发现并不像网上十分钟搭建个人站点等的写的那么简单.遇到了一些问题,下面来详细讲一讲. 首先是用ip地址不能直接访问服务器 ...

  6. Android Studio教程03-Activtiy生命周期的理解

    目录 1. Activity 1.1. 安卓中的Activity定义和特性: 1.2. 注册Activity 1. Intent filters:设置默认开启的activity 1.3. Activi ...

  7. 《生命》第四集:Fish (鱼类)

    旗鱼,是游动最快的鱼,他们不仅速度快,背上的鱼鳍还能吓唬成群的沙丁鱼,他们依靠速度与技巧结队捕食. 飞鱼,继续讲述了一下,飞鱼可以飞起来,把捕食者远远甩掉:飞鱼保护后代的方式是把卵产在水中的树叶上,很 ...

  8. linux编译64bitHadoop (eg: ubuntu14.04 and hadoop 2.3.0)

    Hadoop官网提供的编译好的hadoop-2.3.0.tar.gz二进制包是在32位系统上编译的,在64系统上运行会有一些错误,比如: WARN util.NativeCodeLoader: Una ...

  9. MySQL高级知识(六)——索引优化

    前言:索引优化的目的主要是让索引不失效,本篇通过相关案例对索引优化进行讲解. 0.准备 创建经典的tb_emp表. DROP TABLE IF EXISTS `tb_emp`; CREATE TABL ...

  10. C#深度学习の枚举类型(IEnumerator,IEnumerable)

    一.关于枚举的含义 .Net提供了可枚举类型的接口IEnumerable和枚举器接口IEnumerator,程序集System.Collections 另: IQueryable 继承自IEnumer ...