1.使用最多的java对象数据类型String
由于String类型是对象类型并且它是final所修饰的,所以在声明一个String类型的数据时就会创建一个对象,如果大量的进行不合理操作就会造成垃圾对象过多,拖慢系统的运行效率造成不必要的资源消耗。
例:
String str = "a";
str += "b";
这个例子会产生三个对象存储在堆区,首先创建一个字符串“a”然后创建一个字符串“b”,最后创建一个“ab”然后改变变量str的引用指向的地址;
java对于如何避免垃圾对象的产生提供了两个工具对象StringBuilder 和StringBuffer;
StringBuilder和StringBuffer都是通过串池来完成对字符串的操作避免了垃圾对象的产生。
例:
String str = null;
StringBuilder sb1 = new StringBuilder();
sb1.append("a");
sb1.append("b");
str = sb1.toString();
StringBuffer sb2 = new StringBuffer();
sb2.append("a");
sb2.append("b");
str = sb2.toString();
例子中str 的两次赋值结果相同但是引用地址不同,StringBuilder和StringBuffer都是通过串池中声明“a”“b”“ab”最后调用toString方法来创建String对象的(由于StringBuider过程中已经在串池中声明了“a”“b”“ab”所以StringBuffer的操作并不会重复声明,而是直接引用串池中已存在的字符串)
所以整个过程只创建了两个对象,工具对象本身和一个String对象。
str-->"a"+"b" //每一个字符串都分配一个堆区空间来存放
sb--->"a"+"b" //串池中
↘ ↓
"abc"//堆区
2.StringBuilder和StringBuffer的区别
StringBuilder和StringBuffer都是实现与AbstractStringBuilder接口
StringBuilder运行速度快但是线程不安全,因为其中实现的方法没有考虑多线程并发处理,可能会造成结果与预期不符的效果
StringBuffer运行速度慢但是线程安全,因为其中实现的方法大部分都添加了synchronized来保证并发安全
所以在选择使用时要考虑到你要使用的是否会产生并发处理的情况;
3.java.util.Date
Date一般使用与我们的业务逻辑中是一个比较常用的对象数据类型,它本身也实现了io接口可以直接参与页面和接口之前的传输,但是我们一般不会这么做因为java不是中国人写的,在时间的使用习惯上与中国人有很大的差异而且java.util.Date中可供我们使用的方法只有三个而且有两个方法已经过期了,虽然过期的方法依然可以使用但是考虑到系统安全的话,建议大家尽量不要去大量的使用过期方法,也许下一个版本过期方法就有可能会被从api中删除,那么我们的程序就需要很大的改动。
它的子类有java.sql.Date、java.sql.Time、java.sql.Timestamp。子类我们一般用于对数据库的存取偶尔也直接用在业务逻辑中使用。
我们一般使用SimpleDateFormat来用于时间类型的转换通过表达式来获取自己需要转换的时间格式,常用的时间格式有:
①yyyy-MM-dd HH:mm:ss
②yyyy-MM-dd
③yyyyMMddHHmmss
④yyyyMMddHHmmssSSS
按顺序说 y代表年 M代表月 d代表日 H代表小时 m代表分钟 s代表秒数 S代表毫秒
通过SimpleDateFormat的format方法可以将时间转换成我们需要的时间格式的字符串。
但是SimpleDateFormat可以算是一个重量级资源了那么如何节约资源又不影响使用呢,在一些博客中我之前也看了有人写一些工具类来为每条线程都创建一个SimpleDateFormat对象来确保线程安全和节约资源的开销,但是这种方法有缺陷,就是这种方式只能指定一种固定的日期格式,有时候可能无法满足我们的业务需求,而且SimpleDateFormat继承与DateFormat,其中的大部分方法都有synchronized,所以也并不需要我们在去考虑线程安全问题。
所以我就在想为什么不把他放在我业务层的基类中呢?于是我基于java的继承特性、类加载机制和单例设计模式等特点将其放在了我的Service成的基类中,并提供get方法用于获取对象例:
private static SimpleDateFormat sdf0;
private static SimpleDateFormat sdf1;
private static SimpleDateFormat sdf2;
static {
sdf0 = new SimpleDateFormat("yyyyMMddHHmmss");
sdf1 = new SimpleDateFormat("yyyy-MM-dd");
sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
设置成私有是不想让人直接通过我的类名来操作它而提供了get方法让其可以获取对象,这样在我的程序中所有继承基类的service都可以使用get方法来获取业务需要的日志格式,也避免了资源的浪费,唯一一点不好的地方就是这三个对象将会一直伴随我的程序,并不会在不使用的时候被GC回收,虽然考虑到了这点但我依然这么做了,因为我的业务逻辑中大量的使用了它,这么设计也比较符合我的业务需求;
3.时间类型与String类型的相互转换
String str = "2018-05-22 14:00:00";
(1)String --- java.util.Date
常用的方式有两种都是使用java.util.Date的子类的静态方法实现
① java.util.Date date = java.sql.Date.valueOf(str);
②java.util.Date date = java.sql.Timestamp.valueOf(str);
基于java的多态子类对象可以放在父类的引用中,所以可以直接赋值无需强转;
(2) java.util.Date --- String
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str2 = sdf.format(new java.util.Date());
(3)时间类型的相互转换一般都可以通过有参构造方法完成
Timestamp times = new Timestamp(new java.util.Date().getTime());