在Java类里只能包含成员变量、方法、构造器、初始化块、内部类(包括接口、枚举)5种成员,类成员是用static来修饰的,其属于整个类。
当使用实例来访问类成员时,实际上依然是委托给该类来访问类成员,因此即使某个实例为null,它也可以访问它所属类的类成员。
public class NullAcessStatic { public static void test() { System.out.println("static修饰的类方法"); } public static void main(String[] args) { NullAcessStatic na = null; na.test(); } }
编译、运行正常。表明null对象可以访问它所属类的类成员。
对static关键字而言,一条重要的规则:类成员(方法、初始话块、内部类)不能访问实例成员(方法、成员变量)。
单例类
class Singleton { private Singleton(){} private static Singleton instance; static Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; } } public class SingletonTest { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); if(s1.equals(s2)) System.out.println("s1==s2"); else System.out.println("s1!=s2"); } }
我们可以看到两次产生的Singleton对象实际上是同一个对象。
final修饰符
final修饰的变量不可被改变,一旦获得初始值,该final变量的值就不能被重新赋值。Java语法规定,final修饰的成员变量必须由程序员显式地指定初始值。指定的位置如下:
1、类变量:静态初始化块中指定初始值或者声明该类变量时指定初始值;
2、实例变量:必须在非静态初始化块、声明该实例变量或者构造器中指定初始值;
final修饰基本类型变量和引用类型变量的区别
当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。但对于引用类型变量而言,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不变,即一直引用同一个对象,但这个对象完全可以发生改变。
import java.util.Arrays; class Person { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(){} public Person(int age) { this.age = age; } } public class FinalReferenceTest { public static void main(String[] args) { // TODO Auto-generated method stub final int[] iArr = {5,6,12,9}; System.out.println(Arrays.toString(iArr)); Arrays.sort(iArr); System.out.println(Arrays.toString(iArr)); iArr[2] = 8; System.out.println(Arrays.toString(iArr)); //iArr = null;//对iArr重新赋值,非法 final Person p = new Person(45); p.setAge(23); //p = null; //对p重新赋值,非法 } }