- 单例类
如果一个类始终只能创建一个实例,则这个类被称为单例类。在一些特殊场景下,要求不允许自由创建该类的对象,而只允许为该类创建一个对象。为了避免其他类自由创建该类的实例,把该类的构造器使用private修饰,从而把该类的所有构造器隐藏起来。不过这就需要提供一个public方法作为该类的访问点,用于创建该类的对象,且该方法必须用static修饰(因为调用该方法之前不可能创建出对象,所以调用该方法的不可能是对象,只能是类)。而且,该类还必须缓存已经创建的对象,否则无法知道是否曾经创建国对象,也就无法保证只创建一个对象。为此该类需要使用一个成员变量来保存曾经创建的对象,因为该成员变量需要被静态方法访问,所以该成员变量也必须用static修饰:
class Singleton { private static Singleton instance; private Singleton(){} public 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(); //output :true System.out.println(s1 == s2); } }
- final修饰符
final修饰field
final成员变量必须由程序员显式初始化,系统不回队final成员进行隐式初始化。
final修饰的类Field,实例Field能指定初始值的地方如下:
类属性:必须在静态初始化块中或声明该属性时指定初始值
实例属性:必须在非静态初始化块/声明该属性或构造器中指定初始值。
final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。但对于引用类型变量而言,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。
final修饰方法
final修饰的方法不可被重写。
Objectx类中有个getClass,因为Java不希望重写该方法,所以用final把这个方法密封起来了。
eg
import java.util.Date; public class GetClassDemo extends Date { public static void main(String[] args) { GetClassDemo demo = new GetClassDemo(); demo.test(); } public void test() { System.out.println(super.getClass().getName()); System.out.println(getClass().getName()); System.out.println(getClass().getSuperclass().getName()); } }
输出结果:
com.citi.icg.portal.resource.service.impl.GetClassDemo
com.citi.icg.portal.resource.service.impl.GetClassDemo
java.util.Date
解释:如果在子类中覆盖了父类中的一个方法,那么super.theMethod()会调用父类的theMethod(),而不是子类覆盖后的方法。但如果没有覆盖,那super.theMethod()就调用继承来的theMethod(). 因为getClass()是final修饰的,所以super.getClass()调用的就是Object.getClass()。这个方法返回当前运行时类的Class对象。
- 不可变类
不可变类的意思是创建该类的实例后,该实例的Field是不可改变的。8个包装类和String类都是不可变的,
eg
class Name { private String firstName; private String lastName; public Name(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getFirstName() { return this.firstName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getLastName() { return this.lastName; } } public class Person { private final Name name; /* * public Person(Name name) { this.name = name; public Name getName() { * return name; } */ public Person(Name name) { this.name = new Name(name.getFirstName(), name.getLastName()); } public Name getName() { return new Name(name.getFirstName(), name.getLastName()); } public static void main(String[] args) { Name n = new Name("wukong", "sun"); Person p = new Person(n); System.out.println(p.getName().getFirstName()); n.setFirstName("bajie"); System.out.println(p.getName().getFirstName()); } }
如果需要设计一个不可变类,尤其要注意其引用类型Field,如果引用类型Field的雷是可变的,就必须采取必要的措施来保护该Field所引用的对象不会被修改,这样才能创建真正的不可变类。