定义:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
特点:单例类只能有一个实例;单例类必须自己创建自己的唯一实例;单例类必须给所有其他对象提供这一实例。
1、静态内部类 static nested class
这种写法使用JVM本身机制保证了线程安全问题。由于静态单例对象没有作为ToolFunction的成员变量直接实例化,因此类加载时不会实例化ToolFunction,第一次调用getInstance()时将加载内部类ToolFunctionHolder,在该内部类中定义了一个static类型的变量INSTANCE ,此时会首先初始化这个成员变量,由Java虚拟机来保证其线程安全性,确保该成员变量只能初始化一次,由于getInstance()方法没有任何线程锁定,因此其性能不会造成任何影响。并且由于 ToolFunctionHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本
示例代码:
/**
* 自定义的工具类单例
*/
public class Tool {
private static class ToolHolder {
private static final Tool INSTANCE = new Tool();
}
private Tool (){}
public static final Tool getInstance() {
return ToolHolder.INSTANCE;
}
}
/**
* 判断一个字符串是否是一个合法的ip地址:
* 1 首先检查字符串的长度 最短应该是0.0.0.0 7位 最长 000.000.000.000 15位
* 2 按.符号进行拆分,拆分结果应该是4段
* 3 检查每个字符串是不是都是数字
*/
boolean isIP(String str){
// 1、首先检查字符串的长度 最短应该是0.0.0.0 7位 最长 000.000.000.000 15位
if(str.length()<7 || str.length() >15) return false;
// 2、按.符号进行拆分,拆分结果应该是4段,"."、"|"、"^"等特殊字符必须用 \ 来进行转义
// 而在java字符串中,\ 也是个已经被使用的特殊符号,也需要使用 \ 来转义
String[] arr = str.split("\\.");
if( arr.length != 4 ) return false;
// 3、检查每个字符串是不是都是数字,ip地址每一段都是0-255的范围
for(int i = 0 ; i <4 ; i++ ){
if (!isNUM(arr[i]) || arr[i].length()==0 || Integer.parseInt(arr[i])>255 || Integer.parseInt(arr[i])<0){
return false;
}
}
return true;
}
/**
* 判断一个字符串是否是数字
*/
boolean isNUM(String str){
Pattern p = Pattern.compile("[0-9]*");
Matcher m = p.matcher(str);
return m.matches();
}
2、枚举
通过Tool.INSTANCE来访问实例,这比调用getInstance()方法简单多了。创建枚举默认就是线程安全的,所以不需要担心double checked locking,而且还能防止反序列化导致重新创建新的对象
示例代码:
/**
* 自定义一个单例
*/
public enum Tool {
INSTANCE;
/**
* 判断一个字符串是否是一个合法的ip地址:
* 1 首先检查字符串的长度 最短应该是0.0.0.0 7位 最长 000.000.000.000 15位
* 2 按.符号进行拆分,拆分结果应该是4段
* 3 检查每个字符串是不是都是数字
*/
boolean isIP(String str){
// 1、首先检查字符串的长度 最短应该是0.0.0.0 7位 最长 000.000.000.000 15位
if(str.length()<7 || str.length() >15) return false;
// 2、按.符号进行拆分,拆分结果应该是4段,"."、"|"、"^"等特殊字符必须用 \ 来进行转义
// 而在java字符串中,\ 也是个已经被使用的特殊符号,也需要使用 \ 来转义
String[] arr = str.split("\\.");
if( arr.length != 4 ) return false;
// 3、检查每个字符串是不是都是数字,ip地址每一段都是0-255的范围
for(int i = 0 ; i <4 ; i++ ){
if (!isNUM(arr[i]) || arr[i].length()==0 || Integer.parseInt(arr[i])>255 || Integer.parseInt(arr[i])<0){
return false;
}
}
return true;
}
/**
* 判断一个字符串是否是数字
*/
boolean isNUM(String str){
Pattern p = Pattern.compile("[0-9]*");
Matcher m = p.matcher(str);
return m.matches();
}
}
网友评论