包装类
java是面向对象的语言,但并不是"纯面向对象"的(基本类型),但应用中常要将基本类型转化为对象,以便于操作,解决:java在设计类时为每个基本类型设计了一个对应的类进行代表,这样8个相对应的类统称为包装类(Wrapper Class)
包装类均位于java.lang包:
基本数据类型 | 包装类 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
在这8个类中,除了Character和Boolean类以外,其他的都是"数字型","数字型"都是java.lang.Number的子类(除了这六个包装类还有BigDecimal类和BigInteger类).Number类是abstract类,因此它的抽象方法所有子类都要提供实现
Number类提供了抽象方法:intValue(),longValue(),floatValue(),doubleValue(),意味着所有数字型包装类都可以互相转型
包装类提供了基本类型,包装类以及字符串的转换
基本类型转为包装类对象
Integer a = new Integer(3);
//不推荐使用这种方法.废弃(@Deprecated)
Integer b = Integer.valueOf(30);
//官方推荐(装箱)
//并且每个包装类(8个都有)都提供了静态的valueOf()方法来获取包装类对象
包装类对象转为基本类型
int x = b.intValue();
//拆箱
//8种包装类也都提供了xxxValue()方法来获得基本类型
字符串转为包装类对象
Integer e = new Integer("99");
//废弃(@Deprecated)
Integer f = Integer.parseInt("999");
//这两种方法前提为接收的参数是数字型字符串
包装类转为字符串
String str = f.toString();
//或者用:""+f
自动装箱与自动拆箱
Integer a = 234;
// 自动装箱.Integer a = Integer.valueOf()
//调用的是valueOf(234);而不是new Integer(234);
int b = a;
// 自动拆箱.编译器自动修改为:int b = a.intValue()
Integer in1 = 123456;
Integer in2 = 123456;
System.out.println(in1 == in2); //false
System.out.println(in1.equals(in2));//true
缓存机制:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
简单来讲,缓存了[-128,127]之间的数字
实际就是系统初始的时候,创建了[-128,127]之间的一个缓存数组.
当我们调用valueOf()时,首先检查是否在[-128,127]之间,如果在这个范围则直接从缓存中拿出已经创建好的对象,如果不在,则创建新的Integer对象
Integer in3 = -128;
Integer in4 = Integer.valueOf(-128);
System.out.println(in3 == in4); // true.
System.out.println(in3.equals(in4)); // true.
按理说,"in3 == in4"应该返回false.因为地址不同,但valueOf()提供了缓存[-128-127]之间的数
String类和StringBuilder类
String字符串用字符数组实现,而其中的字符数组用了final修饰,因此才成为不可变序列
AbstractStringBuilder抽象类有两个子类:StringBuilder和StringBuffer
StringBuilder类中的字符数组没有用final修饰,因此可以改值
StringBuilder线程不安全,效率高(一般使用它).StringBuffer线程安全,效率低
StringBuilder sb = new StringBuilder("abcdefg");
System.out.println(Integer.toHexString(sb.hashCode()));
System.out.println(sb);
sb.setCharAt(2, 'M'); //发生改变
System.out.println(Integer.toHexString(sb.hashCode()));
System.out.println(sb);
运行结果:
3b192d32
abcdefg
3b192d32
abMdefg
StringBuilder类的方法
其中有很多方法和String的类似(因此没有列出)
StringBuilder sb = new StringBuilder();
//String用"+"可以实现字符串连接,而StringBuffer类中主要通过append()
for(int i = 0;i<26;i++) {
sb.append((char)('a'+i));
} //a-z加入sb中
System.out.println(sb); //abcd...xyz
sb.reverse(); //原地反转sb
System.out.println(sb); //zyx...cba
char a = sb.charAt(2); //返回sb中参数指定下标char值 给a
System.out.println(a); //x
sb.setCharAt(2, '王'); //把参数指定下标的字符替换为第二个参数
System.out.println(sb); //zy王w...cba
// insert()返回的是StringBuilder(this),相当于把sb传回来,因此可以连用
sb.insert(3, '李').insert(4, '崔');// 链式调用
System.out.println(sb); //zy王李崔w...cba
// delete()返回的也是this
sb.delete(0, 1).delete(0, 1); // 每次删除第一个
System.out.println(sb); //王李崔wvu...cba
Date类
计算机中的基准时间在1970年1月1日00:00:00 并且度量单位是毫秒(ms),因此用long
//Date类的无参构造器中:this(System.currentTimeMillis());
Date d = new Date();
System.out.println(d); // Sat Jul 27 16:36:19 CST 2019
Date date = new Date(2000);// 输出的不是00:00:00因为时区问题,传入当前时间(ms)
System.out.println(date);// 直接打印输出的即为时间信息,应该是当前时间+2000ms
System.out.println(date.getTime());// 获取当前时间点的毫秒数
//after(),传入指定日期,测试是否在指定日期之后,同样的还有before
Date date2 = new Date();
System.out.println(date2.getTime());
System.out.println(date.after(date2));
// false,判断date是否在date2时间之后,比较的还是毫秒数
DateFormat和SimpleDateFormat的使用
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS"); // 标准
// DateFormat df2 = new SimpleDateFormat("yyyy年MM月dd日 HH时:mm分:ss //秒:SS毫秒");
// format()把时间对象按照"格式字符串指定的格式"转成相应的字符串
String str1 = df.format(new Date());
// String str2 = df2.format(new Date());
System.out.println(str1); // 2019-07-29 08:51:04:159
// System.out.println(str2);
// 把字符串按照"格式字符串指定的格式"转成相应的时间对象
// DateFormat类中的parse()返回时间对象
DateFormat df3 = new SimpleDateFormat("yyyy-MM-dd");
Date d = df3.parse("1998-12-15"); //传入的字符串格式必须和上边一行的参数保持一致
System.out.println(d);
// 测试使用其他的格式字符
DateFormat df4 = new SimpleDateFormat("yyyy-MM-DDD"); //D为当年的多少天
String str3 = df4.format(new Date());
DateFormat df5 = new SimpleDateFormat("yyyy-MM-WW");
// WW为当前月份中的第几周,ww为年中的第几周
String str4 = df5.format(new Date());
System.out.println(str4);
Calendar和GregorianCalendar日历类
Calendar类是一个抽象类,提供了关于日期计算的相关功能
我们用其实现类Gregorian类来进行操作
注意:月份表示,一月是0,12月是11
父类Calendar使用常量表示月份:JANUARY等.星期也可以用数字表示:周日是1,周1是二…
Calendar calendar = new GregorianCalendar(2019,8,29);
// 可以用get()来获取其中的一些元素
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH); // 月份从0开始
int day = calendar.get(Calendar.DATE); // 日,几号,也可以用DAY_OF_MONTH
Calendar c2 = new GregorianCalendar();// 什么都不传则默认为今天
c2.set(Calendar.YEAR, 2020); //c2年份设置为2020年
// 日期的计算
Calendar c3 = new GregorianCalendar();
c3.add(Calendar.DATE, 100); // c3往后100天
// 日期对象和时间对象的转化
Date d4 = c3.getTime(); //Calendar对象的getTime()返回Date对象
Calendar c4 = new GregorianCalendar();
c4.setTime(d4); //时间对象d4转为c4日期对象
File类基本用法 (表示文件或者目录) (详细的在I/O处)
File f = new File("d:/a.txt");
//新建一个文件对象(在当前目录下)
File f = new File("d:\\a.txt");
//也可以用"\"来作为分隔,即转义
f.createNewFile();
//创建文件
System.out.println(f);
//打印文件对象输出的是它的目录
f.renameTo(new File("d:/bb.txt"));
//重命名f对象名字
System.out.println(System.getProperty("user.dir"));
//获取当前目录
System.out.println("File是否存在:\t" + f1.exists());
System.out.println("File是否是目录:\t" + f1.isDirectory());
System.out.println("File是否是文件:\t" + f1.isFile());
System.out.println("File最后修改时间:\t" + new Date(f1.lastModified()));
System.out.println("File的大小:\t" + f1.length());
System.out.println("File的文件名:\t" + f1.getName());
System.out.println("File的目录路径(绝对):\t" + f1.getAbsolutePath());
枚举
JDK1.5引入了枚举类型.定义格式:
enum 枚举名{
枚举体(常量列表)
}
枚举体就是放置一些常量
例如:
enum Season{
SPRING,SUMMER,AUTUMN,WINTER
}
所有的枚举类型隐性地继承自java.lang.Enum.枚举实质上还是类!而每个被枚举的成员实质就是一个枚举类型的实例,他们默认都是public static final修饰的.可以直接通过枚举类型名使用它们
建议:
当你需要定义一组常量时,可以使用枚举类型
尽量不要使用枚举的高级特性,事实上高级特性都可以使用普通类来实现,没必要引入枚举,增加程序复杂性.