String常量池:
JVM在使用字符串类型时,为了提高内存使用效率,当使用字面量(常量)给变量赋值时,在方法区内提供了用于存储字面量对象的一个常量池.
原理:
当使用字面量赋值时,先去方法区内的常量池中查询是否有相同字面量的对象.如果有则返回常量池中对象的地址,若没有则在常量池中创建此字面量的对象再返回.
可以看看下面的实例:
public class Tests {
public static void main(String[] args) {
//使用构造器创建两个helloworld字符串对象
String s1 = new String("helloworld");
String s2 = new String("helloworld");
//查看s1与s2是不是同一个对象
System.out.println("s1与s2:"+(s1==s2));
System.out.println("s1与s2内容对比:"+s1.equals(s2));
String s3 = "helloworld";
String s4 = "helloworld";
System.out.println("s2与s3:"+(s2==s3));//false;说明s2与s3不是同一个对象
System.out.println("s3与s4:"+(s3==s4));//true;是同一个对象
String s5 = "hello";
String s6 = "world";
/*编译器在编译期间会进行一些简单的运算
*
*将两个字面量"hello"与"world"拼接成了
* "helloworld"
* */
String s7 = "hello"+"world";
System.out.println("s4与s7:"+(s4==s7));
String s8 = s5+"world";
System.out.println("s4与s8:"+(s4==s8));
String s9 = s5+s6;
System.out.println("s4与s9:"+(s4==s9));
System.out.println("s8与s9:"+(s8==s9));
}
}
运行结果:
s1与s2:false
s1与s2内容对比:true
s2与s3:false
s3与s4:true
s4与s7:true
s4与s8:false
s4与s9:false
s8与s9:false
包装类的常量池:
首先看看包装类与基本数据类型的对应关系:
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
除int和char有所不同之外,其余的都是首字母变大写.
Boolean与Character直接继承自Object类,其余的则继承自Numbers类,而Numbers则继承自Object类.
当将基本数据类型进行自动装箱时,装箱后的对象的字面值,如果是在-128~127之间,会先检查常量池中是否有相同字面值的对象,如果有,则将常量池的对象的地址给引用变量,若没有则创建一个.
下面给出Integer包装类的各种情况
示例代码:
public class Tests {
public static void main(String[] args) {
/*首先定义一个基本数据类型的数据*/
int i=1;
/*包装类的常量池实验*/
Integer i1=1;
Integer i2=1;
Integer i3=new Integer(i);
Integer i4=new Integer(1);
System.out.println("i1与i2是不是同一个对象:"+(i1==i2));
System.out.println("i1与i2的equals方法:"+(i1.equals(i2)));
System.out.println("i2与i3是不是同一个对象:"+(i2==i3));
System.out.println("i2与i3的equals方法:"+(i2.equals(i3)));
System.out.println("i2与i4是不是同一个对象:"+(i2==i4));
System.out.println("i2与i4的equals方法:"+(i2.equals(i4)));
System.out.println("i3与i4是不是同一个对象:"+(i3==i4));
System.out.println("i3与i4的equals方法:"+(i3.equals(i4)));
/*小于-128大于127范围的情况,应该与i1与i2的情况进行对比:*/
Integer i5=128;
Integer i6=128;
System.out.println("i5与i6是不是同一个对象:"+(i5==i6));
System.out.println("i5与i6的equals方法:"+(i5.equals(i6)));
}
}
运行结果:
i1与i2是不是同一个对象:true
i1与i2的equals方法:true
i2与i3是不是同一个对象:false
i2与i3的equals方法:true
i2与i4是不是同一个对象:false
i2与i4的equals方法:true
i3与i4是不是同一个对象:false
i3与i4的equals方法:true
i5与i6是不是同一个对象:false
i5与i6的equals方法:true
总结:
- 八种包装类都是final修饰
- 一经创建,对象内容不可变
- Character和Boolean的父类是Object其他六种的父类是Number类型,是抽象类.
Date
java.util.Date
封装了日期与时间的信息.之后里面的很多功能都弃用,渐渐的使用Calender类型来替代
构造器
Date():
创建一个封装当前系统时间的Date对象
Date(long time):
创建一个距离纪元time毫秒的Date对象
常用方法
long getTime();
返回距离纪元的毫秒数
void setTime(long time);
修改时间对象的毫秒数
示例代码:
import java.util.Date;
public class TestDate {
public static void main(String[] args) {
/*创建一个Date对象*/
Date time = new Date();
System.out.println(time);
/*调用有参构造器,创建一个距离纪元 10亿毫秒的时间对象*/
Date time1 = new Date(1520000000000L);
System.out.println(time1);
System.out.println(time.getTime());
System.out.println(time1.getTime());
time.setTime(time.getTime()-3600000*24);
System.out.println(time.getTime());
System.out.println(time);
}
}
运行结果:
Sun Aug 19 10:44:05 CST 2018
Fri Mar 02 22:13:20 CST 2018
1534646645478
1520000000000
1534560245478
Sat Aug 18 10:44:05 CST 2018
SimpleDateFormat
作用
此类型可以对Date进行格式化,将字符串转成Date类型。
常用构造器
SimpleDateFormat(String format):
创建一个指定格式的SimpleDateFromat对象。
常用方法:
String format(Date date)
作用是将参数date按照构造器里的格式进行格式化成字符串
Date parse(String str)
作用是将指定字符串str转变成Date类型
常用格式:
yy/yyyy: 年
MM:月
dd:日
HH:时(24制)
hh:时(12制)
mm:分
ss:秒
a:上下午
E:星期
示例代码:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Tests {
public static void main(String[] args) {
/*转换成Date类型 Date parse(String str)*/
String birth="1996/08/28";
SimpleDateFormat sdf1=new SimpleDateFormat("yyyy/MM/dd");
Date d= null;
/*需要用try...catch...进行处理.*/
try {
d = sdf1.parse(birth);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(d);
/*格式化方法 String format(Date d)*/
Date now = new Date();
SimpleDateFormat sdf =
new SimpleDateFormat("MM-dd-yyyy HH:mm:ss E a");
String info = sdf.format(now);
System.out.println("时间:"+info);
}
}
运行结果:
Wed Aug 28 00:00:00 CST 1996
时间:08-19-2018 11:22:11 星期日 上午
Calendar
1.是日历类型,此类型封装了有关日历的所有信息,主要用于计算时间分量(日期和时间的一部分有效值).
2.是一个抽象类,提供了一个方法叫getInstance(),来获取一个通用的子类型对象.一般都是GregorianCalendar(格里高利历法,阳 历),获取的时间是执行到此行代码的系统时间值.
3.时间分量常量
static int YEAR/MONTH/DATE;
关于MONTH:日历里的月份是0-11.
static int DAY_OF_WEEK/MONTH/YEAR;
关于DAY_OF_WEEK:默认一周第一天为周日,计数为1-7.
.........
常用方法
- 提供了get(int field),通过指定时间分量常量来获取相应的时间分量的值.
- 提供了set(int field,int value),进行设置时间分量值..提供了add(int field,int value),用于增加对当前日历信息通过时间分量计算value后的日历信息.若value为负值,则表示向前推算.
- int getActualMaximum(int field):获取当前时间分量所在的最大值.如指定Calendar.MONTH,表示月的最大值(11).Calendar.DATE,表示当前日历对象所在月份的最大值(8月,31).
示例代码:
import java.util.Calendar;
public class Tests {
public static void main(String[] args) {
/*时间分量*/
/*首先获取当前时间*/
Calendar c=Calendar.getInstance();
/*输出当前时间*/
System.out.println(c.getTime());
/*分别输出时间分量的值*/
System.out.println("当前时间的YEAR的值:"+c.get(Calendar.YEAR));
System.out.println("当前时间的MONTH的值:"+c.get(Calendar.MONTH));
System.out.println("当前时间的星期的值:"+c.get(Calendar.DAY_OF_WEEK));
/*可以看到星期的计数从1开始,第一天是星期日*/
/*月的计数0开始,第一个月是一月.*/
System.out.println("当前时间的HOUR的值:"+c.get(Calendar.HOUR_OF_DAY));
/*设置时间分量*/
c.set(Calendar.YEAR,2019);
c.set(Calendar.MONTH,1);
c.set(Calendar.DAY_OF_MONTH,19);
System.out.println("设置后的时间为:"+c.getTime());
/*对传入的参数进行加减,传入正数为加,传入负数为减*/
c.add(Calendar.MONTH,2);
c.add(Calendar.DAY_OF_MONTH,-2);
System.out.println("加减后的时间为:"+c.getTime());
/*获取当前时间分量的最大值*/
/*注意当前时间为刚刚设置的四月*/
System.out.println("当前月的最大值为:"+c.getActualMaximum(Calendar.DAY_OF_MONTH));
}
}
运行结果:
Sun Aug 19 11:55:14 CST 2018
当前时间的YEAR的值:2018
当前时间的MONTH的值:7
当前时间的星期的值:1
当前时间的HOUR的值:11
设置后的时间为:Tue Feb 19 11:55:14 CST 2019
加减后的时间为:Wed Apr 17 11:55:14 CST 2019
当前月的最大值为:30