八种基本数据类型相应的引用类型—包装类,有了类的特点,就可以调用类中的方法。
基本数据类型 | 包装类 |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
包装类和基本数据的转换
valueOf
方法,比如Integer.valueOf
其它包装类的用法类似public class Integer01 {
public static void main(String[] args) {
//演示int <--> Integer 的装箱和拆箱
//jdk5前是手动装箱和拆箱
//手动装箱 int->Integer
int n1 = 100;
Integer integer = new Integer(n1);
Integer integer1 = Integer.valueOf(n1);
//手动拆箱
//Integer -> int
int i = integer.intValue();
//jdk5后,就可以自动装箱和自动拆箱
int n2 = 200;
//自动装箱 int->Integer
Integer integer2 = n2; //底层使用的是 Integer.valueOf(n2)
//自动拆箱 Integer->int
int n3 = integer2; //底层仍然使用的是 intValue()方法
}
}
package com.hspedu.wrapper;
public class WrapperVSString {
public static void main(String[] args) {
//包装类(Integer)->String
Integer i = 100;//自动装箱
//方式1
String str1 = i + "";
//方式2
String str2 = i.toString();
//方式3
String str3 = String.valueOf(i);
//String -> 包装类(Integer)
String str4 = "12345";
Integer i2 = Integer.parseInt(str4);//使用到自动装箱
Integer i3 = new Integer(str4);//构造器
System.out.println("ok~~");
}
}
String
对象用于保存字符串,也就是一组字符序列
字符串常量对象是用双引号括起的字符序列。例如:“你好”、“12.97”、"boy"等
字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
String
实现Serializable
,说明可以串行化,即可以在网络上传输。
String
实现接口Comparable
[String
对象可以比较大小]
// 通过构造器创建
String s1 =new String();
String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a, int startIndex, int count)
//直接赋值
String s = "cc"
两种创建String 对象的区别
方式一:先在堆中创建空间,里面维护了value
属性,指向常量池的"cc"空间。如果常量池没有"cc",重新创建,如果有,直接通过value
指向,最终指向的是堆中的空间地址。
方式二:先从常量池查看是否有"cc”数据空间,如果有,直接指向。如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址。
当调用intern
方法时,如果池已经包含一个等于此 String
对象的字符串(用equals(Object)
方法确定),则返回池中的字符串。
否则将此String
对象添加到池中,并返回此 String
对象的引用
s.intern
方法最终返回的是常量池的地址(对象)
String
是一个final
类,代表不可变的字符序列。
字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的。
string s="a";//创建了一个字符串
s +="b";//实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+"b”(也就是"ab")。
如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。
如果这样的操作放到循环中,会极大影响程序的性能
String
类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低
因此java设计者还提供了StringBuilder
和 StringBuffer
来增强String
的功能,并提高效率。
equals
//区分大小写,判断内容是否相等equalsIgnoreCase
//忽略大小写的判断内容是否相等length/获取字符的个数,字符串的长度length
获取字符的个数,字符串的长度indexOf
//获取字符在字符串中第1次出现的索引索引从0开始,如果找不到,返回-1lastIndexOf
//获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1substring
//截取指定范围的子串trim
//去前后空格charAt
// 获取某索引处的字符, 注意不能使用Str[index]这种方式getChars
// 截取多个字符getBytes
//替代getChars
的一种方法是将字符存储在字节数组中toUpperCase
//转大写toLowerCase
//转小写concat
//字符串合成replace
替换字符串中的字符split
分割字符串,对于某些分割字符,我们需要转义比如| \\等compareTo
//比较两个字符串的大小compareToIgnoreCase
// 忽略大小写比较toCharArray
//转换成字符数组egionMatches
// 用于比较一个字符串中特定区域与另一特定区域,它有一个重载的形式允许在比较中忽略大小写format
//格式字符串,%s字符串%c字符%d整型%.2f 浮点型案例,将一个人的信息格式化输出startsWith
// 决定是否以特定字符串开始endsWith
// 决定是否以特定字符串结束valueOf
// 转换为字符串java.lang.StringBuffer
代表可变的字符序列,可以对字符串内容进行增删。
很多方法与String
相同,但StringBuffer
是可变长度的容器。
String
保存的是字符串常量。里面的值不能更改,每次String
类的更新实际上就是更改地址,效率较低
StringBuffer
保存的是字符串变量,里面的值可以更改,每次StringBuffer
的更新实际上可以更新内容,不用每次更新地址(空间大小不够的时候才会进行扩展),效率较高。
AbstractStringBuilder
Serializable
, 即StringBuffer
的对象可以串行化AbstractStringBuilder
有属性 char[] value
,不是final
,该 value
数组存放 字符串内容,因此存放在堆中的。final
类,不能被继承String 和 StringBuffer 相互转换
public class StringAndStringBuffer {
public static void main(String[] args) {
// String——>StringBuffer
String str = "hello tom";
//方式1 使用构造器
//注意:返回的才是StringBuffer对象,对 str 本身没有影响
StringBuffer stringBuffer = new StringBuffer(str);
//方式2:使用的是append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str);
// StringBuffer ->String
StringBuffer stringBuffer3 = new StringBuffer("timerring");
//方式1:使用StringBuffer提供的 toString方法
String s = stringBuffer3.toString();
//方式2:使用构造器来搞定
String s1 = new String(stringBuffer3);
}
}
append
把任何类型数据的字符串加入对象的末尾delete
// 删除索引为>=start && replace
// 替换字符insert
//在索引为index的位置插入 ,原来索引为index的内容自动后移length
//长度setLength
// 设置缓冲区的长度capacity
// 获取可分配空间ensureCapacity
// 设置缓冲区的大小charAt
// 获取索引位置的字符setCharAt
// 设置索引位置的字符getChars
// 获取多个字符reverse
// 颠倒StringBuffer
对象中的字符deleteCharAt
//删除索引位置的字符substring
// 截取子串一个可变的字符序列。此类提供一个与 StringBuffer兼容的API,但不保证同步(StringBuilder
不是线程安全)。
该类被设计用作 StringBuffer
的一个简易替换,用在字符串缓冲区被单个线程使用的时候。
如果可能,建议优先采用该类。因为在大多数实现中,它比 StringBuffer 要快。
在 StringBuilder
上的主要操作是append
和 insert
方法,可重载这些方法,以接受任意类型的数据。
AbstractStringBuilder
类Serializable
,说明StringBuilder
对象是可以串行化(对象可以网络传输,可以保存到文件) AbstractStringBuilder
的 char[] value
;因此字符序列是堆中synchronized
关键字,因此在单线程的情况下使用 StringBuilder
String、StringBuffer 和StringBuilder 的比较
StringBuilder
和 StringBuffer
均代表可变的字符序列,方法是一样的,所以使用和StringBuffer
一样。
String
:不可变字符序列,效率低,但是复用率高(地址都指向它)。StringBuffer
:可变字符序列、效率较高(增删)、线程安全,看源码StringBuilder
:可变字符序列、效率最高、线程不安全如果我们对String
做大量修改,不要使用String
StringBuffer
或StringBuilder
StringBuilder
StringBuffer
String
, 比如配置信息等构建了一个字符容器,指定分隔符
StringJoiner(CharSequence delimiter)
构建了一个字符容器,指定分隔符,前缀,后缀
StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
setEmptyValue
//设置空值toString
// 把容器中的数据以字符串返回add
//添加字符串,也就是拼接,这个方法只能拼接字符串merge
//从另一个StringJoiner
合并length
// 返回该 StringJoiner
的 String
表示长度(包括前后缀)
StringJoiner
跟StringBuilder
一样,也可以看成是一个容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁。
JDK8出现的
基本使用:
//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);//aaa---bbb---ccc
//1.创建对象
StringJoiner sj = new StringJoiner(", ","[","]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//15
//3.打印
System.out.println(sj);//[aaa, bbb, ccc]
String str = sj.toString();
System.out.println(str);//[aaa, bbb, ccc]
Math
类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
public class MathMethod {
public static void main(String[] args) {
//看看Math常用的方法(静态方法)
//1.abs 绝对值
int abs = Math.abs(-9);
System.out.println(abs);//9
//2.pow 求幂
double pow = Math.pow(2, 4);//2的4次方
System.out.println(pow);//16
//3.ceil 向上取整,返回>=该参数的最小整数(转成double);
double ceil = Math.ceil(3.9);
System.out.println(ceil);//4.0
//4.floor 向下取整,返回<=该参数的最大整数(转成double)
double floor = Math.floor(4.001);
System.out.println(floor);//4.0
//5.round 四舍五入 Math.floor(该参数+0.5)
long round = Math.round(5.51);
System.out.println(round); //6
//6.sqrt 求开方
double sqrt = Math.sqrt(9.0); // 当然,如果复数开方的话则NaN
System.out.println(sqrt); //3.0
//7.random 求随机数
// random 返回的是 0 <= x < 1 之间的一个随机小数
// Math.random()
//max , min 返回最大值和最小值
int min = Math.min(1, 9);
int max = Math.max(45, 90);
System.out.println("min=" + min);
System.out.println("max=" + max);
}
}
Arrays
里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)。
toString
返回数组的字符串形式 Arrays.toString(arr)
binarySearch
通过二分搜索法进行查找,要求必须排好序。
copyOf
数组元素的复制
fill
数组元素的填充
equals
比较两个数组元素内容是否完全一致
asList
将一组值,转换成list
sort
排序(自然排序和定制排序) Integer arr[] = {1,-1,7,0,89}
import java.util.Arrays;
import java.util.Comparator;
public class ArraysMethod01 {
public static void main(String[] args) {
Integer[] integers = {1, 20, 90};
//遍历数组
// for(int i = 0; i < integers.length; i++) {
// System.out.println(integers[i]);
// }
//直接使用Arrays.toString方法,显示数组
// System.out.println(Arrays.toString(integers));//
//演示 sort方法的使用
Integer arr[] = {1, -1, 7, 0, 89};
//进行排序
//老韩解读
//1. 可以直接使用冒泡排序 , 也可以直接使用Arrays提供的sort方法排序
//2. 因为数组是引用类型,所以通过sort排序后,会直接影响到 实参 arr
//3. sort重载的,也可以通过传入一个接口 Comparator 实现定制排序
//4. 调用 定制排序 时,传入两个参数 (1) 排序的数组 arr
// (2) 实现了Comparator接口的匿名内部类 , 要求实现 compare方法
//5. 先演示效果,再解释
//6. 这里体现了接口编程的方式 , 看看源码,就明白
// 源码分析
//(1) Arrays.sort(arr, new Comparator()
//(2) 最终到 TimSort类的 private static void binarySort(T[] a, int lo, int hi, int start,
// Comparator super T> c)()
//(3) 执行到 binarySort方法的代码, 会根据动态绑定机制 c.compare()执行我们传入的
// 匿名内部类的 compare ()
// while (left < right) {
// int mid = (left + right) >>> 1;
// if (c.compare(pivot, a[mid]) < 0)
// right = mid;
// else
// left = mid + 1;
// }
//(4) new Comparator() {
// @Override
// public int compare(Object o1, Object o2) {
// Integer i1 = (Integer) o1;
// Integer i2 = (Integer) o2;
// return i2 - i1;
// }
// }
//(5) public int compare(Object o1, Object o2) 返回的值>0 还是 <0
// 会影响整个排序结果, 这就充分体现了 接口编程+动态绑定+匿名内部类的综合使用
// 将来的底层框架和源码的使用方式,会非常常见
//Arrays.sort(arr); // 默认排序方法
//定制排序
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2 - i1;
}
});
System.out.println("===排序后===");
System.out.println(Arrays.toString(arr));//
}
}
自定义实现排序顺序:
import java.util.Arrays;
import java.util.Comparator;
public class ArraysSortCustom {
public static void main(String[] args) {
int[] arr = {1, -1, 8, 0, 20};
//bubble01(arr);
bubble02(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
int i1 = (Integer) o1;
int i2 = (Integer) o2;
return i2 - i1;// return i2 - i1;
}
});
System.out.println("==定制排序后的情况==");
System.out.println(Arrays.toString(arr));
}
//使用冒泡完成排序
public static void bubble01(int[] arr) {
int temp = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
//从小到大
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
//结合冒泡 + 定制
public static void bubble02(int[] arr, Comparator c) {
int temp = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
//数组排序由 c.compare(arr[j], arr[j + 1])返回的值决定
if (c.compare(arr[j], arr[j + 1]) > 0) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
exit
退出当前程序,0 表示一个状态 , 正常的状态。arraycopy
复制数组元素,比较适合底层调用,一般使用Arrays.copyOf
完成复制数组。currentTimeMillens
返回当前时间距离1970-1-1的毫秒数。gc
运行垃圾回收机制 System.gc();
。import java.util.Arrays;
public class System_ {
public static void main(String[] args) {
// System.out.println("ok1");
// //1. exit(0) 表示程序退出
// //2. 0 表示一个状态 , 正常的状态
// System.exit(0);//
// System.out.println("ok2");
//arraycopy :复制数组元素,比较适合底层调用,
// 一般使用Arrays.copyOf完成复制数组
int[] src={1,2,3};
int[] dest = new int[3];// dest 当前是 {0,0,0}
//1. 主要是搞清楚这五个参数的含义
//2.
// 源数组
// * @param src the source array.
// srcPos: 从源数组的哪个索引位置开始拷贝
// * @param srcPos starting position in the source array.
// dest : 目标数组,即把源数组的数据拷贝到哪个数组
// * @param dest the destination array.
// destPos: 把源数组的数据拷贝到 目标数组的哪个索引
// * @param destPos starting position in the destination data.
// length: 从源数组拷贝多少个数据到目标数组
// * @param length the number of array elements to be copied.
System.arraycopy(src, 0, dest, 0, src.length);
// int[] src={1,2,3};
System.out.println("dest=" + Arrays.toString(dest));//[1, 2, 3]
//currentTimeMillens:返回当前时间距离1970-1-1 的毫秒数
System.out.println(System.currentTimeMillis());
}
}
Biglnteger
适合保存比较大的整型
BigDecimal
适合保存精度更高的浮点型(小数)
在对 BigInteger
进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * /
add
加subtract
减multiply
乘divide
除Date
精确到毫秒,代表特定的瞬间SimpleDateFormat
格式和解析日期的类:它允许进行格式化(日期->文本)、解析(文本->日期)和规范化。import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Date01 {
public static void main(String[] args) throws ParseException {
//1. 获取当前系统时间
//2. 这里的Date 类是在java.util包
//3. 默认输出的日期格式是国外的方式, 因此通常需要对格式进行转换
Date d1 = new Date(); //获取当前系统时间
System.out.println("当前日期=" + d1); // 当前日期=Mon Apr 24 13:40:14 CST 2023
Date d2 = new Date(9234567); //通过指定毫秒数得到时间
System.out.println("d2=" + d2); //获取某个时间对应的毫秒数 d2=Thu Jan 01 10:33:54 CST 1970
//1. 创建 SimpleDateFormat对象,可以指定相应的格式
//2. 这里的格式使用的字母是规定好,不能乱写
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
String format = sdf.format(d1); // format:将日期转换成指定格式的字符串
System.out.println("当前日期=" + format); // 当前日期=2023年04月24日 01:40:14 星期一
//1. 可以把一个格式化的String 转成对应的 Date
//2. 得到Date 仍然在输出时,还是按照国外的形式,如果希望指定格式输出,需要转换
//3. 在把String -> Date , 使用的 sdf 格式需要和你给的String的格式一样,否则会抛出转换异常
String s = "1996年01月01日 10:20:30 星期一";
Date parse = sdf.parse(s);
System.out.println("parse=" + sdf.format(parse)); // parse=1996年01月01日 10:20:30 星期一
}
}
第二代日期类,主要就是Calendar
类(日历)。
public abstract class Calendar extends Object implements Serialzable,Cloneable, Comparable<Calendar>
Calendar
类是一个抽象类,它为特定瞬间与一组诸如YEAR
、MONTH
、DAY_OF_MONTH
、HOUR
等日历定股之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
import java.util.Calendar;
public class Calendar_ {
public static void main(String[] args) {
// 1. Calendar是一个抽象类, 并且构造器是private
// 2. 可以通过 getInstance() 来获取实例
// 3. 提供大量的方法和字段提供给程序员
// 4. Calendar没有提供对应的格式化的类,因此需要程序员自己组合来输出(灵活)
// 5. 如果我们需要按照 24小时进制来获取时间, Calendar.HOUR ==改成=> Calendar.HOUR_OF_DAY
Calendar c = Calendar.getInstance(); //创建日历类对象//比较简单,自由
System.out.println("c=" + c);
// 2.获取日历对象的某个日历字段
System.out.println("年:" + c.get(Calendar.YEAR));
// 这里为什么要 + 1, 因为Calendar 返回月时候,是按照 0 开始编号
System.out.println("月:" + (c.get(Calendar.MONTH) + 1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
System.out.println("小时:" + c.get(Calendar.HOUR));
System.out.println("分钟:" + c.get(Calendar.MINUTE));
System.out.println("秒:" + c.get(Calendar.SECOND));
// Calender 没有专门的格式化方法,所以需要程序员自己来组合显示
System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH) +
" " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) );
}
}
Date
、Calendar
存在问题是:
Date
有用,Calendar
则不行。LocalDate
(日期/年月日)、LocalTime
(时间/时分秒)、LocalDateTime
(日期时间/年月日时分秒) JDK8加入:
LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()
System.out.println(ldt);
ldt.getYear();
ldt.getMonthValue();
ldt.getMonth();
ldt.getDayofMonth();
ldt.getHour();
ldt.getMinute();
ldt.getSecond();
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
public class LocalDate_ {
public static void main(String[] args) {
//第三代日期
//1. 使用now() 返回表示当前日期时间的 对象
LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()
System.out.println(ldt);
//2. 使用DateTimeFormatter 对象来进行格式化
// 创建 DateTimeFormatter对象
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = dateTimeFormatter.format(ldt);
System.out.println("格式化的日期=" + format);
System.out.println("年=" + ldt.getYear());
System.out.println("月=" + ldt.getMonth());
System.out.println("月=" + ldt.getMonthValue());
System.out.println("日=" + ldt.getDayOfMonth());
System.out.println("时=" + ldt.getHour());
System.out.println("分=" + ldt.getMinute());
System.out.println("秒=" + ldt.getSecond());
LocalDate now = LocalDate.now(); //可以获取年月日
LocalTime now2 = LocalTime.now();//获取到时分秒
//提供 plus 和 minus 方法可以对当前时间进行加或者减
//看看890天后,是什么时候 把 年月日-时分秒
LocalDateTime localDateTime = ldt.plusDays(890);
System.out.println("890天后=" + dateTimeFormatter.format(localDateTime));
//看看在 3456分钟前是什么时候,把 年月日-时分秒输出
LocalDateTime localDateTime2 = ldt.minusMinutes(3456);
System.out.println("3456分钟前 日期=" + dateTimeFormatter.format(localDateTime2));
}
}
DateTimeFormatter 格式日期类
类似于 SimpleDateFormat
LocalDateTime ldt = LocalDateTime.now();
//关于DateTimeFormatter的各个格式参数,需要看jdk8的文档.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH小时tmm分钟ss秒");
String strDate = dtf.format(ldt);
Instant 时间戳
import java.time.Instant;
import java.util.Date;
public class Instant_ {
public static void main(String[] args) {
//1.通过 静态方法 now() 获取表示当前时间戳的对象
Instant now = Instant.now();
System.out.println(now);
//2. 通过 from 可以把 Instant 转成 Date
Date date = Date.from(now);
//3. 通过 date的 toInstant() 可以把 date 转成Instant对象
Instant instant = date.toInstant();
}
}
其他方法
LocalDateTime
类MonthDay
类:检查重复事件plus
方法测试增加时间的某个部分minus
方法测试查看一年前和一年后的日期API
即可