day4包装类、数组
基本数据类型及其包装类
byte | Byte |
---|---|
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
注:Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean
直接返回 True
or False
。
自动拆装箱原理
// 在没有自动拆装箱之前,我们使用包装类需要使用new的方式
Integer integer1 = new Integer(3);
public class Chap01 {
// 自动装箱:调用了对应包装类(Integer)的valueOf()方法
// 自动拆箱:调用了对应包装类(Integer)的xxxValue()(intValue)方法
public static void main(String[] args) {
// 装箱
Integer integer = Integer.valueOf(1);
// 拆箱
int i = integer.intValue();
}
}
// 装箱源码
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
public static Integer valueOf(int i) {
// 这里需要特别注意,满足当前条件,引用指向的是同一个包装类(-128, 127)
// IntegerCache的源码可以看看
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
public static Boolean valueOf(boolean b) {
// TRUE : FALSE 是两个静态常量
return (b ? TRUE : FALSE);
}
// 其他的类似
测试
public class Chap01 {
public static void main(String[] args) {
Integer integer1 = 3;
Integer integer2 = 3;
Integer integer3 = 128;
Integer integer4 = 128;
// true 装箱的范围为(-128, 127),指向的是同一个对象
System.out.println(integer1 == integer2);
// false 超出了给定点的范围,每次都会新建一个对象
System.out.println(integer3 == integer4);
// true equals() 比较的是对象中的属性值
System.out.println(integer3.equals(integer4));
Boolean boolean1 = true;
Boolean boolean2 = true;
// true 使用的是同一个对象,true/false在源码中是一个静态常量
System.out.println(boolean1 == boolean2);
Double double1 = 5.4;
Double double2 = 5.4;
// false
System.out.println(double1 == double2);
Integer i1 = 40;
Integer i2 = new Integer(40);
// false 装箱,等价于 Integer i1=Integer.valueOf(40),使用的是缓存中的数据
// 而 Integer i2 = new Integer(40) 会直接创建新的对象
System.out.println(i1 == i2);
}
}
Math工具类
// 常用方法
public class Chap03 {
public static void main(String[] args) {
System.out.println(Math.abs(-38273));
System.out.println(Math.min(323, 434));
System.out.println(Math.max(32, 90));
System.out.println(Math.PI);
System.out.println(Math.E);
System.out.println(Math.ceil(32.79)); // 大于等于的最小整数
System.out.println(Math.floor(43.5)); // 小于等于的最大整数
System.out.println(Math.rint(54.7)); // 四舍五入
System.out.println(Math.round(3.7f));
System.out.println(Math.sin(Math.PI/2));
System.out.println(Math.asin(1)); //反正弦
System.out.println(Math.toDegrees(1)); // 弧度制转角度制
System.out.println(Math.toRadians(90)); // 角度制转弧度制
System.out.println(Math.exp(3)); // e的三次幂
System.out.println(Math.pow(2, 4)); // 2的四次幂
System.out.println(Math.sqrt(4)); // 4的平方根
System.out.println(Math.cbrt(8)); // 8的立方根
System.out.println(Math.log(Math.E));
System.out.println(Math.log10(10));
}
}
Date: 用于获取当前时间(new Date())和时间戳(date.getTime())
Calendar:日历类(抽象类)
- 可以产生实现特定语言和日历风格的日期时间格式化所需的所有日历字段值(例如日语 - 公历,日语 - 繁体)。
public class Chap04 {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());
// 初始化日历对象
Calendar rightNow = Calendar.getInstance();
System.out.println(rightNow.getTime()); // 获取当前时间,为Date对象
System.out.println(rightNow.getTimeInMillis()); // 时间戳
System.out.println(rightNow.get(Calendar.YEAR)); // 年
// Calendar.MONTH的范围为(0, 11)
System.out.println(rightNow.get(Calendar.MONTH) + 1); // 月
System.out.println(rightNow.get(Calendar.DAY_OF_MONTH)); // 日
System.out.println(rightNow.get(Calendar.HOUR_OF_DAY)); // 时
System.out.println(rightNow.get(Calendar.MINUTE)); // 分
System.out.println(rightNow.get(Calendar.SECOND)); // 秒
// 源码使用的是星期天为一,星期一为二
System.out.println(rightNow.get(Calendar.DAY_OF_WEEK) - 1); // 星期
rightNow.set(Calendar.YEAR, 2008); // set方法,与get相似
System.out.println(rightNow.get(Calendar.YEAR)); // 2008
// 格式化时间信息
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
System.out.println(sdf.format(rightNow.getTime())); // 2008年06月02日 13:04:52
}
}
Random
- 该类的实例用于生成伪随机数的流
- 如果使用相同的种子创建两个Random
Random
,并且对每个实例进行相同的方法调用序列,则它们将生成并返回相同的数字序列 - 线程安全的, 在多线程设计中考虑使用
ThreadLocalRandom
- 不是加密安全的。 考虑使用
SecureRandom
获取一个加密安全的伪随机数生成器
public class Chap05 {
public static void main(String[] args) throws NoSuchAlgorithmException {
// 构造方法,可以设置构造随机数的种子
Random random = new Random();
// nextInt(54) 获取0, 54的随机整数,其他基本数据类型同理
System.out.println(random.nextInt(54));
// 用相同的种子构建,两个对象获得的随机数是相同的
Random random1 = new Random(10);
Random random2 = new Random(10);
// 13, 13
System.out.println(random1.nextInt(100) + ", " + random2.nextInt(100));
// 多线程的时候使用,线程不安全
ThreadLocalRandom current = ThreadLocalRandom.current();
System.out.println(current.nextInt(100));
// 获取一个加密安全的伪随机数生成器
SecureRandom secureRandom = new SecureRandom();
System.out.println(secureRandom.nextInt(100));
}
}
String, StringBuffer, StringBuilder
类\区别 | 是否可变 | 初始化方式 | 修改方式 | 是否实现了equals/hashCode | 是否线程安全 |
---|---|---|---|---|---|
String | n | 直接赋值/构造器 | 拼接 | y | |
StringBuffer | y | 构造器 | 函数append() | n | y |
StringBuilder | y | 构造器 | 函数append() | n | n |
StringBuffer
与StringBuilder
的源码分析
// 初始容量
public StringBuilder() {
super(16);
}
// 使用的是char型数组
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
// jdk9 改成了byte数组
AbstractStringBuilder(int capacity) {
if (COMPACT_STRINGS) {
value = new byte[capacity];
coder = LATIN1;
} else {
value = StringUTF16.newBytesFor(capacity);
coder = UTF16;
}
}
// append与扩容
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len); // 判断是否需要扩容
str.getChars(0, len, value, count);
count += len;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) { // 所需要的容量 - 当前容量
// 复制数组的方式进行扩容
value = Arrays.copyOf(value,
newCapacity(minimumCapacity)); // 扩容机制
}
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2; // 扩容为原来的二倍加二
if (newCapacity - minCapacity < 0) { // 如果容量还是不够,就将容量设置为字符长度
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
Calendar
打印日历信息
public class Chap07 {
private static final Calendar instance = Calendar.getInstance();
public static void main(String[] args) {
calendar();
}
private static void calendar(){
// 将时间设置为这个月的第一天
instance.set(Calendar.DAY_OF_MONTH, 1);
// 获取这个月第一天的星期信息
int week = instance.get(Calendar.DAY_OF_WEEK) - 1;
System.out.println("********************************");
System.out.println("日\t一\t二\t三\t四\t五\t六");
// 空格填充
for (int i = 0; i < week; i++) {
System.out.print("\t");
}
// 遍历当月的每一天
for (int i = 1; i <= instance.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
System.out.print(i + "\t");
// 每隔七天换行
if ((i + week) % 7 == 0){
System.out.println();
}
}
System.out.println("\n********************************");
}
}
计算输入与现在的时间差
public class Chap08 {
private static final Scanner scanner = new Scanner(System.in);
private static final Calendar calendar = Calendar.getInstance();
public static void main(String[] args) throws ParseException {
while (true){
System.out.print("请输入日期(6-3)(-1退出):");
String next = scanner.next();
if (next.equals("-1")) break;
String[] split = next.trim().split("-");
if (split.length == 2) {
Date now = new Date(); // 拿到当前时间
System.out.println(now);
// 设置月份
calendar.set(Calendar.MONTH, Integer.parseInt(split[0]) - 1);
// 设置日
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(split[1]));
// 设置当天凌晨
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date input = calendar.getTime(); // 获取输入时间
long l = input.getTime() - now.getTime(); // 获取时间差
if (l > 0){
double minute = l/1000.0/60.0; // 拿到多少分
System.out.print("距离纪念日还有:");
if (minute / 60.0 / 24.0 > 1){
System.out.print((int)(minute / 60.0 / 24) + "天");
minute -= (int)(minute / 60.0 / 24) * 24 * 60;
}
if (minute / 60.0 > 1){
System.out.print((int)(minute / 60) + "时");
minute -= (int)(minute / 60) * 60;
}
System.out.println((int)(minute) + "分");
}else System.out.println("时间是不会倒流的,请输入未来的时间");
} else {
System.out.println("请输入正确的格式(月份-日期)");
}
}
}
}