1. 包装类
1.1. 什么是包装类
在开发中,经常用到的基本数据类型不是对象,但在实际应用中需要将基本数据转化成对象,以便于操作。
为了解决这个不足,Java为每个基本数据类型设计了一个对应的类,这样八个和基本数据类型对应的类称为包装类。位于java.lang包中
1.2. 包装类的优点
- 某些方法的参数必须是对象,为了让基本数据类型的数据能作为参数,提供包装类
- 包装类还可提供更多的功能
- 其他重要的功能:比如可以实现字符串和基本数据类型之间的转换
publicclassTestWrapper1{publicstaticvoidmain(String[] args){List list =newArrayList();
list.add(newInteger(56));System.out.println(list);// [56]System.out.println(Integer.SIZE);// 32System.out.println(Integer.MAX_VALUE);// 2147483647System.out.println(Integer.MIN_VALUE);// -2147483648System.out.println(Integer.toBinaryString(123));// 1111011System.out.println(Integer.toOctalString(123));// 173System.out.println(Integer.toHexString(123));// 7bString str ="123";int num =Integer.parseInt(str);System.out.println(num);// 123String str2 ="123.45";double d =Double.parseDouble(str2);System.out.println(d);// 123.45}}
- 注意: - 包装类的对象需要占用栈内存和堆内存,而基本数据类型变量只占用栈内存;基本数据类型变量占用空间少,更简单灵活高效- 作为成员变量,初始值不同,int 0; Integer null- 除了Character和Boolean外,其他都是数字型,数字型都是java.lang.Number的子类
1.3. 使用包装类
1.3.1. 自动装箱和自动拆箱
自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的相互转换
- 自动装箱:基本类型的数据处于需要对象的环境中,会自动转为对象
- 自动拆箱:每当需要一个值时,对象会自动转成基本数据类型,没必要显示调用intValue()、doubleValue()等转型方法
自动装箱过程是通过调用包装类的valueOf()方法实现的,自动拆箱过程是通过调用包装类的xxxValue()方法实现的(如intValue()、doubleValue())
publicclassTestWrapper2{publicstaticvoidmain(String[] args){Integer in =5;Integer in2 =newInteger(5);System.out.println(in == in2);// trueint i = in2;int i2 = in2.intValue();System.out.println(i2);// 5Integer in3 =newInteger(56);Integer in4 =newInteger(56);System.out.println(in3 == in4);// falseSystem.out.println(in3.equals(in4));// trueInteger in5 =25;Integer in6 =25;System.out.println(in5 == in6);// trueSystem.out.println(in5.equals(in6));// trueInteger in7 =256;Integer in8 =256;System.out.println(in7 == in8);// falseSystem.out.println(in7.equals(in8));// true}}
1.3.2. 理解Integer源码
Integer的父类是Number类;底层就是封装了一个int类型的value常量,可以通过构造方法、intValue()等赋值取值
publicclassIntegerextendsNumber{privatefinalint value;publicInteger(int value){this.value = value;}@OverridepublicintintValue(){return value;}}
Integer类提供了一个静态内部类IntegerCache,对于定义一个静态数组cache,长度为256,赋值为-128-127。对于自动装箱,如果是-128-127范围内的数据,直接获取数组的指定值;范围之外的数据,通过new Integer()重新创建对象。
publicclassIntegerextendsNumber{publicstaticclassIntegerCache{staticfinalint low =-128;staticfinalint high;staticfinaljava.lang.Integer cache[];static{int h =127;
high = h;
cache =newjava.lang.Integer[(high - low)+1];int j = low;for(int i =0; i < cache.length; i++){
cache[i]=newjava.lang.Integer(j++);}}}publicstaticjava.lang.IntegervalueOf(int i){if(i >=IntegerCache.low && i <=IntegerCache.high)returnIntegerCache.cache[i +(-IntegerCache.low)];returnnewjava.lang.Integer(i);}}
- 注意: - JDK1.5之后,增加了自动装箱和拆箱功能- 自动装箱调用的是valueOf()方法,而不是new Integer()方法- 自动拆箱调用的是xxxValue()方法- 包装类在自动装箱时为了提高效率,对于-128-127之间的值会进行缓存处理。超过范围,对象之间不能使用==比较,而是使用equals方法
2. String类
字符串相关的类:String类、StringBuilder类、StringBuffer类
- String类:代表不可变的字符序列
- StringBuilder类和StringBuffer类:代表可变字符序列
2.1. String类的使用
publicclassTestString1{publicstaticvoidmain(String[] args){String str ="wyb王一博";System.out.println(str.length());// 6System.out.println(str.isEmpty());// falseSystem.out.println(str.startsWith("w"));// trueSystem.out.println(str.endsWith("b"));// trueSystem.out.println(str.toUpperCase());// WYB王一博System.out.println(str.toLowerCase());// wyb王一博// str = str.toUpperCase();// System.out.println(str); // WYBSystem.out.println(str.charAt(1));// ySystem.out.println(str.substring(3,6));// 王一博System.out.println(str.substring(1));// yb王一博System.out.println(str.indexOf("y"));// 1byte[] bytes = str.getBytes();System.out.println(bytes.length);// 12System.out.println(Arrays.toString(bytes));// [119, 121, 98, -25, -114, -117, -28, -72, -128, -27, -115, -102]String s =newString(bytes,1,2);System.out.println(s);// ybSystem.out.println(str);// wyb王一博boolean flag = str.contains("wyb");System.out.println(flag);// true
str = str.concat("xz").concat("肖战");System.out.println(str);// wyb王一博xz肖战
str = str.replace("wyb","一啵");System.out.println(str);// 一啵王一博xz肖战String s1 =" x z ";System.out.println(s1.length());// 6System.out.println(s1.trim());// x zString str1 ="bjyx";String str2 ="bjyx";System.out.println(str1 == str2);// trueSystem.out.println(str1.equals(str2));// trueString str3 =newString("bjyx");String str4 =newString("bjyx");System.out.println(str3 == str4);// falseSystem.out.println(str3.equals(str4));// trueString str5 ="";String str6 =null;System.out.println(str5.isEmpty());// true// System.out.println(str6.isEmpty()); // Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "str6" is null}}
- 方法 - charAt(int index):返回指定索引处的char值- compareTo(String anotherString):按字典顺序比较两个字符串- concat(String str):将指定字符串连接到此字符串的结尾- contains(CharSequence s):当且仅当此字符串包含指定char序列时,返回true- endsWith(String suffix):是否以指定的后缀结束,返回boolean- startsWith(String prefix):测试此字符串是否以指定前缀开始,返回boolean- startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始,返回boolean- equals(Object anObject):此字符串与指定的对象比较,返回boolean- equalsIgnoreCase(String anotherString):将String与另一个String比较,忽略大小写,返回boolean- hashCode():返回此字符串的哈希码- indexOf(int ch):返回指定字符在此字符串中第一次出现的索引- indexOf(int ch, int fromIndex):返回指定字符在此字符串中第一次出现的索引,从指定的索引开始搜索- indexOf(String str):返回指定子字符串在此字符串中第一次出现的索引- indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现的索引,从指定索引开始- isEmpty():当且仅当length()为0时,返回true- lastIndexOf(int ch):返回指定字符在此字符串中最后一次出现的索引值- lastIndexOf(int ch, int fromIndex):返回指定字符在此字符串中最后一次出现的索引值,从指定索引处开始进行反向搜索- lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现的索引值- length():返回此字符串的长度- replace(char oldChar, char newChar):返回一个新的字符串,它是通过用newChar替换此字符串中出现的所有oldChar得到的- replace(CharSequence target, CharSequence replacement):使用指定的字面了值替换序列替换此字符串所有匹配字面值目标序列的子字符串- replaceAll(String regex, String replacement):使用给定的replacement替换此字符串所有匹配字面值目标序列的子字符串- split(String regex):根据给定正则表达式的匹配拆分字符串- substring(int beginIndex):返回一个新的字符串,它是此字符串的一个子字符串- substring(int beginIndex, int endIndex):返回一个新的字符串,它是此字符串的一个子字符串- toLowerCase():将字符串中所有字符转为小写- toUpperCase():将字符串中所有字符转为大写- toString():返回此对象本身(它已经是一个字符串)- trim():返回字符串的副本,忽略前导空白和尾部空白
2.2. 理解String类源码
- String类是一个final类,意味着该类不能再有子类
- String类底层是一个字符数组value,各种方法的操作其实都是对该数组的操作
publicfinalclassStringimplementsjava.io.Serializable,Comparable,CharSequence{privatefinalchar value[];publicString(){this.value ="".value;}publicString(java.lang.String original){this.value = original.value;}publicbooleanisEmpty(){return value.length ==0;}publicintlength(){return value.length;}publiccharcharAt(int index){if(index <0|| index >= value.length){thrownewStringIndexOutOfBoundsException(index);}return value[index];}publicjava.lang.StringtoString(){returnthis;}}
- String类的equals()方法就是比较底层的字符数组各个元素是否相同,只要发现一个字符不相同,就返回false。如果所有字符都相同,返回true。如果两个变量指向了同一个字符数组,直接返回true
publicbooleanequals(Object anObject){if(this== anObject)returntrue;if(anObject instanceofjava.lang.String){java.lang.String anotherString =(java.lang.String)anObject;int n = value.length;if(n == anotherString.value.length){char v1[]= value;char v2[]= anotherString.value;int i =0;while(n--!=0){if(v1[i]!= v2[i])returnfalse;
i++;}returntrue;}}returnfalse;}
- String类的concat()是创建一个新的字符数组,存放原来字符数组和新加入的字符数组内容,然后以该新数组创建一个新的字符串
publicjava.lang.Stringconcat(java.lang.String str){int otherLen = str.length();if(otherLen ==0)returnthis;int len = value.length;char buf[]=Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);returnnewjava.lang.String(buf,true);}
3. StringBuffer和StringBuilder
StringBuffer和StringBuilder均代表可变的字符序列,这两个类都是抽象类AbstractStringBuilder的子类,方法几乎一样
- StringBuffer是JSK1.0提供的类,线程安全,做线程同步检查,效率较低
- StringBuilder是JDK1.5提供的类,线程不安全,不做线程同步检查,效率较高,建议采用该类
3.1. 使用StringBuilder类
publicclassTestStringBuilder{publicstaticvoidmain(String[] args){StringBuilder builder =newStringBuilder("wyb");
builder.append("xz");System.out.println(builder);// wybxz
builder.insert(3,"bjyx");System.out.println(builder);// wybbjyxxz
builder.setCharAt(3,'B');System.out.println(builder);// wybBjyxxz
builder.replace(3,6,"HHK");System.out.println(builder);// wybHHKxxz
builder.deleteCharAt(6);System.out.println(builder);// wybHHKxz
builder.delete(6, builder.length());System.out.println(builder);// wybHHK
builder.reverse();System.out.println(builder);// KHHbywString string = builder.toString();System.out.println(string);// KHHbyw}}
- 注意:实际开发中StringBuilder的使用场合:字符串的拼接(SQL语句)
- 方法 - append(boolean b):将boolean参数的字符串表示形式追加到序列- capacity():返回当前容量- charAt(int index):返回此序列中指定索引处的char值- delete(int start, int end):移除此序列的子字符串中的字符- deleteCharAt(int index):移除此序列指定位置上的char- ensureCapacity(int minimumCapacity):确保容量至少等于指定的最小值- indexOf(String str):返回第一次出现的指定字符串在该字符串中的索引- indexOf(String str, int fromIndex):从指定的索引处开始,返回第一次出现的指定字符串在该字符串中的索引- lastIndexOf(String str):返回最右边出现的指定字符串在该字符串中的索引- lastIndexOf(String str, int fromIndex):从指定的索引处开始,返回最后一次出现的指定字符串在该字符串中的索引- insert(int offset, boolean b):将boolean参数的字符串表示形式插入此序列中- length():返回长度(字符数)- replace(int start, int end, String str):使用给定String中的字符替换此序列的子字符串中的字符- reverse():将此字符序列用其反转形式取代- substring(int start):返回一个新的String,它包含此字符序列当前所包含字符的子序列- substring(int start, int end):返回一个新的String,它包含此字符序列当前所包含字符的子序列- toString():返回此序列中数据的字符串表示形式
3.2. 理解StringBuilder源码
- StringBuilder类底层和String一样,也是一个字符串数组value,但不是final的。变量count表示的是底层字符数组元素的真实个数,不是底层字符数组的长度
- 默认数组的长度是16。也可以通过构造方法直接指定初始长度。length()方法返回的字符数组元素的真实个数,capacity()返回的是底层数组的长度
publicclassStringBuilderextendsAbstractStringBuilderimplementsAppendable,java.io.Serializable,Comparable,CharSequence{char[] value;int count;publicStringBuilder(){super(16);}publicStringBuilder(int capacity){super(capacity);}publicintlength(){return count;}publicintcapacity(){return value.length;}publicStringtoString(){returnnewString(value,0, count);}}
- 每次添加字符串时要扩容,扩容默认策略是增加到原来长度的2倍+2
publicAbstractStringBuilderappend(String str){if(str ==null){returnappendNull();}int len = str.length();ensureCapacityInternal(count + len);
str.getCharts(0, len, value, count);
count += len;returnthis;}privatevoidensureCapacityInternal(int minimumCapacity){// 如果长度不足,就扩容int oldCapacity = value.length >> coder;if(minimumCapacity - oldCapacity >0){
value =Arrays.copyOf(value,newCapacity(minimumCapacity)<< coder);}}privateintnewCapacity(int minCapacity){int oldLength = value.length;int newLength = minCapacity << coder;int growth = newLength - oldLength;int length =ArraysSupport.newLength(oldLength, growth, oldLength +(2<< coder));if(length ==Integer.MAX_VALUE){thrownewOutOfMemoryError("Required length exceeds implementation limit");}return length >> coder;}
4. 日期类
用long类型表示时间,如果想获得现在时刻的值,可以使用:long now = System.currentTimeMillis();
4.1. Date类
importjava.util.Date;publicclassTestDate{publicstaticvoidmain(String[] args){Date now =newDate();System.out.println(now.toString());// Thu Aug 01 08:40:07 CST 2024System.out.println(now.toLocaleString());// 2024年8月1日 08:40:20System.out.println(now.getYear());// 124 1900+124=2024System.out.println(now.getMonth());// 7 0-11System.out.println(now.getDate());// 1System.out.println(now.getDay());// 4-星期System.out.println(now.getHours());// 8System.out.println(now.getMinutes());// 41System.out.println(now.getSeconds());// 8long l = now.getTime();System.out.println(l);// 1722520811936System.out.println(System.currentTimeMillis());// 1722520811967System.out.println(System.nanoTime());// 1735948366006333Date date1 =newDate(-(long)(1000*60*60*24)*31);System.out.println(date1.toLocaleString());// 1969年12月1日 08:00:00java.sql.Date sDate =newjava.sql.Date(System.currentTimeMillis());System.out.println(sDate);// 2024-08-01java.sql.Date sDate2 =java.sql.Date.valueOf("2024-08-01");System.out.println(sDate2);// 2024-08-01}}
查看API文档可以看到Date类中很多方法都已经过时了。JDK1.1之后,日期操作一般使用Calendar类,而字符串的转化使用DateFormat类
4.2. 理解Date类的源码
publicclassDateimplementsjava.io.Serializable,Cloneable,Comparable<Date>{privatetransientlong fastTime;publicDate(){this(System.currentTimeMillis());}publicDate(long date){
fastTime = date;}publiclonggetTime(){returngetTimeImpl();}publicfinallonggetTimeImpl(){if(cdate !=null&&!cdate.isNormalized()){normalize();}return fastTime;}}
Date类中提供一个成员变量fastTime,表示相应时间对应的毫秒数
4.3. DateFormat类
DateFormat是一个抽象类,一般使用他的子类SimpleDateFormat类来实现。作用是把时间对象转化成指定格式的字符串,反之,把指定格式的字符串转为时间对象
importjava.text.DateFormat;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Date;publicclassTestDateFormat{publicstaticvoidmain(String[] args){// int age = java.lang.Integer.parseInt("123abc");// System.out.println(age); // 报错String str1 ="1999-12-23";java.sql.Date date1 =java.sql.Date.valueOf(str1);System.out.println(date1.toString());// 1999-12-23DateFormat dateFormat =newSimpleDateFormat("yyyy-MM-dd hh:mm:ss");String str ="1999-12-23 09:23:45";Date date =null;try{
date = dateFormat.parse(str);}catch(ParseException e){
e.printStackTrace();}System.out.println(date.toString());// Thu Dec 23 09:23:45 CST 1999System.out.println(date.toLocaleString());// 1999年12月23日 09:23:45DateFormat sdf =newSimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒");// 1999年12月23日 09时23分45秒String str2 = sdf.format(date);System.out.println(str2);}}
4.4. Calendar类
Calendar类是一个抽象类,提供了关于日期计算的功能。GregorianCalendar是Calendar类的一个子类,提供了大多数国家/地区使用的标准日历
importjava.util.Calendar;importjava.util.Date;importjava.util.GregorianCalendar;publicclassTestCalendar{publicstaticvoidmain(String[] args){Calendar cal =newGregorianCalendar();System.out.println(cal.get(Calendar.YEAR));// 2024System.out.println(cal.get(Calendar.MONTH));// 7System.out.println(cal.get(Calendar.DATE));// 1System.out.println(cal.get(Calendar.HOUR));// 10System.out.println(cal.get(Calendar.MINUTE));// 22System.out.println(cal.get(Calendar.SECOND));// 18System.out.println(cal.get(Calendar.DAY_OF_WEEK));// 5
cal.set(Calendar.YEAR,2000);int max = cal.getActualMaximum(Calendar.DATE);System.out.println(max);for(int i =1; i <= max; i++){System.out.println(cal.get(Calendar.DAY_OF_WEEK));// 从 2000 年 8 月 1 日开始,依次打印每一天的星期几,直到 8 月 31 日
cal.add(Calendar.DATE,1);}System.out.println(cal.get(Calendar.DAY_OF_WEEK));// 6System.out.println(cal.getActualMinimum(Calendar.DATE));// 1Date now =newDate();
cal.setTime(now);// Date -> CalendarDate now2 = cal.getTime();// Calendar -> Date}}
4.5. 使用Calendar类实现万年历
importjava.text.DateFormat;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Calendar;importjava.util.Date;importjava.util.GregorianCalendar;importjava.util.Scanner;/**
* 可视化日历 Calendar
* 可以判断这个月一共多少天、某一天是星期几
* 1.实现思路
* 1.按照提示输入任何一个日期
* 2.打印日历
* 1.打印日历头:日 一 二 三 四 五 六
* 2.打印1日之前的空格(循环)
* 3.打印每一天(循环),周六换行
* 2.涉及技能点
* 1.字符串转换成Date:DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse(sdate);
* 2.Date转换成Calendar:cal.setTime(sdate);
* 3.把1999-12-23修改为1999-12-1:cal.set(Calendar.DATE,1);
* 4.判断1999-12-1是星期几:cal.get(Calendar.DAY_OF_WEEK)
* 5.获取当前月的最大天数:cal.getActualMaximum(Calendar.DATE)
* 6.如何判断每天是不是星期六,如果是周六,换行:cal.get(Calendar.DAY_OF_WEEK)==7 cal.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY
* 7.判断是不是当天,如果是,打印*:cal.get(Calendar.DATE) *
* 8.如何日期增加1天:cal.add(Calendar.DATE, 1);
*/publicclassVisualCalendar{publicstaticvoidmain(String[] args){System.out.println("请输入日期(按照格式:2030-3-10):");Scanner scanner =newScanner(System.in);String temp = scanner.nextLine();DateFormat format =newSimpleDateFormat("yyyy-MM-dd");try{// 1. 将字符串转为日期Date date = format.parse(temp);// 2. 将日期转为日历Calendar calendar =newGregorianCalendar();
calendar.setTime(date);// 3. 把日期中的Date取出int day = calendar.get(Calendar.DATE);// 4. 将日历变为当月的1日
calendar.set(Calendar.DATE,1);// 5. 打印日历头信息System.out.println("日\t一\t二\t三\t四\t五\t六");// 6. 打印1日之前的空格(要知道1日是星期几)for(int i =1; i < calendar.get(Calendar.DAY_OF_WEEK); i++){System.out.print("\t");}// 7. 获取当月的最大天数int maxDate = calendar.getActualMaximum(Calendar.DATE);// 8. 打印日历 1-31/28/30for(int i =1; i <= maxDate; i++){// 8.1. 如果是当天,打印*if(i == day){System.out.print("*");}// 8.2. 打印该天System.out.print(i +"\t");// 8.3. 如果是周六,换行int w = calendar.get(Calendar.DAY_OF_WEEK);if(w ==Calendar.SATURDAY){System.out.print("\n");}// 8.4. 日历改为下一天
calendar.add(Calendar.DATE,1);}}catch(ParseException e){
e.printStackTrace();}}}
版权归原作者 Qi妙代码 所有, 如有侵权,请联系我们删除。