分类: Java
2016-09-11 02:03:35
static是java中的常见关键字,本意为“静态”,是指被static声明的元素,加载类的时候就会申请内存地址,且其内存地址在整个生命周期中是“静态”的,不变的,所以全局共享。
就我理解,它还有共享、无状态的含义。共享是指被static修饰的成员是属于类的,所有成员共享;无状态是指static修饰的域,不能对对象敏感/依赖任何对象的生成,没有状态。无状态的实现方式为:被static修饰的域内,不可以使用任何非static的变量或方法,以此保证static方法或内部类不会依赖对象的生成。
此外,无状态还意味着,被static修饰的成员不能依赖任何对象的创建,它在类加载的时候被加载。虽然不可以依赖外部已生成的对象,但是static域内部可以生成对象。(比如main方法)
在java中,static常被用于形容5类元素:变量,方法,内部类,常量和代码块。(Tip:在java语法中,外部类不可以被static修饰,因为没有意义)
1. 静态变量
当变量被static修饰,意味着此变量属于类(共享性)。变量值可以被任何对象修改,且所有对象共享此更改。
2. 静态方法
意味着此方法属于类,可以用类名调用。由于无状态,静态方法中不能有非静态成员(方法/变量)出现(否则静态方法将会依赖对象的创建)。
static方法是静态绑定,所以不支持继承和重写(多态)。如果子类声明了和父类相同的静态方法,子类的方法将被隐藏/不起作用。而普通方法,子类会覆盖父类。
3. 静态内部类
static用于类的修饰只能出现在内部类。最外层的类不能被static修饰(java语法),因为没有意义。
静态内部类的使用:一般来说,当某个内部类中全部操作都不依赖任何对象或者非静态成员,此时它是一个无状态的内部类,可以声明为静态。
静态内部类不依赖外部类的对象生成。所以不能操作外部类的非静态成员。所以只在确定某内部类不需要使用任何外部的有状态变量时,再声明为静态。
静态内部类和外部类的区别不多,使用静态内部类的最常见原因是,某类只会被它的外部类调用,故封装为内部类;同时它不依赖任何对象创建,其功能也只依赖入参,具有静态性。不具备此特性的类,可以声明为普通内部类。
静态内部类不能依赖外部非静态成员,不过自己可以拥有非静态成员,也可以和外部类一样,生成对象。也可以被Spring自动装载作为服务。
4. 静态常量
同时使用static 和 final修饰的成员,既是静态又是不可变的,就成为了静态常量。可以作为全局常量使用。
5. 静态代码块
静态代码块会优于此类中的显式方法之前执行。当Java虚拟机(JVM)加载类时,就会执行该代码块。
关于Spring加载静态内部类和普通内部类
Spring自动装载bean时,对于静态内部类,只需要直接使用@Service或其他bean注解,即可作为被加载类正常使用;对于普通内部类,如果直接打@Service注解,编译时会报错误:Spring无法找到该类的空构造方法,加载失败。
究其原因,是普通内部类是外部类的一个成员,所以其加载和外部类的其他成员变量一样,都是依赖于外部类的对象创建的。
对于普通内部类,通常在外部类中手动new生成,因为不提供给其他类,故不必使用Spring装载。如果用Spring装载普通内部类,需要在中定义,指向其外部类的bean。
关于Spring加载静态对象
可以通过Spring加载一个bean作为static对象。需要在代码中声明该静态对象的非静态setter方法,再在Spring中用property正常注入。
但是,这种方法应该在业务中避免使用。因为static对象的目的,是在编译期申请到内存,并且始终不变。但是在业务代码中,用到的服务bean是不需要在编译期就申请的,Spring默认单例,那么在每个需要服务的地方自动加载@Autowired,获取服务单例提供服务即可,没必要声明为static。