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. Android为TV端助力 最简单的自定义圆点view

    首先创建一个选择器,用来判断圆点状态,可以根本自己的需求改 <selector xmlns:android="http://schemas.android.com/apk/res/an ...

  2. 《React与Redux开发实例精解》读书笔记

    第五章 JSX语法 class属性改为className for属性改为htmlFor jsx中javascript表达式必须要有返回值,使用三元操作符 所有的标签必须闭合 input img等 re ...

  3. ExtJS中layout的12种布局风格

    总览 extjs的容器组件都可以设置它的显示风格,它的有效值有 1. absolute,2. accordion, 3. anchor, 4. border, 5. card, 6. column, ...

  4. PostgreSQL 表值函数

    方法1create type deptSon as ( mid ), id ), name ), DeptParentId ) ); CREATE OR REPLACE FUNCTION functi ...

  5. RHEL/Centos7 安装图形化桌面

    Linux是一个多任务的多用户的操作系统,好多linux爱好者在安装完linux后经常遇到一个问题——没有图形化桌面.今天小编在安装RHEL7的时候,一步留神没有安装图形化桌面,下面分享一下安装图形化 ...

  6. 阿里云windows2012+iis8配置https

    第一步先创建一个免费的证书 步骤一:申请免费证书 步骤二:填写你的二级域 步骤三:等待审核通过,通过后,点击下载 步骤四:根据自己服务器类型,下载对应的证书,根据阿里云的安装步骤做 以下是阿里云提供的 ...

  7. SQL server 数据库的索引和视图、存储过程和触发器

    1.索引:数据排序的方法,快速查询数据 分类: 唯一索引:不允许有相同值 主键索引:自动创建的主键对应的索引,命令方式不可删 聚集索引:物理顺序与索引顺序一致,只能创建一个 非聚集索引:物理顺序与索引 ...

  8. CISCO 动态路由(RIP)

    RIP(路由信息协议):是一种内部网关协议(IGP),是一种动态路由选择协议,基于距离矢量算法(DistanceVectorAlgorithms),使用“跳数”(即metric)来衡量到达目标地址的路 ...

  9. python 黏包现象及其解决方案

    一.数据缓冲区 缓冲区(buffer),它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区,显然缓冲区是具有一定大小的 ...

  10. C#基础知识之String,Stringbuilder和Stringbuffer

    String可以储存和操作字符串,即包含多个字符的字符数据.这个String类提供了存储数值不可改变的字符串. StringBuilder是线程不安全的,运行效率高,如果一个字符串变量是在方法里面定义 ...