一、什么是嵌套类
嵌套类是指被定义在另一个类的内部的类。嵌套类存在的目的应该只是为他的外围类提供服务。如果嵌套类将来可能会用于其他的某个环境中,它就应该是顶层类。嵌套类有四种:静态成员类、非静态成员类、匿名类和局部类。除了第一种之外,其他三种被称为内部类。
二、什么是静态内部类
- 静态成员类是最简单的一种嵌套类。最好把他看做是普通类,只是碰巧被声明在另一个类的内部而已,它可以访问外围类的所有成员,包括哪些被声明为私有的成员。静态成员类是外围类的一个静态成员,与其他的静态成员一样,也遵守同样的可访问规则。如果他被声明为私有的,他就只能在外围类的内部才可以被访问,等等。
- 静态内部类可以有多个实例,跟普通的类一样,所以在多线程环境下要注意这一点。
三、静态内部类的用法
- 静态成员类的一种常见的用法是作为公有的辅助类,仅当与它的外部类一起使用时才有意义。例如考虑一下枚举,他描述了计算器支持的各种操作。
public class Calaculator {
public enum Operation{
ADD,DIVE,PLUS,MUL;
}
public static void main(String[] args) {
System.out.println(Calaculator.Operation.ADD);
}
}
- 从语法上讲,静态成员类和非静态成员类之间唯一的区别是,静态成员类的声明中包含修饰符static。尽管他们的语法非常相似,但是这两种嵌套类有很大的不同。非静态成员类的每个实例都隐含着与外围类的一个外围实例相关联。在非静态成员类的实例方法内部,可以调用外围实例的方法,或者利用修饰过的this构造获得外围实例的引用。如果嵌套类的实例可以在它外围类的实例之外独立存在,这个嵌套类必须是静态成员类:在没有外围实例的情况下,想要创建非静态成员类的实例是不可能的。
四、 静态内部类Builder模式创建对象
- 静态工厂和构造函数都可以创建一个类的对象,它们有一个共同的局限性就是参数过多时可读性不是很好,如果有很多的可选参数的话也不是很好控制,他也有自己的有点,使用静态工厂模式或构造函数模式是一种相对安全的模式;
- JavaBean的模式,这样就解决类静态工厂或者构造函数中遇到的参数过多可读性不好及可选参数控制的问题。
- Builder模式,这种模式即兼容了静态工厂或者构造函数的安全性,也保证了像JavaBean那样的可读性,也可以说是一种相对完美的解决方法。
如下是一个使用静态内部类的Builder模式构建的示例:
package ggindex.v2.stock.model;
import java.util.Date;
import java.util.Map;
public class Symbol {
//指标名称
private String index_name;
//开始日期
private Date start_date;
//结束日期
private Date end_date;
//分类ID
private Integer class_id;
public Symbol(Builder builder) {
this.index_name = builder.index_name;
this.start_date = builder.start_date;
this.end_date = builder.end_date;
this.class_id = builder.class_id;
}
public String getIndex_name() {
return index_name;
}
public void setIndex_name(String index_name) {
this.index_name = index_name;
}
public Date getStart_date() {
return start_date;
}
public void setStart_date(Date start_date) {
this.start_date = start_date;
}
public Date getEnd_date() {
return end_date;
}
public void setEnd_date(Date end_date) {
this.end_date = end_date;
}
public Integer getClass_id() {
return class_id;
}
public void setClass_id(Integer class_id) {
this.class_id = class_id;
}
public static class Builder{
//指标名称
private String index_name;
//开始日期
private Date start_date;
//结束日期
private Date end_date;
//分类ID
private Integer class_id;
public Builder setIndexName(String indexName) {
this.index_name = indexName;
return this;
}
public Builder setStartDate(Date startDate) {
this.start_date = startDate;
return this;
}
public Builder setEndDate(Date endDate) {
this.end_date = endDate;
return this;
}
public Builder setClassId(Integer classId) {
this.class_id = classId;
return this;
}
public Symbol build() {
return new Symbol(this);
}
}
}
构建Symbol实例对象:
public class Test {
public static void main(String[] args) {
Symbol symbol = new Symbol.Builder().setClassId(1)
.setEndDate(new Date())
.setStartDate(new Date())
.setIndexName("test")
.build();
}
}
五、静态内部类实现线程安全的单例模式
平时实现单例模式的时候通常会使用懒汉模式、饿汉模式;懒汉模式要实现线程安全的单例模式,如下代码:
public class Singleton {
//单例实例变量
private static Singleton instance = null;
//私有化的构造方法,保证外部的类不能通过构造器来实例化
private Singleton() {}
//获取单例对象实例
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
Singleton temp = instance;
if (temp == null) {
synchronized (Singleton.class) {
temp = new Singleton();
}
instance = temp;
}
}
}
return instance;
}
}
我们可以看到,要实现一个线程安全的单例类外面包了一层一层的锁synchronized,让人感觉很繁琐。
我们看一下饿汉模式实现线程安全的单例模式:
public class Singleton {
//单例变量 ,static的,在类加载时进行初始化一次,保证线程安全
private static Singleton instance = new Singleton();
//私有化的构造方法,保证外部的类不能通过构造器来实例化。
private Singleton() {}
//获取单例对象实例
public static Singleton getInstance() {
return instance;
}
}
这样可以简单的实现线程安全的单例类,但是也会存在一个问题,这种模式只要类已初始化就会实例化单例类,如果加载的资源很多,而且一直也不用的话就会造成资源的浪费。
看下面的静态内部类,可以很好的解决上面存在的问题,节省资源、代码简洁、线程安全性:
package ggindex.v2.stock.model;
//内部类实现懒汉模式
public class Singleton {
public static class SingletonHolder{
private static Singleton singleton = new Singleton();
}
//私有的构造函数,使外部类无法通过 构造器构造实例
private Singleton() {}
//获取单例对象
public static Singleton getInstance() {
return SingletonHolder.singleton;
}
}