static关键字
Static关键字有四种使用情况:成员变量、成员方法、代码块、内部类。Static修饰的成员变量就成了类变量,随着类的加载而加载,生命周期和类一样。Static修饰的成员方法变成了类方法,可以直接通过类名调用。和.class一样存在于方法区。
static变量和static方法可以被继承但是不能被重写(没有重写的概念)。static方法可以重载(静态不静态和重载不重载没关系)。不能在成员方法内部定义static变量。
static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法。
非静态的成员方法与成员变量的调用,只能通过创建对象调用。类名.方法名等;而静态的成员可以通过类名和创建对象调用(尽量用类名调用,不要创建对象)。
代码一:
class SSClass { static { System.out.println("SSClass"); } } class SuperClass extends SSClass { static { System.out.println("SuperClass init"); } public static int value = 123; public SuperClass() { System.out.println("init SuperClass"); } } class SubClass extends SuperClass { static { System.out.println("SubClass init"); } public SubClass() { System.out.println("init SubClass"); } } public class NotInitialization { public static void main(String[] args) { System.out.println(SuperClass.value); System.out.println(SubClass.value); SubClass.value = 789; System.out.println(SuperClass.value); } }
运行结果:
SSClass SuperClass init 123 123 789
代码二:
class SSClass { static { System.out.println("SSClass"); } } class SuperClass extends SSClass { static { System.out.println("SuperClass init"); } public static int value = 123; public SuperClass() { System.out.println("init SuperClass"); } } class SubClass extends SuperClass { static { System.out.println("SubClass init"); } //与代码一的区别 static int value = 456; public SubClass() { System.out.println("init SubClass"); } } public class NotInitialization { public static void main(String[] args) { System.out.println(SuperClass.value); System.out.println(SubClass.value); SubClass.value = 789; System.out.println(SuperClass.value); } }
运行结果:
SSClass SuperClass init 123 SubClass init 456 123
代码三:
class SSClass { static { System.out.println("SSClass"); } } class SuperClass extends SSClass { static { System.out.println("SuperClass init"); } public SuperClass() { System.out.println("init SuperClass"); } public static void tryPrint() { System.out.println("父类打印"); } } class SubClass extends SuperClass { static { System.out.println("SubClass init"); } public SubClass() { System.out.println("init SubClass"); } public static void tryPrint(String str) { System.out.println("打印: " + str); } } public class NotInitialization { public static void main(String[] args) { SubClass.tryPrint(); SubClass.tryPrint("字符串"); } }
运行结果:
SSClass SuperClass init 父类打印 SubClass init 打印: 字符串
对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类引用父类中定义的静态字段,只会出发父类初始化而不会触发子类初始化。然而如果父类中定义了相同名字的静态变量或方法,则与父类中原有的静态变量已经不是同一个变量或方法。也就是说对于静态变量和方法,是要被类直接调用的,没有重写这一说。
static的一个重要用途是实现单例模式,即该类只能有一个实例。为了实现这一功能,必须隐藏类的构造函数,将其声明为private,并提供一个对象和获取对象的方法,都声明为static。
示例://在类初始化时,已经自行实例化 public class Singleton1 { private Singleton1() {} private static final Singleton1 single = new Singleton1(); //静态工厂方法 public static Singleton1 getInstance() { return single; } }
静态代码块注意只会被执行一次。
静态内部类见内部类详解final关键字
在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。1、修饰类: 当用final修饰一个类时,表明这个类是最终类,不能被继承。如果一个类你不想让它被继承,就可以用final进行修饰。
2、修饰方法:使用final修饰的方法不能被子类重写,可以重载。(最终方法)
3、修饰变量: 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。注意,final的不可变性指的是引用不可变,即它只能指向初始时的那个对象,而不关心指向的对象内容的变化。
由final修饰的变量,是常量,一旦初始化后,它的值不能被修改,即不能被重新赋值,主要是项目中应用的常量的抽取:比如URL常量、路径常量、数字常量等.不能让人轻易修改。
注意: 当final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。
总之,static强调被类直接调用,早于对象且与特定对象无关。final强调不可更改性。