目录
- 1. 包装类
- 1.1 引入包装类
- 1.2 自动装箱和自动拆箱
- 1.3 == 和 equals
- 2. String 类
- 2.1 String类
- 2.2 StringBuffer 和 StringBuilder
- 3. 日期类
- 3.1 Date类
- 3.2 DateFormat类
- 3.3 Calendar 类
- 4. Math类和Random类
- 5. 枚举
- 6. File类
1. 包装类
1.1 引入包装类
我们经常使用的基本数据类型并不是对象,有时为了业务需求,需要将基本数据类型转换成对象。
Java对每个基本类型都设计了一个对应的包装类(Wrapper Class)
byte(Byte)、boolean(Boolean)、short(Short)、char(Character)、int(Integer)、long(Long)、float(Float)、double(Double)
优点:
- 某些方法的参数必须是对象。为了让基本数据类型的数据能作为参数,提供包装类
- 还可以提供更多的功能:比如字符串和基本类型之间的转换
注意:
- 包装类的对象需要占用栈内存和堆内存,而基本数据类型的(局部)变量只占用栈内存,占用空间少。
- 作为成员变量,初始值不同。 int :0, Integer :null
- 除了 Boolean 和 Character ,其余的父类都是 Number
1.2 自动装箱和自动拆箱
- 自动装箱:调用的是
valueOf()
方法
- 为了提高效率,对于 -128 ~ 127 之间的值会进行缓存处理,用数组的下标直接获得,超过范围后,则是
new Integer()
方法
- 自动拆箱:调用的是
xxxValue()
方法
Integer类的 valueOf 方法:
Integer类的内部类 IntegerCache 类:
Integer in = 5; // 自动装箱 JDK1.5提供的功能 相当于 Integer in = Integer.valueOf(5);
int n = in; // 自动拆箱
Integer in2 = new Integer(5); // 手动装箱
int n2 = in.intValue(); // 手动拆箱
1.3 == 和 equals
Integer in = new Integer(20);
Integer in2 = new Integer(20);
System.out.println(in == in2); // false, ==:引用数据类型进行比较,比地址
System.out.println(in.equals(in2)); // true equals:Integer的,进行了重写,比较对象的内容
// 自动装箱 不是直接执行的 new Integer(); 而是执行的Integer.valueOf();
Integer in3 = 123;
Integer in4 = 123;
System.out.println(in3 == in4); // [-128, 127] true, 其余为false
System.out.println(in3.equals(in4)); // true
Integer in5 = 1234;
Integer in6 = 1234;
System.out.println(in5 == in6); // false
System.out.println(in5.equals(in6)); // true
2. String 类
String、StringBuilder、StringBuffer 类是三个字符串相关的类
- String:不可变的字符序列(一旦赋值,便不可改变。 再次赋值时,新开辟一个位置,内容指向新的位置)
- StringBuilder:可变的字符序列,线程不安全
- StringBuffer:可变的字符序列,线程安全
2.1 String类
创建字符串对象:
String str = new String("我是一个字符串aBc");
String str1 = new String("我是一个字符串aBc");
str == str1; // false
str.equals(str1); // true
String str2 = "lwclick";
String str3 = "lwclick";
str2 == str3; // true !!!!!!!
str2.equals(str3); // true
“” 和 null 的区别:
String str4 = "";
String str5 = null;
操作字符串对象:
// 2.1 最基本的操作
str.length(); // 字符的个数,不是字节的个数
str.isEmpty(); // 是否为空
str.startsWith("我是"); // 是否以 XX 开始
str.endsWith("字符串"); // 是否以 XX 结尾
str.toUpperCase(); // 全部转为大写
str.toLowerCase(); // 全部转为小写
// String 是不可变的字符序列,所以即使上面变成了全部小写,输出仍为原来的
System.out.println(str); // str = str.toLowerCase(); 改变指向
str.contains("aB"); // 是否包含 XX
// 2.2 根据索引确定子串
str.charAt(3); // 第 N 个字符。 拿到 "个"
str.substring(1, 3); // 从 M 开始,到 N 结束的字符。 拿到 "是一" 范围为:[1, 3)
str.substring(4); // 从 N 之后的所有字符。 拿到 "字符串aBc"
// 2.3 根据子串确定索引
str = "字符串abcABcabc";
str.indexOf("abc"); // abc 【第一次】出现的索引位置 ==》 3
str.indexOf("abc", 6); // 从索引为 6 的位置开始找 abc 第一次出现的位置
str.lastIndexOf("abc"); // abc 【最后一次】出现的位置
// 2.4 其他
str.replaceAll("ab", "dd"); // 将 ab 【全部】替换为 dd
str.trim(); // 去掉【两端】的空格
// String --> byte[]
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes)); // 输出数组内容 Arrays.toString()
// byte[] --> String
String str1 = new String(bytes);
new String(bytes, 0, 9); // 从第 0 个开始取,取长度为 9 的(转成byte后,一个汉字占3个)
字符串的连接:(String类的缺点,每次连接,都产生一个字符串然后变成垃圾
)
String str = "中国";
str = str.concat("山东");
str = str.concat("济南");
String类的源码:
- String类是一个 final 类,不能再有子类
- 底层是一个字符数组 value,各种方法的操作其实都是对该数组的操作
String源码中的equals
方法:
String源码中的compareTo
方法:
String源码中的concat
方法:
最后,返回了一个 new String(buf, true)
,也就是 新生成了一个字符串
2.2 StringBuffer 和 StringBuilder
都代表可变的字符序列,都是抽象类 AbstractStringBuilder 的子类
- StringBuffer:JDK1.0 提供的类,线程安全,做线程同步检查,效率较低
- StringBuilder:JDK1.5 提供的类,线程不安全,不做线程同步检查,效率高。建议使用
StringBuilder类的使用:
- 创建一个 StringBuilder 对象:
StringBuilder sb = new StringBuilder("我是一个字符串");
其实是将 String 转变为 StringBuilder - 在末尾追加内容:
sb.append(",我是追加的内容");
- 转换为字符串进行操作:
sb.toString();
StringBuilder 的使用场合:SQL 语句的拼接(通过条件,拼接不同的 SQL)
StringBuilder 的其他方法:
- 首尾反转:
sb.reverse();
- 中间添加:
sb.insert(7, "要添加的内容");
在索引为 7 的位置添加内容 - 删除:
sb.delete(m, n);
删除索引为 m 到 n 的内容sb.deleteCharAt(6);
删除索引为 6 的位置的内容 - 修改操作:
sb.replace(m, n, "XXX")
将索引为 m 到 n 的内容替换为 XXX
StringBuilder 的源码:
底层 value 数组的默认长度:
append方法的扩容机制:
3. 日期类
在计算机中,把 1970年 1月 1日 00:00:00 定为基准时间,每个度量单位为 毫秒
3.1 Date类
其中的很多方法已经过时,在实际开发中,只是使用它来获取当前时间
Date date = new Date(); // 获取当前的时间, 相当于 new Date(System.currentTimeMillis());
date.getTime(); // 获得毫秒数,底层使用 fastTime 存储
// java.util.Date 的三个子类
java.sql.Date sDate; // YYYYMMDD
java.sql.Time sTime; // HHMMSS
java.sql.Timestamp timestamp; // YYYYMMDD HHMMSS 更精确
// java.sql.Date 相关的知识
// util.Date --> sql.Date
java.sql.Date sdate = new java.sql.Date(date.getTime());
// 将字符串的日期转变为sql.Date类
java.sql.Date sdate2 = java.sql.Date.valueOf("1999-01-12");
// ========================================== 已过时 =================================
date.toLocaleString(); // 使用者本地的时间
date.getYear(); // 年份: 当前年 - 1900
date.getMonth(); // 月份: 0 - 11
date.getDate(); // 日
date.getDay(); // 星期几:0 - 6
date.getHours(); // 时
date.getMinutes(); // 分
date.getSeconds(); // 秒
3.2 DateFormat类
DateFormat类是一个抽象类,一般使用它的子类 SimpleDateFormat 类来实现
主要作用:将时间对象转换为指定格式的字符串,将字符串转换为时间对象。
// 创建一个 DateFormat 对象
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 字符串 --> Date
Date date = sdf.parse("2018-10-10 23:18:42"); // parse() 参数为字符串,返回 Date
// Date --> 字符串
String str = sdf.format(date); // format() 参数为Date,返回字符串
3.3 Calendar 类
关于日期计算的相关功能
// 获取当前的时间
Calendar cal = Calendar.getInstance();
// 【结果】:java.util.GregorianCalendar[time=1623158467037,areFieldsSet=true,areAllFieldsSet=true,
// lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,
// dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,
// minimalDaysInFirstWeek=1,ERA=1,YEAR=2021,MONTH=5,WEEK_OF_YEAR=24,WEEK_OF_MONTH=2,
// DAY_OF_MONTH=8,DAY_OF_YEAR=159,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,
// HOUR_OF_DAY=21,MINUTE=21,SECOND=7,MILLISECOND=37,ZONE_OFFSET=28800000,DST_OFFSET=0]
基本的操作:
// 获取当前时间的各个部位
cal.get(Calendar.YEAR); // 年
cal.get(Calendar.MONTH); // 月 0-11
cal.get(Calendar.DATE); // 日
cal.get(Calendar.DAY_OF_WEEK); // 周日是1,周六是7
// 修改当前时间的各个部分
cal.set(Calendar.YEAR, 2018); // 将年份改成 2018 年
// 将时间修改为当月的第一天
cal.set(Calendar.DATE, 1);
// 判断今天是否是周六
cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY;
// 获取当月一共多少天
cal.getActualMaximum(Calendar.DATE);
// 将天数加一天
cal.add(Calendar.DATE, 1);
// Date --> Calendar setTime() 方法
Date date = new Date();
cal.setTime(date);
// Calendar --> Date getTime() 方法
Date time = cal.getTime();
4. Math类和Random类
// 如果使用静态导入, import static java.lang.Math.*;
// 可以直接使用 PI 等
Math.PI;
Math.abs(-3.14); // 绝对值
Math.floor(3.14); // 向下取整 3.0
Math.ceil(3.14); // 向上取整 4.0
Math.round(3.14); // 四舍五入
Math.sqrt(25); // 开平方
Math.pow(2, 5); // 2的5次幂
Math 的源码:
Random类:
// 声明一个 Random 对象
Random rand = new Random(); // new Random(10); 种子,随机数的产生取决于种子
// 产生 min 到 max 之间的随机数
rand.nextInt(max - min + 1) + min; // [min, max]之间的数
// 也可以直接使用 Math.random()
(int) (Math.random() * (max - min + 1)) + min;
5. 枚举
定义枚举使用 enum
关键字,JDK 1.5 引入,适用于放置一些常量(性别、季节、星期几)
所有的枚举类型隐性地继承自 java.lang.Enum,每个被枚举的成员(男,女。。)实质上就是一个枚举类型的实例,默认都是public static final
修饰,可以通过枚举类型名使用它们
定义枚举类:
public enum Gander {
man, woman // 默认使用 public static final 修饰
}
使用枚举 – 设置实体类的属性值:
public class People {
private String name;
private Gander gander;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Gander getGander() {
return gander;
}
public void setGander(Gander gander) {
this.gander = gander;
}
public static void main(String[] args) {
People people = new People();
people.setGander(Gander.man); // 此处使用,限定了性别只有 男女
}
}
使用枚举 – switch语句:
Gander g = Gander.man;
switch (g) { // 参数直接放入枚举的【对象】
case man: // case 处,直接使用【属性】
System.out.println("我是一个男人");
break;
case woman:
System.out.println("我是一个女生");
break;
}
6. File类
作用:获取文件或文件夹的属性; 实现对文件、文件夹的创建和删除
不能对文件内容进行修改,需要借助 IO 流
作用1:获取文件或文件夹的属性
// 创建一个 File 对象,指向一个文件或文件夹
File file = new File("E:/readme.txt");
File file = new File("E:\\importantFilet");
// 获取属性
file.getName(); // 文件名
file.getAbsoluteFile(); // 绝对路径
file.exists(); // 是否存在
file.length(); // 文件的长度
file.isFile(); // 是文件吗
file.isDirectory(); // 是文件夹吗
file.canRead(); // 是否可读
new Date(file.lastModified()).toLocaleString(); // 最后修改的时间
File dir = file.getParentFile(); // 获取当前文件的父级文件
File[] files = dir.listFiles(); // 得到目录下的所有文件!!!!!!
作用2:实现对文件、文件夹的创建和删除
// 使用 File 指向一个文件
File file = new File("E:/readme.txt");
// 如果存在就删除,如果不存在就创建
if (file.exists()) {
file.delete();
} else {
File dir = file.getParentFile();
if (!dir.exists()) {
dir.mkdirs(); // 一次创建多级目录
dir.mkdir(); // 一次创建一级目录
}
try {
file.createNewFile(); // 创建文件
} catch (IOException e) {
e.printStackTrace();
}
}
实例:显示文件夹下的内容
File dir = new File("F:\\attendanceManage");
File[] files = dir.listFiles();
for (File file : files) {
System.out.print(new Date(file.lastModified()).toLocaleString() + "\t");
if (file.isDirectory()) {
System.out.print("文件夹 \t");
System.out.print(" ");
} else {
System.out.print("文件 \t");
System.out.print(file.length() + "\t");
}
System.out.print(file.getName());
System.out.println();
}