【1】什么是包装类:
以前定义变量,经常使用基本数据类型,
对于基本数据类型来说,它就是一个数,加点属性,加点方法,加点构造器,
将基本数据类型对应进行了一个封装,产生了一个新的类,---包装类。
int,byte.....>引用数据类型
包装类---->引用数据类型
【2】对应关系:
基本数据类型 对应的包装类 继承关系
【3】已经有基本数据类型了,为什么要封装为包装类?
1.java语言是面向对象的语言,最擅长操作各种各样的类。
2.以前学习装数据的数组,int[] String[] double[] Student[]
以后学习的装数据的集合,有一个特点,只能装引用数据类型的数据
【4】是不是有了包装类以后就不用基本数据类型了?
不是。
Integer类
【1】直接使用,无需导包:
java.lang
类 Integer
【2】类的继承关系:
java.lang.Object
-java.lang.Number
-java.lang.Integer
【3】实现接口:
所有已实现到的接口:
Selializable,Comparable<Integer>
【4】这个类被final修饰,那么这个类不能有子类,不能继承:
public final class Integer
extends Number
implements Comparable<Integer>
【5】包装类是对基本数据类型的封装:对int类型封装产生了Integer
Integer类在对象中包装了一个基本类型int 的值。Integer类型的对象包含一个int类型的字段。
【6】类的历史:
从一下版本开始:
JDK1.0
【7】属性:
public class test01 {//创建类
public static void main(String[] args) {//主方法
System.out.println(Integer.MAX_VALUE);//输出最大值
System.out.println(Integer.MIN_VALUE);//输出最小值
//物极必反原理:
System.out.println(Integer.MAX_VALUE+1);//输出
System.out.println(Integer.MIN_VALUE-1);//输出
}
}
运行结果:
【8】 构造器(发现没有空参构造器)
1.int类型作为构造器的参数:
Integer i1=new Integer(i2);
public class test02 {//创建类
public static void main(String[] args) {//主方法
Integer i1=new Integer(12);//构造器
System.out.println(i1.toString());//输出信息
Integer i2= new Integer("12");//构造器
System.out.println(i2);//输出
}
}
运行结果:
【9】包装类特有的机制:自动装箱 自动拆箱:
public class Test03 {//创建类
public static void main(String[] args) {//主方法
//自动装箱:int--->Integer
Integer i=12;//定义一个Integer对象并赋值
System.out.println(i);//输出
//自动拆箱:Integer --->int
Integer i2=new Integer(12);//创建构造器并传入值
int num=i2;//定义一个int类型的变量并赋值
System.out.println(num);//输出
}
}
运行结果:
1.自动装箱 自动拆箱是从JDK1.5以后新出的特性
2.自动装箱 自动拆箱:将基本数据类型和包装类进行快速的类型转换。
从属与java.lang包(属于这个包意味着直接使用,不用导入包)【图】
类的继承关系
java.lang.Object
java.lang.Number
java.lang.Integer
实现接口 【图】
被final修饰,那么这个类不能有子类,不能被继承【图】
包装类是对基本数据类型的封装:对int类型封装产生了Integer。【图】
类的历史【图】
字段摘要 Field Summary【图】
构造方法摘要,可以在idea上点进去看
Integer i1 = new Integer(39);//Integer方法构造
Integer i2 = new Integer("abc");//报错,点进构造方法,发现是NumberFormatException
System.out.println(i2);
包装类特有机制,拆箱装箱(底层使用了方法完成,velueOf() 和 intValue() )可以自行断点查看
//自动装箱,int直接变成Integer
Integer i = 3;
//自动拆箱,Interger直接变成int相加
System.out.println(i+1);
常用方法,主要查看JavaAPI文档自学,下面列举主要几个方法,可以在idea点进方法查看底层
-
comperTo() 在数字上比较两个Integer对象。
Integer i = 2; Integer i1 = 3; Integer i2 = 3; System.out.println(i.compareTo(i1));//-1 System.out.println(i1.compareTo(i));//1 System.out.println(i1.compareTo(i2));//0
equals()将对象和指定对象进行比较
Integer i3 = new Integer(13);//通过new创建
Integer i4 = new Integer(13);
System.out.println(i3.equals(i4));//ture,equals被重写
System.out.println(i3 == i4);//false
Integer i5 = 1;//通过自动装箱创建
Integer i6 = 2;
System.out.println(6.equals(i5));//ture,equals被重写
System.out.println(i6 == i5);//ture,当自动装箱的值在-128~127之间自动装箱返回的是数,否则是地址
-
intValue()以 int 类型返回该Integer的值
-
parseInt()将字符串转成 int 类型
-
toString()返回一个表示该Integer的字符串
二、日期相关类
1. util.Date (方法很多自己试,API里有)
-
Date d = new Date(); System.out.println(d); System.out.println(d.toGMTString());//有横线花掉的是过失、过期、废弃方法 System.out.println(d.toLocaleString());
System.out.println(d.getTime()); System.out.println(System.currentTimeMillis());//效果一样,但是用第二个,因为是静态方法,快!第一个因为要创建对象,所以不够第二个效率高 //currentTimeMillis()是本地方法,没有方法体,因为方法体的实现不是通过Java写的 //这俩方法的作用,测试算法速度
2. sql.Date
Date d = new Date(1592055964263L); System.out.println(d); /* 1. 区别 java.util.Date:年月日 时分秒 java.sql.Date:年月日 2. 联系 sql.Date 继承自 util.Date 3. 转换 */ //util-->sql java.util.Date d1 = new Date(1592055964263L); Date d11 = (Date) d1;//方式一,强制转换 util-->sql Date d12 = new Date(d1.getTime());//借助构造器 //sql-->util d1 = d;//父类指向子类 //String --> sql.Date Date d13 = Date.valueOf("2017-7-3");
3. SimpleDateFormat
从前台过来的日期数据一般都是有格式的String,需要转换成util.Date类型
-
String-->sql.Date
-
sql.Date-->util.Date
-
局限性:日期必须是规定格式!
-
引入新类DateFormat
java.sql.Date sdate = java.sql.Date.valueOf("2017-7-7");//String-->sql.Date,字符转只能是YYYY-MM-DD格式 Date ud = sdate;//sql.Date-->util.Date //局限性:日期必须是规定格式! //日期转换 //public class SimpleDateFormat(子类) extends DateFormat(父类) DateFormat df = new SimpleDateFormat("yyyy MM dd");//转化标准已经定好(对标前台) //String ---> Date try {//需要try/catch才能使用 Date d = df.parse("2017 03 07");//parse,根据给定字符串和格式生成日期 System.out.println(d.toLocaleString()); } catch (ParseException e) { e.printStackTrace(); } //Date ---> String String format = df.format(new Date());//根据日期给出格式 System.out.println(format);
4. Calendar
Calendar是一个抽象类,不能直接创建对象,使用子类实现
可以使用静态方法Calendar.getInstance()创建。
常用方法:get(),set()
如何从String转换为Calendar
练习:给出一个日期,打印出那一月正确的日历,且在给定日期标星号,如下图。
答案如下:
package com.xiaowei9s.commonuse.dateclass; import java.sql.Date; import java.util.Calendar; import java.util.Scanner; public class Demo05 { public static void main(String[] args) { //获取日期 System.out.println("请输入日期(格式为YYYY-MM-DD):"); Scanner sc = new Scanner(System.in); String strDate = sc.next(); Date date = Date.valueOf(strDate); Calendar cal = Calendar.getInstance(); cal.setTime(date); //打印信息 int nowday = cal.get(Calendar.DAY_OF_MONTH); System.out.println("日\t一\t二\t三\t四\t五\t六"); for (int i = 0; i < cal.get(Calendar.DAY_OF_MONTH); i++) {//对齐一号是星期几 System.out.print("\t"); } for (int i = 1; i <= cal.getActualMaximum(Calendar.DATE); i++) {//遍历该月 String day = i+""; if(i<=9){ //为了对齐一位数两位数 day = i+" "; } if (i==nowday){ //在指定日期打星号 day = i+""; System.out.print(day+"*"+"\t"); continue; } cal.set(Calendar.DATE,i); if (cal.get(Calendar.DAY_OF_WEEK)==7){ //在换行时换行 System.out.println(day+"\t"); continue; } System.out.print(day+"\t"); //正常日期 } } }
5. jdk1.8新增第三批API LocalDate、LocalTime、LocalDateTime
缺陷:可变性和不可变性不合理(不应该有set方法,不应该可以改日历,一个日历对象仅仅永远只能是一个时间,不可变)
偏移性:getYear(),是从1900开始的,有偏移性
格式化,格式化只能对Date格式化,而不能对Calendar格式化
基于这些缺陷,创造了第三批Api。但是前面两批都有人用1) LocalDate
2) LocalTime
3) LocalDateTime (最常用)
get方法
with方法(不可变体现)
加减方法
toString() (无偏移性体现)
4) Demo
package com.xiaowei9s.commonuse.dateclass; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.temporal.ChronoField; import java.time.temporal.TemporalField; public class Demo06 { public static void main(String[] args) { LocalDate localDate = LocalDate.now();//LocalDate获取当前日期 LocalTime localTime = LocalTime.now();//LocalTime获取当前时间 LocalDateTime localDateTime = LocalDateTime.now();//LocalDateTime获取当前时间日期 System.out.println(localDateTime); System.out.println(localTime); System.out.println(localDate); LocalTime localTime1 = LocalTime.of(13,14);//获取指定时间 LocalDate localDate1 = LocalDate.of(1999,9,3);//获取指定日期 LocalDateTime localDateTime1 = LocalDateTime.of(2021,9,3,15,13,22,33);//获取指定时间日期 System.out.println(localDateTime1); System.out.println(localDate1); System.out.println(localTime1); //下面只讲LocalDateTime //get方法 System.out.println(localDateTime1.get(ChronoField.MONTH_OF_YEAR)); System.out.println(localDateTime1.getYear()); System.out.println(localDateTime1.getMonth()); System.out.println(localDateTime1.getMonthValue()); System.out.println(localDateTime1.getDayOfMonth()); System.out.println(localDateTime1.getDayOfWeek()); System.out.println(localDateTime1.getDayOfYear()); System.out.println(localDateTime1.getHour()); System.out.println(localDateTime1.getMinute()); System.out.println(localDateTime1.getSecond()); //with,不是set LocalDateTime localDateTime2 = localDateTime1.withHour(3);//不可变性,即使把时间变成三点,也不会将本来的时间替换,而是新给出除了时间变成3点的一个对象 System.out.println(localDateTime1); System.out.println(localDateTime2); //加减操作 LocalDateTime localDateTime3 = localDateTime1.plusDays(3); LocalDateTime localDateTime4 = localDateTime1.minusHours(5); System.out.println(localDateTime1); System.out.println(localDateTime3); System.out.println(localDateTime4); } }
6. DateTimeFormatter 自定义格式
用于转换LocalDateTime等与String转换的定义和规范.
方式一:
//方式一:预定义的标准格式 DateTimeFormatter df1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;//df可以帮助转换String和LocalDateTime LocalDateTime localDateTime = LocalDateTime.now(); String str = df1.format(localDateTime); System.out.println(str); TemporalAccessor parse = df1.parse("2021-09-04T11:25:23.5"); System.out.println(parse);
方式二:
//方式二:本地相关的格式 //FormatStyle.FULL //FormatStyle.LONG //FormatStyle.MEDIUM //FormatStyle.SHORT DateTimeFormatter df2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);//df可以帮助转换String和LocalDateTime String str1 = df2.format(localDateTime); System.out.println(str1); TemporalAccessor parse1 = df2.parse("2021-9-4 11:41:50");//格式不对会有异常 System.out.println(parse1);
方式三:
//方式三:自定义格式 DateTimeFormatter df3 = DateTimeFormatter.ofPattern("yyyy MM dd");//df可以帮助转换String和LocalDateTime String str2 = df3.format(localDateTime); System.out.println(str2); TemporalAccessor parse2 = df3.parse("2021 09 04"); System.out.println(parse2);
三、Math类
1. API文档中学习
基本概述
- 字段概述:
- 构造器私有化(不想让任何人实例化出对象)
- Math内部所有的属性和方法都是static,都是静态的,可以通过类名直接调用。
2. 走一遍代码
常用属性
System.out.println(Math.PI);System.out.println(Math.E);
常用方法
System.out.println("随机数:"+Math.random());
System.out.println("绝对值:"+Math.abs(-5.6));
System.out.println("进一:"+Math.ceil(9.1));
System.out.println("舍一:"+Math.floor(9.9));
System.out.println("四舍五入:"+Math.round(9.9));
System.out.println("取最大:"+Math.max(3,9));
System.out.println("取最小:"+Math.min(9,28));
四、Random类
1. 自行在API文档中初步了解Random类
2. 不管是无参数构造Random,还是Math类的random方法,最后底层都是到Random类的有参构造中。
3. Demo
package com.xiaowei9s.commonuse.mathclass;import java.util.Random;public class Demo02 {
public static void main(String[] args) {
System.out.println("Math随机数:"+Math.random());//math中生成随机数:底层还是用了Random类
//Random类学习
//带参数构造的Random
Random random = new Random(1858858L);//只要种子固定,则每次启动都会是同一个随机数开始,只有next后才是不同的随机数,并且几次都是一样
//解决办法:给出每次都不一样的种子
Random random1 = new Random(System.currentTimeMillis());
System.out.println(random.nextInt());
System.out.println(random1.nextInt()); //空参数构造的Random:表面无参,实际底层还是调用带参
Random random2 = new Random();
System.out.println(random2.nextInt(10));
System.out.println(random2.nextDouble());
System.out.println(random2.nextFloat());
}
}
五、String类
API文档中自行先把概述了解(5到10分钟)
1. String类的本质
将字符串起来,就是字符串,是不可变类
所有的字符串都是一个实例化出来的对象,例如"abc","你好世界","helloworld"等。
字符串内容不可变,类比LocalDateTime类的不可变性。
String底层是一个char类型的数组
2. String的常用方法
String()空参构造器,给出一个空的value。
String(String original),将original的value和hash给到正构造的String对象。
String(char value[]),将value数组中的值复制到正构造的String对象的属性value中。
length(),字符串底层数组长度。
isEmpty(),字符串底层数组是否为空。
charAt(int index),字符串中底层数组相对应下标的对应值。
equals(Object object),比较两个字符串是否值相等,已被重写。
compareTo(String anotherString),对比两个字符串,实现了一个Comparable接口,需要重写compareTo方法,已被重写。
剩下的看Demo
package com.xiaowei9s.commonuse.stringclass;
import java.util.Locale;
public class Demo01 {
public static void main(String[] args) {
//通过空参构造器创建对象
String str = new String();
String str1 = new String("this string");
String str2 = new String(new char[]{'3','4','5'});
String str3 = "xiaowei";
System.out.println("str3字符串长度:"+str3.length());
System.out.println("str字符串是否为空:"+str.isEmpty());
System.out.println("str3字符串下标3的对应字符:"+str3.charAt(3));
String s = str3;
System.out.println("str3是否和str2相等:"+str3.equals(str2));//已被重写,不是比较地址而是值
String str4 = "aaab";
String str5 = "bbbababc";
System.out.println("str4和str5对比比较:"+str4.compareTo(str5));
String str6 = "123456789";
System.out.println(str6.substring(3));//456789,123没了,截除前三
System.out.println(str6.substring(3, 6));//456,123 789没了,截除前三,截除6后
System.out.println(str6.concat("777"));//拼接字符串
System.out.println(str6.replace('8','*'));//将第一个字符全部用第二个代替
for (String s1:"1-2-3-4-5-6-7-8-9".split("-")
) {
System.out.println(s1);
}//看到字符即分割
System.out.println(str4.toUpperCase(Locale.ROOT));//转大写
System.out.println(str4.toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT));//转小写
String str7 = " ada a s 123 ";
System.out.println(str7.trim());//去除首尾空格
System.out.println(String.valueOf(2));
System.out.println(String.valueOf('a'));
System.out.println(String.valueOf(3.1415926535));
System.out.println(String.valueOf(true));//将其他类型转换成String类型
}
}
3. String内存分析
String在常量池中放置了一个变量,如果后续有结果相同的变量那就不会在增加一个变量,比如String s = "abc";后续如果再来了一个String s1 = "ab"+"c",常量池中也只会有一个"abc",不会有两个。但是注意使用String(String original)构造的String对象则不同。
String s = "1"+"23";String s1 = "12"+"3";String s2 = "1"+"2"+"3";String s3 = "123";String s4 = "123"+"";System.out.println(s4 == s1);//trueSystem.out.println(s2 == s3);//true
上面的字符串会进行编译优化,合并成完整的字符串,可使用反编译工具查看class文件如下:
使用new 创建String:
String s6 = new String("123");System.out.println(s6 == s4);//false
拼接字符串分析:
String s = "abc";
String b = s + "def";
System.out.println(b);
反汇编,借助反汇编来分析整个底层做的事情:
进行反汇编命令后得到反汇编代码,我们观察:
在观察中知道用了两次append,所以在使用变量a和"def"进行拼接的时候,不会进行编译优化,不会直接变成"abcdef",而是会使用StringBuilder类中的方法进行追加。
4. StringBuilder类
可变字符串类有:StringBuilder类,StringBuffer类
不可变字符串类:String类
疑问:
可变和不可变啥意思啊?
本笔记重点:StringBuilder类。
StringBuilder和StringBuffer类。
1. 在API文档中查看基本概述,和基本方法,和String区别不大
2. 查看父类AbstractStringBuilder
有两个属性,和String底层差不多,也有char value[]数组,有int count属性,用于数组中被使用的长度。
3. 分析构造器与append()
StringBuilder sb = new StringBuilder();//表面是空的构造器,底层对value数组初始化长度为16
StringBuilder sb1 = new StringBuilder(3);//底层对value数组初始化长度为3
StringBuilder sb2 = new StringBuilder("abc");//底层对value数组初始化长度为3
sb2.append("aaa").append("bbbbbb").append("ccccccccc").append("ddddddddddddd");//链式调用 return this
构造器中的StringBuilder(String str)底层调用的是append的方法,我们着重分析append方法。
在使用StringBuilder(String str)时,首先会根据str的长度,在后面加上16,以这个长度构成StringBuilder的value长度,比如str="abc",则StringBuilder的value长度就会使3+16=19 。
在一个StringBuilder的对象中使用append(String str)的时候,父类抽象类AbstractStringBuilder类的底层代码会观察你追加的长度是否已经超过当前StringBuilder对象的value长度。
如果长度没有超过,则直接将str中的char value[]中的值 从开头 复制到 StringBuilder对象中的char value[]最后一个字符后。
如果长度超过了,则会先对StringBuilder中的char value[]进行扩容至充足,过程:创建一个新的足够长度的char value[],并且将原有(还没有追加的)字符串复制到新的char value[]中,然后就将str中的char value[]中的值 从开头 复制到 StringBuilder对象中的char value[]最后一个字符后。
如图:
5. 解释可变和不可变
StringBuilder sb = new StringBuilder();
System.out.println(sb.append("abc") == sb.append("def"));//true
StringBuillder可变,在地址不变的情况下,内容是可变的。
如下图
6. StringBuffer概述
基本方法和StringBuilder基本一样,包括追加和构造基本一样。
synchronized,按下不表,多线程部分重点。
7. String,StringBuilder,StringBuffer的区别与联系
String类是不可变类,即一旦一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,直至这个对象销毁。
StringBuffer类则代表一个字符序列可变的字符串,可以通过append、insert、reverse、setChartAt、setLength等方法改变其内容。一旦生成了最终的字符串,调用toString方法将其转变为String
JDK1.5新增了一个StringBuilder类,与StringBuffer相似,构造方法和方法基本相同。
不同是StringBuffer是线程安全的,而StringBuilder是线程不安全的,所以性能略高。通常情况下,创建一个内容可变的字符串,应该优先考虑使用StringBuilder
StringBuilder:JDK1.5开始效率高线程不安全
StringBuffer:JDK1.0开始效率低瞭线程安全