静态类
静态方法与非静态方法之间的区别
Java是面向对象的,但若处于某种特殊的情况下,通常是实用的方法,则不需要类的实例,static这个关键词可以标记出不需实例的方法,一个静态的方法代表说"一种不依靠实例也不需要对象的行为"
非静态方法(需要实例对象)
public class Song {
String title;
public Song(String t) {
title = t;
}
public void play() {
SoundPlayer player = new SoundPlayer();
player.playSound(title);
}
}
静态方法(以Math方法为例)
进入Math源码发现大部分的方法都是为static 方法
所以我们在使用Math方法的时候,都是使用Math直接点上方法,而不用去创建Math实例对象
以类的名称调用静态的方法
以引用变量的名称调用非静态的方法
静态方法不能调用非静态的变量
如果你尝试在静态的方法内使用实例变量,编译器会认为:“不知道你说的是那个实例的变量!” 静态的方法是不知道堆上有那些实例的。
public class test01 {
private int size;
public static void main(String[] args) {
System.out.println("Size of duck is" + size); // 此时我们根本无从知道堆上是否有Duck
}
public void setSize(int s) {
size = s;
}
public int getSize() {
return size;
}
}
运行上述代码会报错
静态的方法也不可以调用非静态的方法
public class test01 {
private int size;
public static void main(String[] args) {
System.out.println("Size of duck is" + getSize());
}
public void setSize(int s) {
size = s;
}
public int getSize() {
return size;
}
}
静态方法无法看到实例的状态
静态变量:它的值对所有的实例来说都相同
class Duck {
int duckCount = 0;
public Duck() {
duckCount++;
}
}
这样来计算duck的数量显然是不可以的,因为每个实例对象的duckCount的初始值都是0。
public class test01 {
private int size;
private static int duckCount = 0;
public test01(int size) {
duckCount++;
}
public void setSize(int s) {
size = s;
}
public int getSize() {
return size;
}
}
使用静态变量duckCount只有在第一次在被载入的时候初始化,每次构造函数的时候,此变量就会递增
public static void main(String[] args) {
test01 test01 = new test01();
System.out.println(duckCount);
test01 test02 = new test01();
System.out.println(duckCount);
test01 test03 = new test01();
System.out.println(duckCount);
}
静态变量是共享的。同一个类所有的实例共享一份静态变量
每个变量:每个实例一个
静态变量:每个类一个
静态变量的起始动作
静态项目的初始化有两项保证:
- 静态变量会在该类的任何对象创建之前就完成初始化,
- 静态变量会在该类的静态方法执行之前就初始化。
静态变量会在任何静态方法执行前前初始化完成
class Player {
static int playerCount = 0; // 载入的时候会被初始化成0
private String name;
public Player(String name) {
this.name = name;
playerCount++;
}
}
class PlayerTestDrive {
public static void main(String[] args) {
System.out.println(Player.playerCount);
Player one = new Player("Tiger Woods");
System.out.println(Player.playerCount); // 静态变量也是通过类的名称来存取的
}
}
静态的final变量是常数
我们以Math.PI为例
public static final double PI = 3.141592653589793;
- 此处被标记为public,因此可以供各方读取
- 此变量被标记为static,所以你不需要Math的实例
- 此处被标记为final,因为圆周率是不变的
- 此外没有别的方法可以识别变量为不变的常数(constant),但有命名惯例(naming convention)可以帮助你认出来
常数变量的名称应该都是大写字母
静态初始化程序(static initializer)是一段在加载类是会执行的程序代码,它会在其他程序可以使用该类之前就执行,所以很适合放静态final变量的起始程序
class Foo {
final static int x;
static {
x = 42;
}
}
静态final变量的初始化
①声明的时候:
public class Foo {
public static final int FOO_X = 25;
}
②在静态初始化程序中:
public class Bar {
public static final double BAR_SIGN;
static { // 这段代码会在类被加载的时候执行
BAR_SIGN = (double) Math.random();
}
}
如果没有用这两种方法之一来给值的话,编译器会告诉你,你没有初始化;
final不知用在静态变量上
- final的变量代表你不能改变它的值
- final的方法代表你不能覆盖掉此方法
- final的类代表你不能继承该类(也就是创建子类)
静态类的问题
- 非静态方法可以调用该类的静态变量和静态方法
- 将类标记为final的目的主要是为了安全
- 如果类已经被标记为final的,再标记final的方法会变得很多余,因为类无法被子类继承,所有的方法都不会被覆盖,如果只是想限定某些方法不被重写,只要在个别方法上加上final就可以了
要点!!!!
-
静态的方法应该用类的名称来调用,而不是用对象引用变量
-
静态的方法可以直接调用而不需要在堆上的实例。
-
静态的方法是一个非常实用的方法,它不需要特别的实例变量值
-
静态的方法不能存取非静态的方法
-
如果类只有静态方法,你可以将构造函数标记为private的以避免被初始化
-
静态变量为该变量所属类的成员共享.静态变量只有一份,而不是每个实例都有自己的一份
-
静态方法可以存取静态变量
-
在Java中常量是把变量同时标记为static和final的
-
final的静态变量值必须在声明或静态初始化程序中赋值:
static { DOG_CODE = 420; }
-
常量的命名习惯是全部使用大写字母
-
final值一旦被赋值,就不能更改
-
final的方法不能被覆盖
初始化
-
静态变量为该变量所属类的成员共享.静态变量只有一份,而不是每个实例都有自己的一份
-
静态方法可以存取静态变量
-
在Java中常量是把变量同时标记为static和final的
-
final的静态变量值必须在声明或静态初始化程序中赋值:
static { DOG_CODE = 420; }
-
常量的命名习惯是全部使用大写字母
-
final值一旦被赋值,就不能更改
-
final的方法不能被覆盖
-
final的类不能被继承