一、包装类
1.1包装类相应的继承体系
1.2包装类和基本数据类型的相互转换
这里以int和integer为例
package com.wrapper_;
public class Integer01 {
public static void main(String[] args) {
//演示int<-->Integer的装箱和拆箱
}
//jdk5前是手动装箱和拆箱
//手动装箱
int n1 = 100;
Integer integer = new Integer(n1);
Integer integer1 = Integer.valueOf(n1);
//手动拆箱
int i = integer.intValue();
//jdk5以后可以自动装箱和自动拆箱
int n2 = 200;
//自动装箱int -->Integer
Integer integer2 = n2;//底层使用的是Integer.valueOf(n2)
//自动拆箱Integer-->int
int n3 = integer2;//底层使用的还是valueOf
}
package com.wrapper_;
public class WrapperVSString {
public static void main(String[] args) {
//包装类(Integer)->String
Integer i = 100;//自动装箱
//方式1
String str = i+"";
//方式2
String str2 = i.toString();
//方式3
String.valueOf(i);
//String ->包装类(Integer)
//方式1
String str4 = "12345";
Integer i2 =Integer.parseInt(str4);//自动装箱
//方式2
Integer i1 = new Integer(str4);//用构造器
}
}
二、String类
2.1String类的基础概念
当然String还有非常多的构造器==>点击此处<==
2.2String的结构剖析
第八点一定要注意不要带入到String中去思考,只才行字符数组的角度去分析final对其的影响就行
2.3String类创建剖析
jdk7之前常量池在方法去,之后常量池在堆中。差别不大,为了助于理解可以把常量池单独看做一个空间。
方法区是用于存储类信息、常量、静态变量和即时编译器编译后的代码等数据的区域。
为了深入理解String的创建方式例举出以下例子:
解析:对于字符串的equals方法,equals会被重写,它功能会由原来的判断地址是否相等变成判断String的内容是否相等。所以a.eqauls(b)返回的是true。因为“==”是判断a和b指向的地址是否相等,因为a会先在常量池创建一个“abc”再指向它,b在常量池中寻找“abc”,如果b找到了就也指向它没找到就在常量池中创建一片新的地址空间并指向它。显然此处b能找到,因此a==b也是true。
先分析a,a是直接指向常量池中的“hsp”的。再分析b,b是指向堆中的对象value,再由value指向常量池中的“hsp”。a.equals(b)比较的是内容,所以返回true,因为a指向常量池,b指向堆,所以指向的地址肯定不同,因此a==b为false。b.intern返回的的是常量池的地址,因此和a指向的地址相等为true,同理,因为b本身是指向堆的,b指向的地址就与b.intern返回的地址不相同false
p1,p2都是new出来的,因此都会在堆中创建不同的对象,但是这两个对象的内容相等(都指向方法区中的“hspedu”)。equals比较的是内容所以是true,p1.name和p2.name都是指向方法区因此也是true,“hspedu”不是new出来的,因此也是从方法区返回的地址,所以其地址与p1.name相同为true。同理是s1和s2作为对象的引用它们指向的地址是在堆中不同区域(因为它们是两个不同的对象,只是它们最终指向的属性相等)因此s1 ==s2为false
首相,因为是双引号,直接在常量池中开辟空间并由s1直接指向次空间,该空间存储的是“hello”,当传入“haha”时会先在常量池中寻找是否有存在内容也是“haha”的区域(常量池对象),如果有用s1直接引用如果没有,则会新开辟一个空间并用s1指向新的空间,旧的空间会被视为“垃圾”被自动清除。
补充(重要):在前面讲过String是用一个私有的final value数组来存放内容的,如果不带入String,这个value数组是一个地址无法改变但是内容可以改变的字符数组。但是由于String的特性是内容无法改变,因此尽管String有方法能够在底层改变char数组(char本身是可以改变的),那也是通过创建新的String对象来实现的,原本的String对象的内容不可以改变。
对于对象这个概念进行总结:从栈中直接指向的就是对象。比如:String str1= “hello”,这里栈中的引用直接指向了常量池中的存有hello的一块内存区域,那块区域就是常量池对象。同理String str1 = new String("hello"),是现在堆中创建对象,再由对象value数组这个属性指向常量池中存有具体字符的区域。因为栈中的引用直接指向的堆,因此这里的对象就是创建在堆中而不是在常量池中。(大前提这些对象都是在main里面创建的)
编译器不会傻傻的开辟三块空间分别存储hello,helloabc,abc,它会进行优化,它会判断创建的常量池对象是否有引用指向,最终它只会存helloabc因此只创建了一个对象
前面两句话很简单在常量池分别创建了两个对象。(对于第三句话(底层)它会先创建一个StringBuilder sb = StringBuilder(),再执行sb.append(“hello”),下一步它会再一次执行sb.append(“abc”)将abc追加到hello后面,最后通过sb.toString方法返回一个字符串。)上面说了一大堆,其实通过一系列的方法将两个字符串整合(放入常池中)最后通过一个新的对象(该对象在堆中)去指向这个常量池的字符串。因此这题总共创建了三个对象两个在常量对象,一个堆对象。
2.4String的常见方法
常见方法多用就行,要了解常用方法看下这篇文章==>点击此处==<
三、StringBufferl类
StringBuffer类代表可变的字符序列,可以对字符串内容进行增删(就是一个增强版的String)很多方法与String相同,但StringBuffer是可变长度的。
3.1StringBuffer的结构剖析
1.StringBuffer的直接父类是AbstractStringBuilder
2.String实现了Serializable,即StringBuffer的对象可以串行化【可以网络传输】
3.在父类中AbstractStringBuilder有属性char[] value,不是final,该value数组存放字符串内容,引出存放在堆中(String是存放在常来池中)
4.StringBuffer是一个final类不可以被继承
5.因为StringBuffer字符内容是存在cahr[] value,所有在变化(增加/删除)不用每次都更换地址(即创建对象)
3.2String和StringBuffer的区别
3.3StringBuffer转换
package com.StringBuffer;
import java.lang.StringBuffer;
public class StringBuffer02 {
public static void main(String[] args) {
//1.创建一个大小为16的char[],用于存放字符内容
StringBuffer stringBuffer = new StringBuffer();
//2.通过构造器制定char[]大小
StringBuffer stringBuffer1 = new StringBuffer(100);
//3.通过给一个String创建StringBuffer,char[]大小就是字符串长度+16
StringBuffer stringBuffer2 = new StringBuffer("hello");
}
}
package com.StringBuffer;
public class StringAndStringBuffer {
public static void main(String[] args) {
//String ->StringBuffer
String str = "helli tom";
//方式1 使用构造器
//注意:返回的才是StringBuffer对象,对str本身没有影响
StringBuffer stringBuffer = new StringBuffer(str);
//方法2使用append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1.append(str);
//StringBuffer->String
StringBuffer stringBuffer2 = new StringBuffer("SSJ");
//方式1使用StringBuffer提供的toString方法
String s = stringBuffer2.toString();
//方式2使用构造器来搞定
String s1 = new String(stringBuffer2);
}
}
3.4StringBuffer常用方法
直到怎么用就行可以看看这篇文章==>点击此处==<
3.5StringBuffer练习
对于前面半部分分析:对StringBuffer在创建时入关传入的字符串是null,它会在底层字符数组里面赋值null(即value[c++]=‘n’,value[c++]=‘u’,value[c++]=‘l’,value[c++]=‘l’)因此字符串长度是4
对于后半部分分析: 第二个构造器的底层源码如图,它会先调用str.length()计算字符串长度,但是此时的字符串指向null没有长度可言,因此这里会抛出空指针异常
四、StringBuilder
StringBuilder和StringBuffer均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样。具体可以去参考StringBuffer的结构剖析处
4.1StringBuilder结构剖析
StringBuilder和StringBuffer均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样。具体可以去参考StringBuffer的结构剖析处
不难发现StringBuilder和StringBuffer有着一样的类的继承关系,说明他们的特性很多都是一样的,但是StringBuilder多用于单线程,因为它的速度更快 。
4.2String,StringBuffer,StringBuilder的比较
五、Math类
5.1Math方法
具体的用法看下面的文章==>点击此处==<
六、Arrays类
6.1Arrays方法1
package com.Arrays_;
import java.util.Arrays;
import java.util.Comparator;
public class ArraysMethod01 {
public static void main(String[] args) {
//演示遍历数组=============================
Integer[] integers = {1,20,90};
//方法1使用for循环
//方法2Arrays.toString
System.out.println(Arrays.toString(integers));
//演示sort方法===============================
//方法1冒泡排序(太麻烦了)
//方法2使用sort方法,这个方法是直接影响对象ARR本身
//默认排序方法
//Arrays.sort(ARR);//从小到大
//通过方法重载实现定制排序
//1.调用定制排序时传入了两个参数 (1)排序的数组ARR (2)实现Comparator()接口的匿名内部类
//2.定制排序实际上就是由我们自己去设计Comparator接口,从而带入底层实现排序
Integer ARR[] = {1,-1,7,0,89};
Arrays.sort(ARR, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2-i1;//从大到小。从小到大(i1-i2)
//这句话决定了底层代码是那种排序方式
}
});
System.out.println(Arrays.toString(ARR));
//演示binarySearch方法=============================
Integer[] ARR1 = {1,2,90,123,567};
//binarySearch 通过二分搜索法进行查找,要求数组必须排好序
//1.使用binarySearch二叉查找
//2.要求该数组是有序的,如果该数组是无序的则不能使用
//3.如果数组中不存在该元素,则返回return-(low+1)
int index= Arrays.binarySearch(ARR1,90);
System.out.println("index="+index);
int index2= Arrays.binarySearch(ARR1,568);//返回-6 因为该数应该在567又边-(5+1)
System.out.println("index="+index2);
}
}
6.1Arrays方法2
package com.Arrays_;
import java.util.Arrays;
import java.util.List;
public class ArraysMethod02 {
public static void main(String[] args) {
Integer[] ARR = {0,1,2,123,345};
//copyOf数组元素的复制=============================
//1.从ARR数组中拷贝ARR.length个元素到新数组newArr中
//2.如果拷贝的长度>ARR.length就在新数组的后面增加null
//3.如果拷贝长度<0,就会抛出异常NegativeArraySizeException
Integer[] newArr = Arrays.copyOf(ARR,ARR.length);//ARR.length根据自己的要求决定要拷贝多少个数
//ill数组元素的填充==================================
Integer[] num = new Integer[]{9,3,2};
//1.使用99替换所有的元素
Arrays.fill(num,99);
System.out.println(Arrays.toString(num));
//asList 将一组数,转换成List===============================
//1.asList方法会将(2,3,4,5,6,1)数据转成一个List集合
//2.返回asList编译类型List(接口)
//3.asList运行类型java.util.Arrays#ArrayList
List<Integer> asList = Arrays.asList(2,3,4,5,6,1);
System.out.println("asList="+asList);
}
}
七、System类
7.1相关方法
package com.System_;
import java.util.Arrays;
public class System01 {
public static void main(String[] args) {
//exit 退出当前程序============================
System.out.println("ok1");
//System.exit(0);
//1.exit(0)表示程序退出
//2.0表示一个状态,正常的状态
//arraycopy:复制数组元素,比较适合底层调用==============================
//一般使用Arrays.copyOf完成复制数组
//主要搞清楚5个参数的含义
//参数1:源数组
//参数2:从源数组的哪个索引位置开始拷贝
//参数3:目标数组
//参数4:把源数组的数据拷贝到目标数组的哪个索引
//参数4:从源数组拷贝多少个数据到目标数组
int [] src = {1,2,3};
int [] dest = new int[3];
System.arraycopy(src,0,dest,0,3);
System.out.println("dest="+ Arrays.toString(dest));
//currentTimeMillens:返回当前时间距离1970-1-1的毫秒数======================
System.out.println(System.currentTimeMillis());
}
}
八、BigInteger和BigDecimal类
7.1BigInteger
package com.Bignum;
import java.math.BigInteger;
public class Big1 {
public static void main(String[] args) {
//当我们编程中,需要处理很大的整数long不够用===========================
BigInteger bigInteger = new BigInteger("78946020000000000000000000");
BigInteger bigInteger1 = new BigInteger("999");
System.out.println(bigInteger);
//===================================
//对bigInteger进行加减乘除需要使用对应的方法,不能直接使用+、-、*、/;
// 加 add
// 减 subtract
// 乘 multiply
// 除 divide
//现在我们以加法为例
BigInteger ADD = bigInteger.add(bigInteger1);
System.out.println(ADD);
}
}
7.2BigDecimal (高精度)
package com.Bignum;
import java.math.BigDecimal;
public class Big2 {
public static void main(String[] args) {
//当我们需要保存一个精度很高的数时,double不够用============================
BigDecimal bigDecimal = new BigDecimal("19999.111111111111111111111111111111111111111111111111");
BigDecimal bigDecimal1 = new BigDecimal("0.111111111111111");
System.out.println(bigDecimal);
//===========================================
//对bigDecimal进行加减乘除需要使用对应的方法,不能直接使用+、-、*、/;===========================
// 加 add
// 减 subtract
// 乘 multiply
// 除 divide
//现在我们以加法为例
BigDecimal ADD = bigDecimal.add(bigDecimal1);
System.out.println(ADD);
}
}
九、日期类
9.1第一代日期类Date(是java.util包)
注意:
第一句代码返回d1的日期格式是国外的方式,一般需要对其进行转换(使用第四句代码)
第六局话可以把一个格式化的字符串转换成相应的Date
9.2第二代日期类Calendar类(日历)
注:对于小时这一字段的获取,c.get(Calendar.HOUR)是12进制的,我们习惯看24进制的将其改成c.get(Calendar.HOUR_OF_DAY)
Calendar没有提供专门的格式化方式需要程序员自己进行格式化,也就是图片中的最后一句
9.3第三代日期类
package com.Date_;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDate_ {
public static void main(String[] args) {
//第三代日期
LocalDateTime ldt = LocalDateTime.now();//得到更多的信息
System.out.println(ldt);
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();年月日
//只要时间LocalTime.now();时分秒
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH小时mm分ss秒");
String format = dateTimeFormatter.format(ldt);
System.out.println(format);
}
}
这里方法很多,肯定是记不住的,需要用什么就查什么 。