目录
4. String、StringBuffer、StringBuffer小结和使用场景【掌握】
6. 数学相关类Math/BigInteger/BigDecimal
7. System/Runtime/Java中的垃圾回收机制
1.前言
这一篇基本上重点讲解的是String类,而他也是Java里面最重要的一个类之一。
2.日期(时间)相关类
2.1 日期类的应用场景
日期类在我们实际开发中,经常用到例如,实际软件的如下场景中
- 淘宝订单
- 聊天记录
- VIP有效期间
- 售票
- 可以利用每一条订单时间来统计查询: 这个月花了多少钱
2.1.1Java中的日期相关的几个类
- Date
- 本类表示时间(日期)new一个对象表示一个具体的时间:根据系统获得时间值
- 构造方法:
Date(); 就表示当前系统时间对象
Date(long date) 根据指定的毫秒值创建一个指定的时间
- 问题: 直接打印Date对象 :Sat Apr 01 15:28:03 GMT+08:00 2017
看起来不直观
- 希望根据不同地区的用户显示不同的效果:
2017-04-01
2017/04/01
2017年04月01日
...
请看下面的第二个点
- DateFormat SimpleDateFormat
- 作用一: 把一个Date对象可以转成我们希望的一个结果样式(字符串)
- 作用二: 也可以把一个字符串解析为一个Date对象
- 学习重点就是如何调用上面的提到的两个功能方法,注意怎么给他格式
Calendar 日历中的一些方法使用
- int get(int field) 方法 : 通过指定的字段获得对应的值 -> 获得当前的年月日...
- set(int field,int value) : 给指定的字段设置值,注意把新值覆盖之前的这个字段值,会自动的进位
- add(int field,int amount) : 这个方法和set差不多,但是把amount的值累加到当前设置的字段原有的值之上
- setTime(Date d) 可以直接把一个Date设置进去
- Date getTime() 可以获得日历对象中的当前日期对象
- 其它方法参考文档
- 补充 Calendar对象的获得
- 是一个抽象类 : 抽象类可以创建它的对象吗? 不能!
- 获得对象: Calendar cal2 = Calendar.getInstance()
- 奇怪现象?
Calendar内部的getInstance 中怎么搞到这个对象的呢?
其实内部创建的是一个Calendar的子类对象
3. Java中的常用类学习方式
3.1 什么是常用类?为什么要学习?
实际开发中我们需要设计大量的类,而有一些JDK已经帮我们程序员设计好了,可以大大的节省我们设计类的时间,提高开发效率。这些经常使用到的JDK类,就是Java的常用类。
3.2 怎么使用Java中的常用类?【掌握】
要使用Java中类,无非也就是使用类中的成员,包括:实例变量、类变量、实例方法、类方法、构造方法等。
- 实例变量
需要通过对象调用,所以,先通过new类名(...) 调用构造方法创建对象,然后通过创建好的对象调用实例变量。例如:
调用User类中的name实例变量
2类变量
直接通过:类名.类变量 调用。例如:调用Integer类中MAX_VALUE常量
3.实例方法
需要通过对象调用,所以,先通过new类名(...) 调用构造方法创建对象,然后通过创建好的对象调用实例方法。例如:
调用String类中的charAt(int index)方法
4.类方法
直接通过:类名.类方法 调用。例如:调用Integer类中static方法:int max(int a, int b);
5.构造方法
直接new类名(...) 调用构造方法创建对象
3.3 注意
这么多的类,每一个类中又有很多的方法,记不住怎么办呢?
只要掌握了调用方式即可。即,知道常用的方法、成员变量在哪个类中,并且会使用API和百度查询到就可以,不要求记住方法名,随着后面接触和做项目使用越来越多就会自然记得住常用的方法了。
3.4 小结
只要掌握了实例变量、类变量、实例方法、类方法、构造方法等调用方式即可。
字符串相关类【重点】
4. String类
4. 1什么是字符串
字符串我们已经简单认识过了:""双引号中的数据就是字符串String类型的常量。
它在Java中不属于基本数据类型, 而是引用类型,也称为类类型。
4.2 为什么我们要学习字符串相关的类?
字符串处理在编程中应用非常广泛,例如,大家用到的交友软件注册、登录等这些数据本质都是字符串,所以字符串在实际开发中非常重要,使用场景非常广泛,所以需要对其常用方法必须掌握。底层原理要了解。
4.3 学习字符串类的哪些东西?
1. 学习字符串类String、StringBuilder、StringBuffer的底层原理,进而掌握使用场景。
2. 学习字符串类String、StringBuilder、StringBuffer类的常用方法
4.4 使用字符串类
1. String类
Java中使用String这个类描述字符串这种常量数据。
API中对java.lang.String类的描述:
通过api的查阅,知道String类在java.lang包中。
只要使用双引号引用起来的数据都是一个String对象。
String类中所有字符串常量,一旦书写完成,它就是一个固定值,这个数据不能改变。
注意:字符串常量,它属于对象,但是它不是存储在堆空间中,而是存储在堆中的字符串常量池中。
字符串常量池中保存的就是所有的字符串数据。只要我们书写了双引号,不管双引号中间是什么数据,
这些数据都会立刻在字符串常量池中保存,并且一直存在,不会被改变。
1. String代码解读
String str1 = null;// 表示str1没有引用地址
String str2 = "";// 表示str2对象引用了在常量池中创建了一个空字符串常量
String str3 = new String();// 表示str3对象引用了在堆中创建了一个空字符串常量
2. 字符串常量池
-
- 当第一次使用String str = "A"; 的方式赋值,会将该字符串值【对象】放入到常量池
- 当再次使用String str = "A"; 的方式会先检查常量池是否有"A"值,
① 如果存在直接引用
② 如果不存在,会创建"A"放入常量池
字符串拼接:
① 常量方式拼接,并直接使用赋值符号赋值,会检查常量池
② 变量方式拼接,不会检查常量池
String s1 = "A"+"BC";// 使用常量拼接,会检查常量区是否有拼接好的"ABC",如果有不会创建
String str = "A";
String s2 = str + "BC";// 使用变量拼接,不会检查常量区,而直在常量池接创建对象
注意:常量池的使用是为了提高程序执行效率,因为在Java中字符串常量使用非常频繁,所以,为了节省创建字符串对象的时间,使用了常量。其实,常量对于我们开发没有影响,我们只关心代码的执行效果。
3.String类常用方法:【重点】
// 常用方法:
// 1.char charAt(int index) 返回 char指定索引处的字符。 不能超过下标范围
str = "我qunianmailegebiao";
char charAt = str.charAt(3);
System.out.println(charAt);
// 2.String concat(String str) 将指定的字符串连接到该字符串的末尾。 相当于:+
String concat = str.concat("大宝剑");
System.out.println("concat:" + concat);
System.out.println("str : " + str);
/*
* 3.boolean contains(CharSequence s) 判断当前对象是否包含连续的参数s。s可以是以下三个子类的对象
* CharSequence接口,包含下面子类:String、StringBuffer、StringBuilder
*/
str = "abcdefg";
boolean contains = str.contains("abc");//判断当前对象str是否包含连续的参数abc
System.out.println("是否包含:" + contains);
// 4.boolean endsWith(String suffix) 判断当前字符串是否以指定的后缀suffix结尾。(参数必须连续)
// 5.boolean startsWith(String prefix) 判断当前字符串是否以指定的前缀prefix开头。 (参数必须连续)
str = "黄某源和苍苍老师速8.avi";
boolean endsWith = str.endsWith(".avi");
System.out.println(endsWith);
/*
* 8.void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
* srcBegin:字符串开始下标
* srcEnd:字符串结束下标(不包含)
* dstBegin:数组dst的下标
* 将此字符串中的字符复制到目标字符数组dst中。 (含头不含尾)[srcBegin,srcEnd)
*/
str = "abceeeabcdefg";
char[] dst = new char[5];
str.getChars(2, 6, dst, 1);// 将字符串str中下标2开始到6结束【不包含6】的字符复制到数组dst中,从数组的下标1开始粘贴
System.out.println(Arrays.toString(dst));
// 9.int indexOf(String s) 返回s第一次在当前对象str中出现的索引 ,-1表示没有找到(注意:这里s必须也是匹配连续的字符串)
int indexOf = str.indexOf("abc");
System.out.println("下标:" + indexOf);
// 10.int indexOf(String s, int fromIndex) 返回s在当前对象指定下标fromIndex后第一次出现的索引 (str是作为一个整体匹配下标的)
int indexOf2 = str.indexOf("abc",4);
System.out.println("下标:" + indexOf2);
// 11.int lastIndexOf(String str) 返回指定子字符串最后一次出现的字符串中的索引。
// 12.int lastIndexOf(String str, int fromIndex) 返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向前搜索。
// 13.boolean isEmpty() 当 length()为 0时,返回 true 。
// 14.int length() 返回此字符串的长度。
// 15.boolean matches(String regex) 判断当前字符串对象是否匹配给定的正则表达式regex,通常用来进行权限限制,字符格式限制 一般用了做校验:如,用户名和密码的合法性
str = "abc";
String regex = "^[a-zA-Z]+$";// 匹配a-z或者A-Z之间任意多个字符
boolean matches = str.matches(regex);// 判断str是否满足a-z或者A-Z之间任意一个字符的要求
System.out.println("是否满足:" + matches);
/*
* 16.String replace(CharSequence target, CharSequence replacement) 将当前字符串中的target替换为replacement,通常用来和谐用语
* 父接口:CharSequence
* 该接口的实现类:String、StringBuffer、StringBuilder
*/
str = "WQNMLGB,你个DSB,我CNM";// WQNMLGB/DSB/CNM:和谐用语
String replace = str.replace("WQNMLGB", "*******");// *******,你个DSB,我CNM
System.out.println(replace);
String replace2 = replace.replace("DSB", "***");// *******,你个***,我CNM
System.out.println(replace2);
String replace3 = replace2.replace("CNM", "***");// *******,你个***,我CNM
System.out.println(replace3);
/**
* replace()和replaceAll(),replaceFirst()区别
* replace()只能匹配String、StringBuffer、StringBuilder对象
* replaceAll()和replaceFirst()可以匹配正则表达式,更灵活
* 如:
*/
// 17.String replaceAll(String regex, String replacement) regex是正则表达式,将当前字符串中的regex全部替换为replacement
str = "abc.efdg";
// regex = "\\.";// 正则表达式中的.表示匹配任意一个字符
// regex = "\\.";// 正则表达式中的\\.表示匹配一个.
regex = "a";// 表示匹配一个a
String replaceAll = str.replaceAll(regex, "#");
System.out.println("replaceAll=====》: " + replaceAll);
// 18.String replaceFirst(String regex, String replacement) 将当前字符串中的第一个regex替换为replacement
// 19.String[] split(String regex) 将当前字符串对象按照给定的正则表达式regex分割为String[]
str = "172.168.11.65;192.168.11.66;172.168.11.69;169.168.11.169;";
// 请将当前str中所有的ip地址打印出来
String[] split = str.split(";");
for (String s : split) {
System.out.println(s);
}
// 20.CharSequence subSequence(int beginIndex, int endIndex) 从当前字符串中beginIndex和endIndex之间截取子串(含头不含尾)
str = "12345678";
CharSequence subSequence = str.subSequence(1, 6);
System.out.println(subSequence);
// 21.String substring(int beginIndex) 从当前字符串中截取beginIndex到最后的子串
// 22.String substring(int beginIndex, int endIndex) 从当前字符串中beginIndex和endIndex之间截取子串(含头不含尾)
str = "172.168.11.65;192.168.11.66;172.168.11.69;169.168.11.169;";
// 请将字符串中ip是172开头的 最后一段打印出来
/*
* 思路:
* 1. 将字符串str先进行按照;分割
* 2. 遍历字符串数组,判断字符串以172开头的
* 3. 在以172的字符串中,再截取最后一个.后面的字符,打印
*/
String[] split2 = str.split(";");
// 遍历数组
for (String s : split2) {
System.err.println("s=========>" + s);
// 判断字符串以172开头的
if (s.startsWith("172")) {
System.err.println("172----:" + s);
// 先找出最后一个.的下标,int lastIndexOf(String str)
int index = s.lastIndexOf(".");
// 从最后一个点截取剩余字符串 :String substring(int beginIndex)
String substring = s.substring(index + 1);//+1是为了将字符串中的.去掉
System.err.println(substring);
}
}
// 23.char[] toCharArray() 将此字符串转换为新的字符数组。 方便遍历当前所有的字符
str = "abcdef";
char[] charArray = str.toCharArray();
for (char d : charArray) {
System.out.println(d);
}
// 24.String toUpperCase() 将此字符转换为全大写 一般用于验证码
// 25.String toLowerCase() 将此字符转换为全小写 一般用于验证码
String upperCase = str.toUpperCase();
System.out.println(upperCase);
// 26.String trim() 将当前字符串对象中字符前面和后面的空格去除 用了避免用户的一些不当输入
str = " asdlkjfal jfdaklfj dsalkj ";
String trim = str.trim();
System.out.println(trim);
// 27.static String valueOf(Object obj) 将其他类型转换为String对象
String valueOf = String.valueOf(1);// 这里其实是1的包装类Integer
System.out.println(valueOf);
4.String小结【掌握】
1. String 字符串类,底层是基于char[]常量, 一旦创建长度就固定不变了,适用于字符串不经常增删改的操作的场景。父接口:CharSequence,该接口的实现类:String、StringBuffer、StringBuilder。
2. 将其他类型转换为String类型不同方式效率对比:【掌握】
toString() > String.valueOf(Object obj) > +
因为+号,底层先将字符串对象转换为StringBuilder对象,然后调用StringBuilder对象的append追加字符串方法,再调用toString方法,转换为String对象
- 使用场景:String类适用于字符串不经常增删改的操作的场景。【掌握】
5. StringBuilder类【掌握】
1. StringBuilder概述:
StringBuilder基于可变的char[],默认长度是16个,适用于频繁操作(增删改插)字符串的场景,该类是线程不安全的。
StringBuilder:
- 是一个字符串缓冲区,其实就是一个容器;
- 长度是可变的,任意类型都可以。注意:是将任意数据都转成字符串进行存储;
- 容器对象提供很多对容器中的数据操作的功能,比如添加,删除,修改,查询;
- 所有的数据最终都会变成一个字符串;
和数组最大的不同就是数组存储完可以单独操作每一个元素,每一个元素都是独立的。
字符串缓存区,所有存储的元素都会被转成字符串,而且变成了一个更长的字符串。
2. StringBuilder类的常用方法【掌握】
1. 构造方法:
说明:
1.1 对于StringBuilder()构造方法,其初始容量为16个字符表示,如果存在StringBuilder的数据超过了16个字符,这个容器可以自动扩容(容器空间自动变大)。(经常使用)
解释:StringBuilder底层体现就是一个字符数组,StringBuilder类的对象将数组封装起来,然后对外提供很多便捷方法,而数组本身是没有什么太多方法的。如果外界将数据存放到底层的数组中,如果底层数组空间存放不下外界传递过来的值,那么jvm会基于原来存在的数组在创建一个新的数组,长度是原来数组的一倍,然后jvm将原来数组的数据全部复制(遍历数组,将数据添加到新的数组中)到新的数组中,然后在数组后面的空间中给数组添加新的值,如果还是存不下在创建一个新的数组。
1.2 对于StringBuilder(int capacity)构造函数来说,capacity表示容器的容量,如果在开发中想自己设置缓冲区大小,可以通过此构造函数来实现;
任何容器:它都围绕容器中的数据的 增 删 改 查 而设计的方法。
/*
* 构造方法:
* 1.StringBuilder() 构造一个没有字符的字符串构建器,初始容量为16个字符。
2.StringBuilder(CharSequence seq) 构造一个包含与指定的相同字符的字符串构建器 CharSequence 。
3.StringBuilder(int capacity) 构造一个没有字符的字符串构建器,
由 capacity参数指定的初始容量。 指定长度capacity可以节省了数组扩容时间
4.StringBuilder(String str)构造一个初始化为指定字符串内容的字符串构建器。
*
*/
StringBuilder sb = new StringBuilder();// 创建一个默认16个长度的char[]数组
StringBuilder sb2 = new StringBuilder("abc");// 创建一个19个长度的char[]数组
2.成员方法:
/*
* 常用方法:
* 1. StringBuilder append(Object obj) 在队尾添加字符串
* 2. StringBuilder delete(int start, int end) 删除指定起始和结束位置之间的字符(含头不含尾)
* 3. StringBuilder deleteCharAt(int index) 删除指定下标处的字符
* 4. StringBuilder insert(int offset, Object obj) 在指定下标处插入一个任意类型数据
* 5. StringBuilder reverse()将字符串翻转
* 6. void setCharAt(int index, char ch) 修改指定下标处的字符为ch
7. void setLength(int newLength) 设置字符串长度是newLength
8. trimToSize() 将所有没有使用的数组空间去除 。 如果使用setLength,该方法无效
* 9. int capacity() 返回当前容量。(理论值)
10.public int length()返回长度(实际值,即已经存储的字符个数)
*/
// append方法
sb.append(true).append("abc");// 因为append方法返回值类型是StringBuilder,所以可以接着调用方法
System.out.println("sb = " + sb);// trueabc
// delete方法
sb.delete(0, 3);// 含头不含尾【下标】
System.out.println(sb);
// 3. StringBuilder deleteCharAt(int index) 删除指定下标处的字符
sb.deleteCharAt(0);
System.out.println(sb);
// insert
sb.insert(0,true).insert(0,"狼牙棒").insert(0, new Object());
System.out.println(sb);
// reverse()
sb.reverse();
System.out.println(sb);
// setCharAt()
sb.setCharAt(0, '插');// 将下标0处的字符修改为 插
System.out.println(sb);
// setLength()
// sb = new StringBuilder();
sb.setLength(1000);
System.out.println("设置后的长度:" + sb.length());
System.out.println("容量:" + sb.capacity());
System.out.println(sb);
// int capacity() 返回当前容量。
sb = new StringBuilder("abcd");//长度20
int capacity = sb.capacity();
System.out.println("容量:" + capacity);
System.out.println("==================");
// trimToSize() 将所有没有使用的数组空间去除
sb.trimToSize();
capacity = sb.capacity();
System.out.println("容量:" + capacity);
System.out.println("长度:" + sb.length());
sb = new StringBuilder();
System.out.println("容量:" + sb.capacity());
System.out.println("长度:" + sb.length());
3. StringBuffer类
- StringBuffer概述
StringBuffer类,功能上基本上跟StringBuilder类相同,只是StringBuffer是线程安全的,相比较StringBuilder而言StringBuffer效率更低一点。
- StringBuffer中的常用方法参考StringBuilder
4. String、StringBuffer、StringBuffer小结和使用场景【掌握】
String 字符串类,底层是基于char[], 一旦创建长度就固定不变了,适用于字符串不经常增删改的操作的场景。
StringBuilder: 基于可变的char[],默认长度是16个,适用于频繁操作(增删改插)字符串的场景,
该类是线程不安全的。
StringBuffer:基于可变的char[],默认长度是16个,适用于频繁操作(增删改插)字符串的场景,
该类是线程安全的。
如果是单线程和多线程没有线程安全要求,用StringBuilder。
如果是多线程有线程安全要求,用StringBuffer
如果不经常操作字符串用 String节省空间
StringBuffer和StringBuilder扩容机制:当要添加的字符串大于 > 当前字符数组的长度的时候扩容,扩容是: 原来长度*2+2 的方式扩容
拼接字符串效率最高的方式【掌握】
StringBuilder.append() > StringBuffer.append() > +
5.包装类
5.1 什么是包装类
场景:通过文本框获得用户输入的数字数据,因为文本框里面是书写文本数据的,所以后台得到的都是字符串。如果想要对字符串中的数字进行运算,必须将字符串转换成数字。
怎么解决上述出现的问题呢?
Java中提供了相应的解决问题的对象。
基本数据类型包装类:Java将基本数据类型值封装成了对象。
封装成对象有什么好处?
可以提供更多操作基本数据的功能。
java语言属于一种面向对象的语言,会把真实存在的事物或信息都会进行描述并封装为类。
在java中存在8种基本数据类型,而java语言也把这8种基本数据类型进行了封装。称为:包装类。
学习Java语法基础的时候,我们知道Java中有8种基本数据类型,这些数据类型可以在内存中开辟出对应类型的空间,然后可以保存对应类型的数据。
8种基本数据类型,它们仅仅只能规定空间的类型,而我们不能使用面向对象的方式去使用8种基本类型创建对象(new int();不能这样去创建基本类型的对象)。
由于8种基本类型不能像类类型一样去new对象,于是Java就对每种基本类型给出了一个对应的类类型。
而java语言也把这8种基本数据类型进行了封装。称为:包装类
基本数据类型 其对应的包装类(可以在API文档中查询到)
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
5.2 为什么要使用包装类
- 既然有了int干嘛还需要一个Integer,感觉差不多
- Integer类(字段,方法),在这个类中把int的位数,最大值,最小值写成常量了
- Integer类中提供了一些有用的方法:例如int-String之间的转换,和其它的数据类型的转换
- 包装类的继承体系
Number 的子类必须提供将表示的数值转换为 byte、double、float、int、long 和 short 的方法
- 也就是说,Number的子类都提供了方法,将子类对象所表示的数据,转换成byte、double、float、int、long 、short等数据类型
- 例如:查找Integer类中 :提供了非静态的下列方法,应该用对象调用
- byte byteValue() 以 byte 类型返回该 Integer 的值。
- double doubleValue() 以 double 类型返回该 Integer 的值。
- float floatValue() 以 float 类型返回该 Integer 的值。
- int intValue() 以 int 类型返回该 Integer 的值。
- long longValue() 以 long 类型返回该 Integer 的值。
- short shortValue() 以 short 类型返回该 Integer 的值。
Integer对象创建,调用构造方法
- Integer(int value)
- Integer(String s)
- 思考: 如下两个有什么区别
- Integer i1 = new Integer(123);
- Integer i1 = new Integer(“123”);
- 简单提示: 在项目很多时候从前台传输数据到后台几乎都是字符串的形式
常用方法:【掌握】
/*
* 调用Integer类中的常量字段: 调用方式:类名.字段名
* static int BYTES 用于表示二进制补码二进制形式的 int值的字节数。
static int MAX_VALUE 一个持有最大值一个 int可以有2 31 -1。
static int MIN_VALUE 的常量保持的最小值的 int可以具有,-2 31。
static int SIZE 用于表示二进制补码二进制形式的 int值的位数。
static 类<Integer> TYPE 类原始类型 int的 类实例。
*/
// 调用Integer类中的常量: static int MAX_VALUE
System.out.println(Integer.MAX_VALUE);// 2147483647
System.out.println(Integer.MIN_VALUE);// -2147483648
/*
* 因为当前类中有非static方法,所以需要创建对象
* 构造方法:
* 1.Integer(int value) 将int参数转换为Integer对象
2.Integer(String s) 将String参数s转换为对应的Integer对象,注意,必须保证字符串只能是数字,负责会报错NumberFormatException。
*/
Integer integer = new Integer(128);
System.out.println(integer);//123
// 构造方法:2.Integer(String s) 使用
Integer integer2 = new Integer("123");//NumberFormatException数字格式异常,通常是将字符串转换为数值类型的时候,有非数字的字符的时候发生该错误
System.out.println(integer2);
// 调用普通方法:1. static修饰的 => 类名.方法名(....) 2. 非static修饰的 => 对象名.方法名(....)
// 1. byte byteValue() 将当前的Integer对象转换为byte类型。 如果超出表示范围,会强制转换
byte byteValue = integer.byteValue();//转换的时候,如果超过byte表示范围,会以二进制方式进位
System.out.println(byteValue);
// 2. static int max(int a, int b) 返回两个 int的较大值,就像调用 Math.max一样 。
int max = Integer.max(1, 2);
System.out.println("最大值:" + max);
// 3. static int min(int a, int b) 返回两个 int的较小值,就像调用 Math.min一样 。
/*
* 4. static int parseInt(String s) 将字符串参数转换为有正负的十进制整数。
* 如果参数s有有非数字相关的字符,会报NumberFormatException数字格式异常,通常是将字符串转换为数值类型的时候,有非数字的字符的时候发生该错误
*/
// 5. static int sum(int a, int b) 根据+运算符将两个整数相加。
// 6. static String toHexString(int i) 将int类型的十进制值转换为十六进制的值
// 7. static Integer valueOf(String s) 将String类型转换为Integer类型
- 排错
定位错误的位置:
- 删除法:删除新编写的代码,运行如果没有错,说明是当前位置有错
- 根据提示信息:从上面的错误提示中 at 在,找到我们自己写的代码最后一个 21然后点一下(自动定位)
- debug逐行运行代码
排错
- 根据删除代码位置Integer i3 = new Integer("A"); 思考可能出错原因:分析并解决
只可能构造方法发生错误
- 根据错误信息NumberFormatException
NumberFormatException查看通过API查看错误描述:异常说明有不可解析参数
查看构造方法描述:如果抛出NumberFormatException异常说明有不可解析参数
分析原因:不合适的字符串例如“A”不能解析为整数 但是“10”可以
5.3 自动装箱拆箱
- 以int -- Integer为例
- 自动装箱 : Integer i1 = 123;
- 自动拆箱 : int i2 = i1;
- 手动装箱: int i2 = new Integer(123);
- 手动拆箱: int i2 = i1.intValue();
- 自动拆箱装箱的特点
- 从jdk5开始支持自动装箱 拆箱的
- 自动装箱拆箱只支持 基本数据类型和其对应的包装类
double d = 123;
Integer i = 123;
Double dd = 123.0;
Double ddd = 123; // 不行 : 自动装箱拆箱只支持 基本数据类型和其对应的包装类
5.4 享元模式
- 简单来说就是正数中的几个包装类内部把常用 [-128,127] 的数据缓存起来了
- 测试:
/* [-128~127]缓存,对象Integer的对象!当采用赋值方式,会先到缓存中查找是否有值缓存着,如果有,直接使用引用地址 */
Integer i1 = 20;
Integer i2 = 20;
System.out.println(i1 == i2);// true此处不存在拆箱比较值,比较的是对象的地址
/* 但凡是new 都会在堆内存中,创建一个新的对象,对象的地址值不一样 */
Integer i3 = new Integer(20);
Integer i4 = new Integer(20);
System.out.println("i3 == i1 "+(i3 == i1));//false
System.out.println(i3 == i4);//false
/* 赋值范围超过缓存值的范围,享源模式中没有缓存值,则会自动创建对象 */
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6);
/* 上面比较的都是Integer 对象 */
System.out.println(i1.equals(i2));// true
System.out.println(i1.equals(i3));// true
System.out.println(i3.equals(i4));// true
/* 在强化,对象值比较还是用equals(),java中Integer 已经覆写了equals() */
- 思考:浮点数会不会存在享元模式:不会..
- 思考:上面这段代码学了之后有什么用?
- 掌握这项知识,理解设计思想
- 需要知道的就是再一次强化:== equals的区别
- 如果是引用类型,而我们希望比较值是否相等,推荐使用equals更靠谱
5.5 小结
包装类,我们仅仅用了Integer示例,其他包装类使用方式完全相同。我们只需要掌握下面内容即可
-
-
- 包装类创建对象
- 包装类对象调用方法
-
6. 数学相关类Math/BigInteger/BigDecimal
6.1 数学相关类介绍
这几个常用类比较简单,主要是理解,为后期做知识储备,用到的时候在回顾能看懂即可,无需过分纠结,做好练习,重点关注概念及示例
6.2 Math
- 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数
- 记住一点: 以后遇到1中的情况,需要用到数学计算,知道今天学过,来这里来找即可
/*
* Math中常量: 调用常量:类名.常量名
* 类名.常量名:
static double E
static double PI
*/
System.out.println(Math.PI);
// 调用方法:调用方法(都是static修饰的)
// 1. static double abs(double a)返回值为 double绝对值。
// 2. static double ceil(double a) 天花板,向上取整
System.out.println(Math.ceil(3.14));//4.0
// 3. static double floor(double a) 地板,向下取整
System.out.println(Math.floor(3.14));//3.0
// 4. static long/int round(double a) 四舍五入
System.out.println(Math.round(3.45));//4
// 5. static double max(double a, double b)返回两个 double值中的较大值。
// 6. static double min(double a, double b)返回两个 double值中的较小值
// BigInteger bi = 10;//自动装箱,根本不存在.自动拆箱装箱,只与对应得包装类存在
BigInteger b1 = new BigInteger("1111111111111111111111111111");
BigInteger b2 = new BigInteger("1111111111111111111111111111");
// System.out.println(b2+b1);//自动装箱,根本不存在.自动拆箱装箱,只与对应得包装类存在
System.out.println(b2.multiply(b1));
System.out.println(b2.add(b1));
6.3 BigInteger
- BigInteger概述
BigInteger是比long类型精度更高的类型,当有用到精度高于long需求的时候用。
- 常用方法
// BigInteger bi = 10;//自动装箱,根本不存在.自动拆箱装箱,只与对应得包装类存在 BigInteger b1 = new BigInteger("1111111111111111111111111111"); BigInteger b2 = new BigInteger("1111111111111111111111111111"); // System.out.println(b2+b1);//自动装箱,根本不存在.自动拆箱装箱,只与对应得包装类存在 System.out.println(b2.multiply(b1)); System.out.println(b2.add(b1)); |
6.4 BigDecimal
1. BigDecimal概述
BigDecimal:比double类型精度更高的类型,一般使用在金融相关行业。例如,银行、保险公司等
建议大家用String类型的有参构造,因为double类型会有精度丢失问题。注意调用方法的时候的溢出问题。如果溢出,用重载方法。
- 常用方法:【掌握】
/* * 构造方法: * BigDecimal(String val) 建议使用这种方式创建,因为其他方式有可能会有精度丢失 */ BigDecimal bigDecimal = new BigDecimal("3.1415926"); BigDecimal bigDecimal2 = new BigDecimal("0.5926"); // 加法:BigDecimal add(BigDecimal augend) 返回 BigDecimal ,其值是 (this + augend) BigDecimal add = bigDecimal.add(bigDecimal2); System.out.println("和:" + add); // 减法:BigDecimal subtract(BigDecimal subtrahend) 返回 BigDecimal ,其值是 (this - subtrahend) // 乘法:BigDecimal multiply(BigDecimal multiplicand) 返回 BigDecimal ,其值是 (this × multiplicand), // 除法:BigDecimal divide(BigDecimal divisor)返回BigDecimal ,其值为(this / divisor // BigDecimal divide = bigDecimal.divide(bigDecimal2);// ArithmeticException 算数异常 // System.out.println("商:" + divide); /* * 当精度超出BigDecimal表示范围的时候,就需要用divide方法重载方法 * * public BigDecimal divide(BigDecimal divisor,RoundingMode roundingMode) * 该方法现在没有能够设置小数位数的参数,如果需要设置指定小数位数,用重载方法 * RoundingMode:就是一个枚举类,是决定取舍方式的。 * 使用方式:枚举名.字段; * * 建议使用:该方法可以决定保留小数的位数 * BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) * scale:保留的小数位数 * roundingMode: 通过类.常量使用,例如:BigDecimal.ROUND_DOWN */ BigDecimal divide = bigDecimal.divide(bigDecimal2,12,BigDecimal.ROUND_DOWN);// ArithmeticException 算数异常 System.out.println("商:" + divide); BigDecimal divide2 = bigDecimal.divide(bigDecimal2,12,RoundingMode.FLOOR);// ArithmeticException 算数异常 System.out.println("商:" + divide2);
6.5 小结
当使用到上面类的时候,在查API或者百度,今天只要学会调用方法即可。
7. System/Runtime/Java中的垃圾回收机制
7.1 为什么需要学习
因后期学习开发中会用到里面的一些API,我们了解一下,其中垃圾回收机制及代码操作实例,需要我们一些概念。所以该知识点我们作为了解
7.2 System类中常用方法【掌握】
System类(重点掌握两个方法)【掌握】
1.System.arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length)【掌握】
数组复制方法
src: 源数组
srcPos:源数组开始复制的下标
dest: 目标数组
destPos:目标数组开始复制下标
length: 复制的元素个数
从源数组src中的srcPos下标处,开始复制 length个元素到目标数组dest中,从destPos下标开始粘贴
注意不要超过两个数组的长度限制
2.long System.currentTimeMillis()【掌握】返回当前时间毫秒数。主要是用了测试程序运行时间
// 2.long System.currentTimeMillis()(掌握)返回当前时间毫秒数。主要是用了测试程序运行时间
long startTime = System.currentTimeMillis();//先获取复制数组前的时间毫秒数
System.out.println(startTime);
// 1.System.arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length)(掌握)
int[] src = {1,2,3,4,5,6,7,8,9};
int[] dest = new int[4];
// 从数组src的第二个元素开始复制,到dest数组的第一个元素开始粘贴,一个复制了3个使用
System.arraycopy(src, 1, dest, 0, 3);//注意下标越界问题
// 直接打印数组是地址,所以,需要调用Arrays中的toString方法
String str = Arrays.toString(dest);
// 打印字符串str
System.out.println(str);
// 2.long System.currentTimeMillis()(掌握)返回当前时间毫秒数。主要是用了测试程序运行时间
long endTime = System.currentTimeMillis();//先获取复制数组前的时间毫秒数
System.out.println(endTime);
System.out.println("数组复制的时间是:" + (endTime - startTime));
了解的2个方法
3. System.exit(int status)结束当前JVM。 status - 退出状态。 非零状态码表示异常终止
4. System.gc() 调用垃圾(堆中匿名对象)回收器 谨慎使用,
因为业内有句话叫:stop all the world 所有的时间都在处理垃圾
public class SystemTest2 {
public static void main(String[] args) {
// ==================下面作为了解=============================
// 3. System.exit(int status)结束当前JVM。 status - 退出状态。 非零状态码表示异常终止
// System.out.println("结束前...");
// System.exit(0);
// System.out.println("完事后~!");
// 4. System.gc() 调用垃圾(堆中匿名对象)回收器 谨慎使用, 因为业内有句话叫:stop all the world 因为在处理完垃圾前,不会做其他工作
for (int i = 0; i < 1000; i++) {
//创建匿名对象Garbage,制造垃圾
new Garbage();
}
// 调用垃圾回收方法gc()
System.gc();
}
}
/**
* 垃圾类,为了测试垃圾回收
*
*/
class Garbage {
/** 声明一个计数器,因为需要每个对象共享计数器,所以加上static修饰 */
static int count = 0;
@Override // 在对象被GC销毁的时候,会自动调用该方法,所以,重写一下,通过打印语句看执行效果
protected void finalize() throws Throwable {
System.out.println("我被干掉了 : " + ++count);
}
}
7.3 Runtime类【了解】
Runtime类概述:
Runtime类:该类可以通过Java代码执行启动一个进程(一个应用程序)
使用方式:
1. 获取对象。通过静态方法获取
Runtime runtime = Runtime.getRuntime();
2.Process exec(String command) 通过字符串参数,启动对应名字的进程,并且返回该进程
注意:只能执行启动该文件夹 c:\windows\system32下
// 1. 获取对象。通过静态方法获取 ,Runtime.getRuntime();
Runtime runtime = Runtime.getRuntime();
// 2.Process exec(String command) 通过字符串参数,启动对应名字的进程,并且返回该进程
runtime.exec("mspaint.exe");//此处有一个红色的报错,将鼠标移动到错误语句上,选择弹出框中的第一个选项即可
runtime.exec("notepad.exe");//此处有一个红色的报错,将鼠标移动到错误语句上,选择弹出框中的第一个选项即可
runtime.exec("FeiQ.exe");//此处有一个红色的报错,将鼠标移动到错误语句上,选择弹出框中的第一个选项即可