13 - 常用类
13 - 1 包装类
1、八种基本数据类型对应的引用——包装类;
2、通过包装类,就可以调用对应类的方法;
基本数据类型 | 包装类 |
---|---|
Boolean 和 Character的直接父类是 Object | |
boolean | Boolean |
char | Character |
下面6种,直接父类是 Number | |
btye | Btye |
short | Short |
int | Integer |
long | Long |
float | Float* |
double | Double |
13-1-1 包装类和基本数据类型的转换
1、在JDK5前 的手动装箱和手动拆箱
手动装箱
// 装箱 int ---> Integer
int a = 99;
Integer integer01 = new Integer(a);
Integer integer02 = Integer.valueOf(a);
手动拆箱
// 拆箱 Integer ---> int
Integer integer03 = new Integer(66);
int b = Integer.intValue(integer03);
2、JDK5 以后(含JDK5)的自动装箱和自动拆箱
- 自动装箱底层自动调用 valueOf()方法 ,自动拆箱底层调用的是 intValue()方法
自动装箱
int a1 = 36;
//底层是 Integer integer1 = Integer.valueOf(a1)
Integer integer1 = a1;
自动拆箱
Integer integer2 = new Integer(666);
//底层 int a2 = Integer.intValue(integer02);
int a2 = integer2;
测试题目
//输出结果是什么?
Object obj1 = true ? new Integer(1) : new Double(2.0);
System.out.println(obj1); //输出 1.0
/*
注意:
1、三元运算符是一个整体;
2、要注意基本数据类型优先级;
*/
13-1-2 包装类和String类型 的转换
1、Integer类型 ----> String类型
Integer a = 888; //自动装箱
/*
方式1
注意:
1、以 a 为基本数值转成的字符串,对原先 a的类型无影响;
*/
String str1 = a + "";
//方式2
String str2 = a.toString();
//方式3
String str3 = String.valueOf(a);
2、String类型 ----> Integer类型
String str4 = "6688";
//方式1
Integer i1 = Integer.parseInt(str4); //这里用到自动装箱
//方式2
Integer i2 = new Integer(str4); //通过constructor
13-1-3 常用方法
1、方法很多,核心:会查API,要读懂API,松,不建议靠翻译软件去帮助翻译,自己去尽量看英文原档,利用理解,翻译软件除非是有些地方自己真翻译不通再用!!!
13-1-4 经典题目
1、题目1
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); //False
************************************************************
/*
注意:This method will always cache values in the range -128 to 127
老韩给的提示:
1、如果 i 在 -128~127 之间,就从数组中返回;
2、如何 i 不在 -128~127 之间,直接返回 new Integer(i);
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
*/
//
Integer m = 1; //底层 Integer.valueOf(1); 看上面源码
Integer n = 1;//底层 Integer.valueOf(1);
System.out.println(m == n); //T
*************************************************************
//
Integer x = 128;//底层 Integer.valueOf(1);
Integer y = 128;//底层 Integer.valueOf(1);
System.out.println(x == y);//F
2、题目2
Integer i11=127;
int i12=127;
//只有有基本数据类型,判断的是值是否相同
System.out.println(i11==i12); // T
13 - 2 String类
1、String对象 用于保存字符串,即一组字符序列;
2、字符串常量对象 —— 双引号括起的字符序列,如:“hello”
3、字符串的字符用 Unicode 字符编码,一个字符占两字节(不区分字母还是汉字);
4、String类图:
(1)String 实现了 Serializable接口,说明 String 可以串行化,可以在网络传输;
(2)String 实现了 Comparable接口,说明 String对象 可以比较大小;
5、String类 是 final修饰,不能被其他类继承;
6、String 有属性 private final char value[]; 用于存放字符串内容;
- value 是一个 final 类型, 不可以修改:即 value 不能指向新的地址,但是单个字符内容是可以变化;
13-2-1 String创建对象的两种方式
1、直接赋值:String s = “hsp”;
- 先从常量池查看是否有 “hsp” 数据空间,如果有,直接指向;如果没有,则重新创建,然后指向。s 最终指向是常量池的空间地址。
2、constructor: String s2 = new String(“hsp”);
- 先在堆中创建空间,里面有 value属性,指向常量池的 hsp空间;如果常量池没有 “hsp”,重新创建,如果有,直接通过 value指向。最终指向的是堆中的空间地址。
JVM内存分布
13-2-2 String的经典题
1、关于 intern() 方法
- 老韩提示:b.intern() 最终返回的是常量池的地址;
public class Test {
public static void main(String[] args) {
String a = "song";
String b = new String("song");
String c = b.intern();
System.out.println(a.equals(b));
System.out.println(a == b);
/*
intern()方法解读
When the intern method is invoked, if the pool already contains a
string equal to this {@code String} object as determined by
the {@link #equals(Object)} method, then the string from the pool is
returned. Otherwise, this {@code String} object is added to the
pool and a reference to this {@code String} object is returned.
*/
System.out.println(a == b.intern());// true
System.out.println(c.toString());
System.out.println(b == b.intern()); // false
}
}
内存分布图
2、这个题目不难,每次看的时候,建议自己动手画一下内存分布图,加深理解;
public class Practice02 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "hspedu";
Person p2 = new Person();
p2.name = "hspedu";
System.out.println(p1.name.equals(p2.name)); //比较内容 true
System.out.println(p1.name == p2.name); // true
System.out.println(p1.name == "hspedu"); // true
System.out.println("*********************");
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2); //比较对象是否指向同一个对象 false
}
}
class Person{
public String name;
public Person(){}
public Person(String name) {
this.name = name;
}
}
13-2-3 String的特性
1、String是一个 final类,代表不可变的字符序列;
2、字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的;
/*
* The value is used for character storage.
松,留意一下:
1、JDK12 源码里面 String类,用于字符存储的 value数组,改为了 byte类型;
2、JDK8 源码里面 String类,用于字符存储的 value数组,是 char类型;
*/
private final byte[] value;
题目
1、问题:创建了几个对象?
String a = "hello" + "abc";
/*
老韩提示:
1、编译器不是傻子,做了一个优化,判断创建的常量池对象,是否有引用指向;
2、String a = "hello" + "abc"; ---> String a = "helloabc";
答案:创建1个对象;
*/
2、问题:创建了几个对象?画出内存图?
- 创建3个对象
String a = "hello"; //创建 a对象
String b = "abc"; // 创建 b对象
String c = a + b;
/*
老韩提示:
1、底层是 StringBuilder sbd = new StringBuilder();
2、sbd.append(a) ;
// sbd是在堆中,并且append是在原来字符串的基础上追加的;
3、sbd.append(b);
4、String c= sbd.toString();
最后:其实是 c 指向堆中的对象(String) value[] -> 池中 "helloabc"
总结:
1、String d = "an" + "wo"; 常量相加,看得是池;
2、String c = a + b; 变量相加,是在堆中
*/
3、很综合的一个练习题,主要看内存图:
public class Practice05 {
public static void main(String[] args) {
Test1 ex = new Test1();
ex.change(ex.str,ex.ch);
System.out.print(ex.str + " and ");
System.out.println(ex.ch);
//输出: hsp and hava
}
}
class Test1{
String str = new String("hsp");
final char[] ch = {'j','a','v','a'};
public void change(String str,char[] ch){
str = "java";
ch[0] = 'h';
}
}
内存分布图,松,跟着代码看顺序
13-2-4 String类常用方法
1、split方法;
- 在对字符串进行分割时,如果有特殊字符,需要加入 转义符 \ ;
2、compareTo方法;
比较两个字符串的大小,如果前者大,
// 则返回正数,后者大,则返回负数,如果相等,返回 0
// 老韩提示:
// (1) 如果长度相同,并且每个字符也相同,就返回 0
// (2) 如果长度相同或者不相同,但是在进行比较时,可以区分大小
// 就返回 if (c1 != c2) {
// return c1 - c2;
// }
//(3) 如果前面的部分都相同,就返回 str1.len - str2.len
3、format方法;
/*
老韩提示:
1、 %s , %d , %.2f %c 称为占位符
2、 %s 表示后面由 字符串来替换;
3、 %d 是整数来替换
4、%.2f 表示使用小数来替换,替换后,只会保留小数点两位, 并且进行四舍五入的处理
5、 %c 使用 char类型 替换;
*/
4、String类的方法很多,注意:后续用到,查阅API -----> 这里就体现了 English 的重要性咯,松!!!
13-3 StringBuffer
1、java.lang.StringBuffer 代表可变的字符序列,可以对字符串内容进行增删;
2、很多方法与String相同,但是 StringBuffer 是可变长度的;
3、StringBuffer 是一个容器;
StringBuffer类图
4、老韩提示:
(1)StringBuffer 的直接父类是 AbstractStringBuilder;
(2)StringBuffer 实现了 Serializable接口,即 StringBuffer对象可以串行化(对象可以网络传输,可以保存到文件);
(3)在父类 AbstractStringBuilder 中,有属性 char[] value,该 value数组 存放 字符串内容,引用存放在堆中的;
(4)StringBuffer 是一个 final类,不能被继承;
(5)StringBuffer 字符内容是存放在 char[] value 中,因此在变化(增加/删除),不用每次都更换地址(即不是每次创建新对象),所以效率比 String 高;
- 提示:松,不用每次都更换地址(即不是每次创建新对象),也就是当空间不够时,有一个扩容机制发挥作用,这里根据 源码 可以找到根据!!!
13-3-1 String 和 StringBuffer
1、String 保存的是字符串常量(存放在常量池中),里面的值不能更改,每次 String类 的更新实际上就是更改地址,效率较低;
- 注意: private final char[] value;
2、StringBuffer 保存的是字符串变量,里面的值可以更改,每次 StringBuffer 的更新实际上可以更新内容,不用每次更新地址,效率较高。
- 注意:char[] value; 这个存放在堆中
3、StringBuffer 常用的几个构造器
//无参构造器
StringBuffer sb01 = new StringBuffer();
/*
看下面源码:
1、父类 AbstractStringBuilder
AbstractStringBuilder(int capacity) {
if (COMPACT_STRINGS) {
value = new byte[capacity];
coder = LATIN1;
} else {
value = StringUTF16.newBytesFor(capacity);
coder = UTF16;
}
}
2、子类 StringBuffer
public StringBuffer() {
super(16);
}
3、可以看见:创建一个 大小为 16的 char[] value ,用于存放字符内容
*/
=====================================================================
// 通过构造器指定 char[] value 的大小
StringBuffer sb02 = new StringBuffer(100);
/*
看下面源码:
1、父类 AbstractStringBuilder
AbstractStringBuilder(int capacity) {
if (COMPACT_STRINGS) {
value = new byte[capacity];
coder = LATIN1;
} else {
value = StringUTF16.newBytesFor(capacity);
coder = UTF16;
}
}
2、子类 StringBuffer
public StringBuffer(int capacity) {
super(capacity);
}
3、可以看到:可以自己通过构造器指定 char[] value 的大小;
*/
========================================================================
//通过 给一个String 创建 StringBuffer, char[] 大小就是 str.length() + 16
StringBuffer sb03 = new StringBuffer("hello");
/*
看下面源码:
1、父类 AbstractStringBuilder
AbstractStringBuilder(int capacity) {
if (COMPACT_STRINGS) {
value = new byte[capacity];
coder = LATIN1;
} else {
value = StringUTF16.newBytesFor(capacity);
coder = UTF16;
}
}
2、子类 StringBuffer
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
3、可以看到:
(1)先给 String 创建一个 StringBuffer对象,char[] value 的大小是 str.length + 16;
(2)通过 append方法,把 str 给添加上;
*/
13-3-2 String 和 StringBuffer 的转换
松,看提示
- 看源码可能会慢点,但是看源码才是最爽的!!!
1、String ----> StringBuffer
(1)使用 constructor; 注意:返回的才是 StringBuffer对象 ,对传入的字符串本身没有影响;
(2)使用 append方法;
2、StringBuffer —> String
(1)使用 StringBuffer 的 toString方法,返回的是 String;
(2)使用 String 的构造器,实参是 StringBuffer类型;
13-3-3 StringBuffer常用方法
1、append方法 ----> 用于追加 字符串;
2、delete(start,end) ----> 删除 >= start && < end 的字符;(左闭右开)
3、replace(start,end,“xxxx”) ----> 用于替换 指定位置 start ~ end 间的字符; (左闭右开)
4、indexOf(“xxxx”) ----> 查找指定的子串在字符串第一次出现的索引,如果找不到返回-1;
5、s.insert(9,“赵敏”) ------> 在索引为 9 的位置插入 “赵敏”,原来索引为 9;
6、length() -----> 计算字符串长度
练习题1
- 体现——看源码的重要性
public class Exercise01 {
public static void main(String[] args) {
String str = null;
StringBuffer sb = new StringBuffer();
/*
* 提示:
* 1、这里底层调用了 AbstractStringBuilder 的 appendNull方法
* 2、看源码
*private AbstractStringBuilder appendNull() {
ensureCapacityInternal(count + 4);
int count = this.count;
byte[] val = this.value;
if (isLatin1()) {
val[count++] = 'n';
val[count++] = 'u';
val[count++] = 'l';
val[count++] = 'l';
} else {
count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
}
this.count = count;
return this;
}
* */
sb.append(str);
// 注意:这里计算 StringBuffer sb 的长度不是自己从表面分析的:长度为0;
System.out.println(sb.length()); //4
System.out.println(sb); // null
}
}
练习题2
public class Exercise02 {
public static void main(String[] args) {
String str = null;
/*
实际执行到这句话:抛出了 NullPointerException
抛出异常,JVM就中断程序;
这句话 System.out.println(sb01); 就不会执行
*/
StringBuffer sb01 = new StringBuffer(str);
//打印的输出结果是什么?
/*
* 1、从表面分析应该打印:null;
* 2、实际答案是:抛出 NullPointerException
* 3、在传入 Str 时,会调用 构造器 StringBuffer(String str);
* 4、答案看源码:
* public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
*5、super(str.length() + 16); 因为传进去的 str 为 null,
* 因此会 抛出 NullPointerException
*
* */
System.out.println(sb01);
}
}
13-3 StringBuilder
1、一个可变的字符序列。
- StringBuilder 提高一个与 StringBuffer 兼容的API,但不能保证同步(StringBuilder 不是线程安全);
- StringBuilder 被用作 StringBuffer 的一个简易替换,用在字符串缓冲器被单个线程使用的时候。如果可以,建议优先使用 StringBuilder,因为在多数实现中,它比 StringBuffer 要快。
2、在 StringBuilder 上的操作主要看 append方法 和 insert方法,这些方法可重载;
13-3-1 StringBuilder 的基本知识
1、StringBuilder 继承 AbstractStringBuilder;
2、实现了 Serializable接口 ,说明 StringBuilder 对象是可以串行化(对象可以网络传输,可以保存到文件);
3、StringBuilder 是 final 类;
4、StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 char[] value,因此,字符序列是堆中;
5、StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用,效率最高;
13-4 String StringBuffer StringBuilder 的比较
相同点 | 不同点 | |
---|---|---|
String | 不可变字符序列,效率低,但复用率高; | |
StringBuffer | StringBuffer and StringBuilder 非常类似,均代表可变的字符序列,方法也基本一致; | 可变字符序列,效率较高(增删),线程安全(看源码); |
StringBuilder | 可变字符序列,效率最高,线程不安全; |
1、String 的使用说明
//创建一个字符串
String s = "a";
/*
1、实际上原来的 "a"字符串对象 已经丢弃了,现在又产生了一个新字符串 s + "b" (也就是 "ab");
2、如果多次执行这些改变字符串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。
如果这样的操作放在循环中,会极大地影响程序的性能。
结论:
1、对于String类 ,由于多次执行改变字符串内容的操作,导致大量副本字符串存留在内存中,
因此 String类的复用率高;
其实更直接的说明 -----> 在 String类中,存放字符串的是 private final char[] value;
2、但 ----> 如果要对字符串做大量修改,不要使用 String类;
*/
s += "b";
2、String StringBuffer StringBuilder 的效率测试
public class TestEfficiency {
public static void main(String[] args) {
long startTime = 0L;
long endTime = 0L;
//测试 StringBuffer 效率
StringBuffer buffer = new StringBuffer("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) { //StringBuffer 拼接 100,000次
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer 的执行时间:" + (endTime - startTime));
//测试 StringBuilder效率
StringBuilder builder = new StringBuilder("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {//StringBuilder 拼接 100,000次
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder 的执行时间:" + (endTime - startTime));
// 测试String 效率
String text = "";
startTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {//String 拼接 100,000次
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String 的执行时间:" + (endTime - startTime));
}
}
运行结果
13 - 5 String StringBuffer StringBuilder 使用选择
使用原则,老韩提示
1、如果字符串存在大量的修改操作,一般使用 StringBuffer / StringBuilder
2、如果字符串存在大量的修改操作,并在单线程的情况下,推荐:StringBuilder
3、如果字符串存在大量的修改操作,并在多线程的情况下,推荐:StringBuffer
4、如果对字符串很少修改,且被多个对象引用,推荐:String,比如配置信息…
13-6 Math类
1、Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
2、Math类的方法均为 static方法,方法具体使用,自己会查API就是 yyds!!!
-
public final class Math extends Object
-
Math类的构造器是 private修饰,因此 Math不能 创建对象;Math类的方法 均为 static方法,可以通过类名直接调用;
-
松,这也是说明 —— 在自己定义工具类时,便可参考Math类;
13-7 Arrays类
Arrays里包含一系列静态方法,管理或操作数组(如:搜索和排序)
1、toString 返回数组的字符串形式
-
Arrays.toString(arr);
2、sort排序 —— 自然排序和定制排序
定制排序,有点意思
(1)根据老韩提示走一遍如下
-
public class ArraysExercise01 { public static void main(String[] args) { //sort方法 自然排序和定制排序 //1、因为数组是引用类型,所以通过 sort 排序后,会直接影响到实参 arr02; //2、sort 重载的,也可以通过传入一个接口 Comparator 实现定制 //3、调用 定制排序 时,传入两个参数 // (1) 排序的数组 arr // (2) 实现了 Comparator 接口的匿名内部类 , 要求实现 compare //4、源码执行过程 //(1)Arrays.sort(arr02, new Comparator<Integer>(); //(2)最终到 TimSort类的 static <T> void sort(T[] a, int lo, int hi, // Comparator<? super T> c,T[] work, int workBase, int workLen) //(3)当执行到 binarySort(a, lo, hi, lo + initRunLen, c); // 会根据动态绑定机制 c.compare 执行我们传入的匿名内部类 compare() // private static <T> void binarySort(T[] a, int lo, int hi, int start, // Comparator<? super T> c) // while (left < right) { // int mid = (left + right) >>> 1; // if (c.compare(pivot, a[mid]) < 0) // right = mid; // else // left = mid + 1; // } //(4)new Comparator<Integer>() { // @Override // public int compare(Integer o1, Integer o2) { // Integer i1 = (Integer) o1; // Integer i2 = (Integer) o2; // return i1 - i2; // } //5、可以看到 public int compare(Integer o1, Integer o2) 返回的值 >0 / <0 // 会影响整个排序的结果 //6、以上:接口编程 + 动态绑定 + 匿名内部类 综合应用 Integer[] arr02 = {-5,0,89,1,-66}; Arrays.sort(arr02, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { Integer i1 = (Integer) o1; Integer i2 = (Integer) o2; return i1 - i2; } }); System.out.println("====排序以后的数组===="); System.out.println(Arrays.toString(arr02)); } }
定制排序自己实现一遍如下
-
public class ArraysExercise02 { public static void main(String[] args) { int[] arr = {-5,3,0,1,66,88,-1}; arraySort(arr, new Comparator() { @Override public int compare(Object o1, Object o2) { int i1 = (Integer) 01; int i2 = (Integer) o2; return i1 - i2; } }); System.out.println("===数组排序以后的顺序==="); System.out.println(Arrays.toString(arr)); } public static void arraySort(int[] arr, Comparator c) { int temp = 0; // int arrj01; // int arrj02; for (int i = 0; i < arr.length - 1; i++) { for (int j = i; j < arr.length - 1; j++) { // int arrj01 = (Integer) arr[j]; // int arrj02 = (Integer) arr[j+1]; if (c.compare(arr[j], arr[j + 1]) > 0) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } }
-
结果如下:结果有问题,再看时,记得优化
-
这里就出现一个问题,如果一组数里面有两个 负数,
-
(1)用自己写的正常的冒泡来排序,还是用自己手写的定制排序来排序,都会出现排序不对的情况,我现在还优化不了!
-
(2)但是用 Arrays 提供的sort方法,进行排序,结果没有问题;
3、binarySearch —— 通过二分搜索法进行查找,要求必须先排好序;
-
/* 1、要求数组必须为有序数组,若数组是无序的,就不能使用:binarySearch 2、如果数组中没有相应元素,就返回 return -(low + 1); // key not found. */
4、copyOf —— 数组元素的复制
-
老韩提示:
-
/* 1. 从 arr 数组中,拷贝 arr.length 个元素到 newArr 数组中 2. 如果拷贝的长度 > arr.length 就在新数组的后面 增加 null 3. 如果拷贝长度 < 0 就抛出异常 NegativeArraySizeException 4. 该方法的底层使用的是 System.arraycopy() */
5、fill —— 数组元素的填充
- 用一个 num01 去填充数组,也就是 用 num01 去替换原来的元素;
6、equals —— 比较两数组元素是否一致
7、asList —— 将一组值,转为 list;
-
老韩提示:
-
/* 1、asList 方法,会将{1, 2, 3, 4, 5, 6} 数据转换位一个 List 集合; 2、看源码,返回 asList 编译类型是: List<T>接口 public static <T> List<T> asList(T... a) { return new ArrayList<>(a); } 3、运行类型:class java.util.Arrays$ArrayList 这个是 Arrays 的 static内部类,看下面 private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable */ public class ArraysExercise03 { public static void main(String[] args) { Integer[] arr = {1, 2, 3, 4, 5, 6}; List<Integer> integers = Arrays.asList(arr); System.out.println("integerList:" + integers); //integers的编译类型是 List(Integer) 看一下运行类型 System.out.println(integers.getClass()); } }
13 - 8 System类
1、exit方法: 退出当前程序;
/*
1、exit(0) 表示程序退出;
2、0 表示一个状态,正常的状态;
*/
System.exit(0);
2、arrayCopy方法:复制数组元素,比较适合底层调用,一般使用 Arrays.copyOf完成复制数组;
-
public class SystemExercise02 { public static void main(String[] args) { int[] arr1 = {1,2,3}; int[] dest = new int[3]; /* * 老韩提示 ——— 也就是明白这5个参数的意思就OK!!! * @param src the source array. * @param srcPos starting position in the source array. * @param dest the destination array. * @param destPos starting position in the destination data. * @param length the number of array elements to be copied. * */ System.arraycopy(arr1,0,dest,0,arr1.length); System.out.println(Arrays.toString(dest)); } }
3、currentTimeMillens:返回当前时间距离 1970-1-1 的毫秒数;
4、gc:运行垃圾回收机制,System.gc();
13-9 BigInteger and BigDecimal类
1、BigInteger:适合保存比较大的整型;
2、BigDecimal:适合保存精度更高的浮点数(小数);
3、BigInteger and BigDecimal常用方法
(1)add 加
(2)subtract 减;
(3)multiply 乘;
(4)divide 除;
BigInteger练习代码,对四个方法结合源码,有相应说明,要看看
-
public class BigIntegerExercise01 { public static void main(String[] args) { // int i = 99999999999999999999999999999999999999999999111111; /* * 1、看类图:BigInteger 和 BigDecimal 直接父类是 Number ----> Object * 2、构造器是: * public BigInteger(String val) { this(val, 10); } * */ BigInteger bigInteger = new BigInteger("9999999999999999999999999999" + "9999999999999999111111"); BigInteger bigInteger1 = new BigInteger("100000"); /* * add(): 方法有重载,具体返回类型,要看具体调用的方法的源码 * */ // bigInteger = bigInteger.add(bigInteger1); // System.out.println(bigInteger); // System.out.println("**********************"); /* * subtract(): 方法有重载,具体返回类型,要看具体调用的方法的源码 * */ // bigInteger = bigInteger.subtract(bigInteger1); // System.out.println(bigInteger); /* * multiply():方法有重载,具体返回类型,要看具体调用的方法的源码 * */ // bigInteger = bigInteger.multiply(bigInteger1); // System.out.println(bigInteger); /* * Returns a BigInteger whose value is {@code (this / val)} * 注意:得到的结果是去掉了小数部分; * */ bigInteger = bigInteger.divide(bigInteger1); System.out.println(bigInteger); } }
BigDecimal练习代码,主要调用 divide方法,要注意一下
-
public class BigDecimalExercise01 { public static void main(String[] args) { double i = 32.22222225555555555555111111111333333888888888d; System.out.println(i); /* * BigDecimal的 * 1、add() subtract() multiply() * 2、divide()要注意,有时计算可能会抛出异常 * ArithmeticException: Non-terminating decimal expansion; * no exact representable decimal result. * * 3、在调用 divide()方法时,指定精度即可. BigDecimal.ROUND_CEILING * */ BigDecimal bigDecimal = new BigDecimal("444444.4444444444444" + "444444444444444444444444444"); BigDecimal bigDecimal01 = new BigDecimal("2"); System.out.println(bigDecimal.divide(bigDecimal01,BigDecimal.ROUND_CEILING)); } }
13 - 10 日期类
13-10-1 第一代日期类 — Date
1、Date: 精确到毫秒,代表特定的瞬间;
2、SimpleDateFormat:格式化和解析日期的类;
(1)允许进行格式化:日期 ----> 文本;
(2)解析(文本 —> 日期)和规范化;
-
//可以把一个格式化的String 转换为 date //1、String --> Date,SimpleDateFormat定义的格式要与给的String格式相同, // 否则抛出异常:java.text.ParseException
13-10-2 第二代日期类 – Calendar
1、Calendar类 是一个抽象类,它为特定瞬间与一组比如 YEAR MONTH…等日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法;
-
//1、Calendar类 是抽象类; //2、constructor 是private; //3、通过 getInstance()方法获得 Calendar对象; //4、Calendar没有专门的格式化方法,得自己定义;
13-10-3 第三代日期类
1、JDK 1.0 包含了一个 java.util.Date类,但是其大多数方法在 JDK 1.1 引入 Calendar类之后被弃用了。但是 Calendar类也存在些问题:
(1)可变性:如日期和时间这样的类应该是不能变的;
(2)偏移性:Date 中的年份是从 1900年 开始的,月份是从 0 开始的;
(3)格式化:格式化只对 Date有用,而 Calendar则不行;
(4)Date Calendar不是线程安全的,不能处理闰秒(每隔两天,多出1秒)等;
2、LocalDate(日期/年月日),LocalTime(日期/时分秒),LocalDateTime(日期/年月日时分秒)---- JDK8加入
(1)LocalDate(日期/年月日):只包含日期,可以获得日期字段;
-
/* * 1、LocalDate 是 final类; * 2、constructor 是 private修饰; * 3、通过 now()方法 获得日期对象 * 说明:Obtains the current date from the system clock in the default time-zone. * public static LocalDate now() { return now(Clock.systemDefaultZone()); } * */
(2)LocalTime(日期/时分秒):只包含时间,可以获得时间字段;
(3)LocalDateTime(日期/年月日时分秒):包含 日期 + 时间,可以获得 日期和时间 的字段;
-
/* * 1、LocalDateTime 是 final类; * 2、constructor 是 private修饰; * 3、通过 now()方法 获得日期时间对象 * 说明:Obtains the current date-time from the system clock in the default time-zone. * public static LocalDateTime now() { return now(Clock.systemDefaultZone()); } * */
3、DateTimeFormat ----》格式日期类;
-
/* * DateTimeFormatter * 1、是 final类; * 2、constructor 是私有的; * 3、通过 ofPattern()方法 获得 DateTimeFormatter对象 * * public static DateTimeFormatter ofPattern(String pattern) { return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); } * */
4、Instant ----》 时间戳
-
Date 与 Instant 的转换
-
public class InstantExercise01 { public static void main(String[] args) { Instant instant = Instant.now(); System.out.println(instant); //通过 Date类 static from()方法,可以把 Instant 转换为 Date Date from = Date.from(instant); System.out.println(from); //通过 Date 的 toInstant方法 把 date 转为为 Instant对象 Date date = new Date(); Instant instant1 = date.toInstant(); System.out.println(instant1); } }
5、演示的几个方法,其他方法,到时用的时候,自己 查API 就可了;
-
// plus() minus() 对当前时间进行加减