文章目录
- 一、Object
- Object中的成员方法(11个)
- toString
- equals
- clone
- 二、Objects
- 三、BigInteger和BigDecima
- BigInteger
- BigDecima
- 四、正则表达式
- 五、Date
- JDK7前时间相关类
- SimpleDateFormat类
- Calendar类
- JDK8新增时间相关类
- 六、包装类
一、Object
没有一个属性是所有类的共性,因此Object类中没有一个成员变量,也就没有带参的构造方法,只有一个空参构造方法.
Object中的成员方法(11个)
toString
一般会重写,打印对象时打印属性
默认情况下,Object类中的toString方法返回的是地址值,所以默认情况下,打印一个对象打印的就是地址值。如果想看到对象内部的属性值,该怎么办?
处理方案:重写父类Object中的toString方法,把对象的属性进行拼接
equals
真正想要比的是对象中的属性值,父类中的方法不能满足当前需求,重写方法
一开始判断当前的调用者this和当前参数中的是不是同一个对象,如果地址值一样,直接return true
否则比较类型是否相等,进行强转,再比较对象内部的属性值
例子:
两个结果都是false;
因为第一个equals方法是String调用的,所以equals要看String类中的
String 类中重写的equals方法:
字符串中的equals方法,先判断参数是否为字符串,如果是字符串,再比较其内部的属性,但是如果不是字符串,直接返回false
第二个equals方法是StringBuilder调用的,所以equals要看StringBuilder类中的
StringBuilder类中没有equals方法,看其父类AbstractStringBuilder中也没有equals方法,所以默认继承Object中的equals方法,再Object当中默认是使用==号比较两个对象的地址值
clone
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制
protected只能被本包或者其他包下的子类访问,重写clone方法
并且需要实现Cloneable接口
该接口中没有任何的抽象方法
如果一个接口中没有抽象方法,表示当前的接口是一个标记性接口,现在Cloneable
一旦实现了,那么当前类的对象就可被克隆,如果没有实现,当前类的对象就不能克隆
实现细节:
方法在底层会帮我们创建一个对象,并把元对象中的数据拷贝过去
1、重写Object类中的clone方法
2、让JavaBean类实现Cloneable接口
3、创建元对象并调用clone就可以了
深克隆:基本数据类型拷贝过来,字符串复用,引用数据类型会重新创建新的
浅克隆:不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来
Object中的克隆是浅克隆
可以重写方法或者利用第三方工具Gson完成深克隆
Gson gson = new Gson();
//把对象转化为json对象
String s = gson.toJson(u1);
//再把字符串变回对象就可以了
User user = gsin.fromJson(s,User.class);
二、Objects
Objects是一个工具类,提供了一些方法去完成一些功能
Objects
的equals方法实现细节:
1、方法的底层会判断参数是否为null,如果为null,直接返回false
2、如果不为null,那么就再次调用equals方法
3、如果此时s是重写过equals方法的JavaBean类型,所以最后还是会调用重写之后的equals方法
如果没有重写,比较的就是地址值,重写了就比较属性值
三、BigInteger和BigDecima
BigInteger
BigInteger的构造方法:
BigInteger中的静态方法 BigInteger bd1 = BigInteger.valueOf(100);
和 BigInteger db2 = new BigInteger("100");
区别:
1、BigInteger.valueOf(100) 能表示的范围比较小,只能在long的取值范围之内,如果超出long的范围就不行了
2、在内部对常用的数字:-16~16进行了优化,提前把 -16~16 先创建好BigInteger的对象,如果多次获取不会重新创建新的
底层源码:
存放 -16 – -1 和1 --16的两个数组以及单独数字0
BigInteger的构造方法小结:
- 如果BigInteger表示的数字没有超出long的范围,可以用静态方法获取
- 如果BigInteger表示的数字超出long的范围,可以用构造方法获取
- 对象一旦创建,BigInteger内部记录的值不能发生改变
- 只要进行计算都会产生一个新的BigInteger对象
BigInteger的成员方法:
BigDecima
可以表示较大的小数和解决小数运算精度失真问题
运行结果:
计算机中的小数:浮点数运算的时候会有精度丢失的风险这个和计算机保存浮点数的机制有很大关系。计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。这也就是解释了为什么浮点数没有办法用二进制精确表示。
BigDecimal 可以实现对浮点数的运算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal 来做的。
1、通过传递double类型的小数来创建对象
BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal(0.09);
System.out.println(bd1);
System.out.println(bd2);
这种方式有可能是不精确的,所以不建议使用
2、通过传递字符串表示的小数来创建对象
BigDecimal bd1 = new BigDecimal("0.01");
BigDecimal bd2 = new BigDecimal("0.09");
System.out.println(bd1);
System.out.println(bd2);
这种方法可以获取到精确的小数
3、通过静态方法获取对象
BigDecimal bd3 = BigDecimal.valueOf(10);
System.out.println(bd3);
底层源码:
第二种和第三种方式的细节:
1、如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
2、如果要表示的数字比较大,超出了double的取值范围,建议使用构造方法
3、静态方法中,如果我们传递的是0-10之间的整数,包含10 包含0,那么方法会返回已经创建好的对象,不会重新new。
BigDecimal的成员方法:
四、正则表达式
作用:
1、校验字符串是否满足规则
2、在一段文本中查找满足要求的内容
通过正则表达式进行文本爬虫:
//1、获取正则表达式的对象
Pattern p = Pattern.compile("Java\\d{0,2}");
//2、获取文本匹配器对象
//拿着m去读取str 找符合p规则的子串
Matcher m = p.matcher(str);
//3、利用循环获取
while(m.find()){
String s = m.group();
System.out.println(s);
}
五、Date
世界标准时间:格林威治时间,简称GMT
目前时间标准时间已经替换为:原子钟
Date类是一个JDK写好的JavaBean类,用来描述时间,精确到毫秒
利用空参构造创建的对象,默认表示系统当前时间
利用有参构造创建的对象,表示指定的时间
JDK7前时间相关类
SimpleDateFormat类
格式化:把时间变成我们喜欢的格式
解析:把字符串表示的时间变成Date对象
构造方法
成员方法
//利用空参构造创建SimpleDateFormat对象 默认格式
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = new Date();
sdf.format(d);
//利用带参构造创建SimpleDateFormat对象 指定格式
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1 = new Date();
sdf1.format(d1);
Calendar类
Calendar代表了系统当前时间的日历对象,可以单独修改,获取时间中的年、月、日
Calendar是一个抽象类,不能直接创建对象,通过getInstance
方法获取对象
//1、获取日历对象 通过一个静态方法获取到子类对象
//细节1:Calendar是一个抽象类,不能直接new
//底层原理:会根据系统的不同时区来获取不同的日历对象,默认表示当前时间,
//会把时间中的纪元,年,月,日,时,分,秒,星期,等放在一个数组当中
// 0:纪元 1:年 2:月 3:一年中的第几周 4:一个月中的第几周 5:一个月中的第几天
//细节2:
//月份:范围0~11 如果获取出来的是0 那么实际上是1月
//星期:在外国人眼里,星期日是一周中的第一天
//1(星期日) 2(星期一) 3(星期二)……
Calendar c = Calendar.getInstance();
//2、修改日历代表的时间
Date d = new Date();
c.setTime(d);
//获取日期中的某个字段信息
//java在Calendar中 ,把索引对应的数字都定义成常量
int year = c.get(1);
int year1 = c.get(Calendar.YEAR);
int month = c.get(2)+1;
int month1 = c.get(Calendar.MONTH)+1;
int day= c.get(5);
int day1 = c.get(Calendar.DAY_OF_MONTH);
int week = c.get(Calendar.DAY_OF_WEEK);
c.set(Calendar.YEAR,2000);
c.set(Calendar.MONTH,11);//实际上是12月
//调用方法在这个基础上增加一个月
c.add(Calendar.MONTH,1);
//调用方法在这个基础上减一个月
c.add(Calendar.MONTH,-1);
总结:
1、如何获取对象?
通过getInstance
方法来获取对象
2、常见方法:
setXxx
:修改
getXxx
:获取
add
:在原有的基础上进行增加或减少
3、细节点:
日历类中的月份范围:0~11
日历类中星期的特点:星期日是一周中的第一天
JDK8新增时间相关类
//1、获取所有的时区名称
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
//2、获取当前系统的默认时区
ZoneId zoneId = ZoneId.systemDefault();
//3、获取指定时区
ZoneId zoneId1 = ZoneId.of("Asia/Pontianak");
Instant时间戳常用的方法
ZoneDateTime时间戳常用的方法
DateTimeFormatter 用于时间的格式化和解析
LocalDate、LocalTime、LocalDateTime
工具类
例题1:
用JDK7和JDK8计算当前活了多少天
JDK7
//JDK7:
//规则:只要对时间进行计算或者判断,都需要先获取当前时间的毫秒值
//1、计算出生年月日的毫秒值
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String birth = "1999-10-04";
long birthTime = sdf.parse(birth).getTime();
//2、获取当前时间的毫秒值
Date today = new Date();
long todayTime = today.getTime();
//3、计算间隔
long day = (todayTime-birthTime)/1000/60/60/24;
System.out.println(day);
}
JDK8
public static void main(String[] args) throws ParseException {
LocalDate birth = LocalDate.of(1999,10,4);
LocalDate today = LocalDate.now();
long days = ChronoUnit.DAYS.between(birth, today);
System.out.println(days);
}
例题2:
用JDK7和JDK8判断任意的一个年份是闰年还是平年
二月有29天是闰年,一年有366天是闰年
JDK7
public static void main(String[] args) throws ParseException {
//可以把时间设置为3月1日
Calendar c = Calendar.getInstance();
c.set(2023,2,1);
//再把日历往前减一天
c.add(Calendar.DAY_OF_MONTH,-1);
//看看当前时间是28号还是29号
int day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
//判断day是28还是29
}
JDK8
public static void main(String[] args) throws ParseException {
LocalDate ld = LocalDate.of(2023, 3, 1);
LocalDate localDate = ld.minusDays(1);
System.out.println(localDate.getDayOfMonth());
}
JDK8中自带方法判断
isLeapYear();
public static void main(String[] args) throws ParseException {
LocalDate ld = LocalDate.of(2023, 3, 1);
boolean leapYear = ld.isLeapYear();
System.out.println(leapYear);
}
六、包装类
包装类:用一个对象,把基本数据类型给包起来
基本数据类型对应的引用类型
为什么要设置包装类?
1、在集合当中只能存引用数据类型,不能存基本数据类型
2、参数如果是Object类型,那么基本数据类型就传不进去
JDK5之前
//通过构造方法获取Integer对象
Integer i1 = new Integer(1);
//通过静态方法获取Integer对象
Integer i2 = Integer.valueOf(123);
这两种方式获取对象的区别
运行结果
JDK5之后提出了自动装箱和自动拆箱
自动装箱:把基本数据类型会自动变成其对应的包装类
自动拆箱:把包装类自动的变成其对象的基本数据类型
//在底层,此时还会去自动调用静态方法valueOf得到一个Integer对象,只不过这个动作不需要我们自己去操作了
Integer i1 = 10;
Integer i2 = Integer.valueOf(10);
//自动拆箱的动作
int i = i2;
在JDK5之后,int和Integer可以看作是同一个东西,因为在内部可以自动转化
Integer中的成员方法
细节:
- 细节一:在类型转换的时候,括号中的参数只能是数字不能是其他,否则代码会报错
- 细节二:8中包装类当中,除了Character都有对应的parseXxx的方法,进行类型转换