一。 String
首先我们要明确,String并不是基本数据类型,而是一个对象,并且是不可变的对象。查看源码就会发现String类为final型的(当然也不可被继承), 并且它的成员方法都默认为final方法。通过查看JDK文档会发现几乎每一个修改String对象的操作,实际上都是创建了一个全新的String对象。String类是通过 char数组 来保存字符串的
字符串为对象,那么在初始化之前,它的值为 null,到这里就有必要提下 ” ”、null、new String() 三者的区别。null 表示string还没有new ,也就是说对象的引用还没有创建,也没有分配内存空间给他,而 ” ”、new String() 则说明了已经new了,只不过内部为空,但是它创建了对象的引用,是需要分配内存空间的。
1.1. 字符串的创建
String对象一旦被创建就是固定不变的了,把String类定义为 不可改变 之后具有一个很大的 优点,即 编译时 编译器可以把 字符串 设置为 共享。对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象。
1.1.1 采用new关键字创建对象时,每次new出来的都是一个存储在 堆(heap) 上的新的对象, 是运行期新创建的。new 创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中(即在堆上创建一个新的String实例),然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址。
1.1.2 单独使用 " " 引号创建的字符串都是常量,编译期就已经确定存储到String Pool中;创建时,JVM 先到常量池里查找,如果有的话返回常量池里的这个实例的引用,否则的话创建一个新实例并置入常量池里。故 String a = "123" 时,对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。在 String a = "123","123" 表示一个 字符串对象。而 a 是 "123" 对象的地址,也叫做"123"对象的引用。
所以 在使用字符串的过程中,为提高效率,减少了内存空间的占用,推荐使用直接赋值(即String s=”aa”),除非有必要才会新建一个String对象(即 String s = new String(”aa”))。
(使用只包含常量的字符串连接符如 "aa" + "aa "创建的也是常量,编译期就能确定,已经确定存储到String Pool中;使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中.。 池 和 堆 是两个不同的地址)
eg. String s1 = "ab";
String s2 = "b";
String s3 = "a" + s1;
System.out.println((s1 == s3));
后台输出 : false
1.2. 字符串常量池 (JVM为了提高性能和减少内存的开销,在 实例化字符串 的时候进行了一些优化:使用 字符串常量池 )
每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的 实例引用。如果字符串不存在常量池中,就会
实例化 该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串。
1.3 常用方法
1.3.1. 获取:
int length ( ): 获取字符串的 长度。
char charAt (int index): 返回 指定索引 处的 char值。
int indexOf (String str): 返回 str 在字符串中第一次出现的 位置。(如果返回-1表示该str不在字符串中存在。)
int indexOf (int ch,int fromIndex): 从fromIndex指定位置开始,获取ch在字符串中出现的位置。
int lastIndexOf (int ch): 反向索引一个字符出现的位置
1.3.2. 判断:
boolean contains(str); 字符串中是否包含某一个子串。
boolean isEmpty(): 判断长度是否为0.
boolean startsWith(str);
boolean endsWith(str);
boolean equals(str);
boolean equalsIgnoreCase(); 判断内容是否相同,并忽略大小写
1.3.3. 转换:
char[] toCharArray() ; 将字符串转换成字符数组
int i = Integer.parseInt( str ) ; 将字符串转换为整型数值
double d = Double.parseDouble( str ) : 将字符串转换为double
值
toUpperCase( ) ;
toLowerCase( ) ;
1.3.4. 替换: replace ( oldchar, newchar );
1.3.5. 截取 : substring(begin) ; substring(begin, end)
1.4. 案例
String s = null;
s += "abc";
System.out.println(s);
后台输出: nullabc
*** StringBuffer ———— 线程安全
StringBuffer 和 String 一样都是用来 存储 字符串的,只不过由于他们内部的实现方式不同,导致他们所使用的范围不同,对于StringBuffer 而言,他在处理字符串时,若是对其进行修改操作,StringBuffer都是修改自身,并不会产生一个新的字符串对象,而 String类 则是产生一个新的对象,这是他们之间最大的区别。所以 在内存使用方面StringBuffer 优于 String 。
源代码中StringBuffer的很多方法都被关键字synchronized 修饰了,所以是 线程安全 的。
同时 StringBuffer 不能 使用 = 进行 初始化 ,它必须要产生StringBuffer实例,也就是说必须通过它的 构造方法 进行 初始化 。
在 StringBuffer 的使用方面,它更加侧重于对字符串的变化,例如追加、修改、删除,相对应的方法:
1、append ( ):追加指定内容到当前 StringBuffer 对象的末尾,类似于字符串的连接,这里 StringBuffer 对象的内容会发生改变。
2、insert():该类方法主要是在StringBuffer对象中插入内容。
3、delete():该类方法主要用于移除StringBuffer对象中的内容。
*** StringBuilder ———— 非线程安全
StringBuilder 也是一个 可变 的字符串对象,他与 StringBuffer 不同 之处就在于它是 线程不安全 的,基于这点,它的 速度 一般都比 StringBuffer 快。与 StringBuffer 一样,StringBuider 的主要操作也是 append 与 insert 方法。这两个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。
二。 enum(枚举类)
2.1. 有的时候一个 类 的 对象 是 有限且固定 的,这种情况下我们使用 枚举类 就比较方便。
eg. Public enum Gender{
/ /实例化, 不需使用new 关键字,不需显式调用构造器。自动添加public static final修饰。
FEMALE("女");
public String desc;
/ / 枚举类的构造器只能是私有的
this.desc = desc;
}
public String getDesc(){
return desc;
}
public void setDesc(String desc){
this.desc = desc;
}
}
2. 2. 枚举类的遍历 -------- values()
枚举类名 . values() 返回的是 一个类型与枚举类型一致的 数组。
eg. for (Gender gender : Gender.values() ){
System.out.println(gender.toString());
}
2.3 . 在 switch 中的操作
Gender gender = Gender , MALE;
switch (gender) {
}
三。 File 类
3.1. File 类的 对象 可以代表一个具体的 文件 或 文件夹。
eg. File f1 = new File( “d:\\ test\\1.txt” ); // 绝对路径
File f2 = new File( “1.txt” ); // 相对路径
File f3 = new File(“e:\\test); // 文件夹
3.2. 创建 文件 / 文件夹 , 必须 先 构造方法 new 一个 File对象, 然后再调用 createNewFile(), mkdir() / mkdirs().。 (创建之前先判断是否存在)
eg. File f1 = new File( “d:\\ test\\1.txt” );
if (file.exists()){
file.delete();
file.createNewFile();
}else{
file.createNewFile();
}
通常情况下,
File f1 = new File( “d:\\ test\\1.txt” );
if ( !file.exists()){
file.createNewFile();
前者 可更好的避免对文件内容的重复操作
3.3. 判断文件属性 ( isFile( ) 和 isDirectory( ) , canRead(),canWrite( ),isHidden( ) )
3.4. 文件属性 ( lastModified( ), length( ), list( ), listFiles( ), renameTo( ) , getName( ), getParent( ), getPath( ), getAbsolutePath( ) ,setReadable( ),
setWritable( ) )
3.5. 删除文件 delete()
四。 Date 类
Date 就是一个跟时间操作相关的,Date类是位于java.util包中的,表示特定的时间,精确到毫秒。比较常用的一个 构造方法 是 Date(),它可以将当前系统的时间信息作为值初始化给他的成员变量 (其他构造方法大多已过时)
eg. public static void main(String[] args) {
Date d = new Date();
System.out.println(d);
}
后台输出 : Wed Jul 05 16:34:42 CST 2017
4.1 SimpleDateFormat 类
对于时间,我们可以将其格式化(如 dd-MM-yyyy 或 ddMMyyyy。) ----------- 子类 SimpleDateFormat 调用其 构造方法 SimpleDateFormat(String pattern)
; SimpleDateFormat 是 非线程安全的,因此 不应该在多线程序中使用,除非是在对外线程安全的环境中使用,如 将 SimpleDateFormat 限制在 ThreadLocal 中。如果不这么做,在解析或者格式化日期的时候,可能会获取到一个不正确的结果。
eg. public static void main(String[] args) {
//首先创建一个Date对象。
Date d = new Date();
//然后使用DateFormat类的子类SimpleDateFormat类来创建一个对象 , 并传递一个字符串参数规定格式
SimpleDateFormat df = new SimpleDateFormat(" yyyy-MM-dd E a hh:mm:ss ");
// 调用其format方法,将Date作为被格式化对象传递进去,format方法返回的是一个字符串类型的时间表示。
String date = df.format(d);
System.out.println(date);
}
后台输出 : 2017-07-05 星期三 下午 04:54:35
除了上述的 y : 年,M : 月份, d : 日期, E : 星期, a : 上下午…… 另有 w : 年中的周数, W :月份中的周数, D :年中的天数,F :星期中的天数 (注意大小写的区别)
五。 Calender 类
Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。Calendar 的 getInstance 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化:
5.1 获取当前时间Calendar rightNow = Calendar.getInstance();Date d = rightNow.getTime()( getTime()返回一个表示此Calendar
时间值(从历元至现在的毫秒偏移量)的Date
对象。)
eg. public static void main(String[] args) {
String[] week = {"","周日","周一","周二","周三","周四","周五","周六"};
String[] year = {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"};
//获取一个Calender类的实例。
Calendar c = Calendar.getInstance();
//获取周中的星期几,并用中文表示,利用查表法在week数组中获得中文表示
int index1 = c.get(Calendar.DAY_OF_WEEK);
//获得日历字段中的月,也表示用中文表示,同样也利用查表法获得中文表示
int index2 = c.get(Calendar.MONTH);
//获得完整的时间,并打印。
System.out.println(c.get(Calendar.YEAR)+"年"+ year[index2] +c.get(Calendar.DAY_OF_MONTH)+"日"+ week[index1]);
System.out.println(c.get(Calendar.YEAR)+"年"+ index2 + "月" +c.get(Calendar.DAY_OF_MONTH)+"日"+"星期"+ index1);
}
后台输出 : 2017年六月12日周三
2017年5月12日星期4
在 Calendar 的 MONTH字段 中 第一个月是 JANUARY
,它为 0,以此类推 ; DAY_OF_WEEK字段中,第一天为SUNDAY
, 它为 1, 以此类推。 故第一个输出才为正确的当前时间。
5.2. 计算某一年中的第几星期的星期几是几号
SimpleDateFormat df=new SimpleDateFormat("yyyy年MM月dd日");
Calendar cal=Calendar.getInstance();
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.WEEK_OF_YEAR, 3);
cal.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
System.out.println(df.format(cal.getTime()));
输出:
2017年01月17日