第十一章 日期类

  1. import java.text.SimpleDateFormat;
  2. import java.util.Date;
  3. public class DateTest01 {
  4. public static void main(String[] args) throws Exception {
  5. // 获取系统当前时间(精确到毫秒的系统当前时间)
  6. // 直接调用无参数构造方法就行。
  7. Date nowTime = new Date();
  8. // java.util.Date类的toString()方法已经被重写了。
  9. // 输出的应该不是一个对象的内存地址,应该是一个日期字符串。
  10. //System.out.println(nowTime); //Thu Mar 05 10:51:06 CST 2020
  11. // 日期可以格式化吗?
  12. // 将日期类型Date,按照指定的格式进行转换:Date --转换成具有一定格式的日期字符串-->String
  13. // SimpleDateFormat是java.text包下的。专门负责日期格式化的。
  14. /*
  15. yyyy 年(年是4位)
  16. MM 月(月是2位)
  17. dd 日
  18. HH 时
  19. mm 分
  20. ss 秒
  21. SSS 毫秒(毫秒3位,最高999。1000毫秒代表1秒)
  22. 注意:在日期格式中,除了y M d H m s S这些字符不能随便写之外,剩下的符号格式自己随意组织。
  23. */
  24. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
  25. //SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
  26. //SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
  27. String nowTimeStr = sdf.format(nowTime);
  28. System.out.println(nowTimeStr);
  29. // 假设现在有一个日期字符串String,怎么转换成Date类型?
  30. // String --> Date
  31. String time = "2008-08-08 08:08:08 888";
  32. //SimpleDateFormat sdf2 = new SimpleDateFormat("格式不能随便写,要和日期字符串格式相同");
  33. // 注意:字符串的日期格式和SimpleDateFormat对象指定的日期格式要一致。不然会出现异常:java.text.ParseException
  34. SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
  35. Date dateTime = sdf2.parse(time);
  36. System.out.println(dateTime); //Fri Aug 08 08:08:08 CST 2008
  37. }
  38. }
  1. /*
  2. 获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数。
  3. 1秒 = 1000毫秒
  4. 简单总结一下System类的相关属性和方法:
  5. System.out 【out是System类的静态变量。】
  6. System.out.println() 【println()方法不是System类的,是PrintStream类的方法。】
  7. System.gc() 建议启动垃圾回收器
  8. System.currentTimeMillis() 获取自1970年1月1日到系统当前时间的总毫秒数。
  9. System.exit(0) 退出JVM。
  10. */
  11. public class DateTest02 {
  12. public static void main(String[] args) {
  13. // 获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数。
  14. long nowTimeMillis = System.currentTimeMillis();
  15. System.out.println(nowTimeMillis); //1583377912981
  16. // 统计一个方法耗时
  17. // 在调用目标方法之前记录一个毫秒数
  18. long begin = System.currentTimeMillis();
  19. print();
  20. // 在执行完目标方法之后记录一个毫秒数
  21. long end = System.currentTimeMillis();
  22. System.out.println("耗费时长"+(end - begin)+"毫秒");
  23. }
  24. // 需求:统计一个方法执行所耗费的时长
  25. public static void print(){
  26. for(int i = 0; i < 1000000000; i++){
  27. System.out.println("i = " + i);
  28. }
  29. }
  30. }
  1. import java.text.SimpleDateFormat;
  2. import java.util.Date;
  3. public class DateTest03 {
  4. public static void main(String[] args) {
  5. // 这个时间是什么时间?
  6. // 1970-01-01 00:00:00 001
  7. Date time = new Date(1); // 注意:参数是一个毫秒
  8. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
  9. String strTime = sdf.format(time);
  10. // 北京是东8区。差8个小时。
  11. System.out.println(strTime); // 1970-01-01 08:00:00 001
  12. // 获取昨天的此时的时间。
  13. Date time2 = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
  14. String strTime2 = sdf.format(time2);
  15. System.out.println(strTime2); //2020-03-04 11:44:14 829
  16. }
  17. }

第十二章 数字类

  1. import java.math.BigDecimal;
  2. /*
  3. 1、BigDecimal 属于大数据,精度极高。不属于基本数据类型,属于java对象(引用数据类型)
  4. 这是SUN提供的一个类。专门用在财务软件当中。
  5. 2、注意:财务软件中double是不够的。咱们之前有一个学生去用友面试,经理就问了这样一个问题:
  6. 你处理过财务数据吗?用的哪一种类型?
  7. 千万别说double,说java.math.BigDecimal
  8. */
  9. public class BigDecimalTest01 {
  10. public static void main(String[] args) {
  11. // 这个100不是普通的100,是精度极高的100
  12. BigDecimal v1 = new BigDecimal(100);
  13. // 精度极高的200
  14. BigDecimal v2 = new BigDecimal(200);
  15. // 求和
  16. // v1 + v2; // 这样不行,v1和v2都是引用,不能直接使用+求和。
  17. BigDecimal v3 = v1.add(v2); // 调用方法求和。
  18. System.out.println(v3); //300
  19. BigDecimal v4 = v2.divide(v1);
  20. System.out.println(v4); // 2
  21. }
  22. }
  1. import java.text.DecimalFormat;
  2. /*
  3. 关于数字的格式化。(了解)
  4. */
  5. public class DecimalFormatTest01 {
  6. public static void main(String[] args) {
  7. // java.text.DecimalFormat专门负责数字格式化的。
  8. //DecimalFormat df = new DecimalFormat("数字格式");
  9. /*
  10. 数字格式有哪些?
  11. # 代表任意数字
  12. , 代表千分位
  13. . 代表小数点
  14. 0 代表不够时补0
  15. ###,###.##
  16. 表示:加入千分位,保留2个小数。
  17. */
  18. DecimalFormat df = new DecimalFormat("###,###.##");
  19. //String s = df.format(1234.56);
  20. String s = df.format(1234.561232);
  21. System.out.println(s); // "1,234.56"
  22. DecimalFormat df2 = new DecimalFormat("###,###.0000"); //保留4个小数位,不够补上0
  23. String s2 = df2.format(1234.56);
  24. System.out.println(s2); // "1,234.5600"
  25. }
  26. }

第十三章 random类

  1. import java.util.Random;
  2. /**
  3. * 随机数
  4. */
  5. public class RandomTest01 {
  6. public static void main(String[] args) {
  7. // 创建随机数对象
  8. Random random = new Random();
  9. // 随机产生一个int类型取值范围内的数字。
  10. int num1 = random.nextInt();
  11. System.out.println(num1);
  12. // 产生[0~100]之间的随机数。不能产生101。
  13. // nextInt翻译为:下一个int类型的数据是101,表示只能取到100.
  14. int num2 = random.nextInt(101); //不包括101
  15. System.out.println(num2);
  16. }
  17. }

第十四章 枚举

1. 枚举基本概念

1.1 语法

enum 枚举类型名{ 枚举值1,枚举值2 }

1.2 什么时候使用

结果超过两种并且还是可以一枚一枚列举出来的,建议使用枚举类型,例如:颜色、四季、星期等都可 以使用枚举类型。

1.3 switch语句中使用枚举

  1. enum ColorType{
  2. GREEN,
  3. RED,
  4. ORANGE,
  5. WHITE,
  6. BLACK
  7. }
  8. private void TestEnum(ColorType type){
  9. switch (type){
  10. case ColorType.GREEN:
  11. break;
  12. case ColorType.RED:
  13. break;
  14. case ColorType.ORANGE:
  15. break;
  16. case ColorType.WHITE:
  17. break;
  18. case ColorType.BLACK:
  19. break;
  20. default:
  21. }
  22. }

以上会报一个错误:
an enum switch case label must be the unqualified name of an enumeration constant
意思是: 枚举 switchcase 标签必须为枚举常量的非限定名称,即case语句中只能写枚举类定义的变量名称,不能加类名,如下代码:

  1. private void TestEnum(ColorType type){
  2. switch (type){
  3. case GREEN:
  4. break;
  5. case RED:
  6. break;
  7. case ORANGE:
  8. break;
  9. case WHITE:
  10. break;
  11. case BLACK:
  12. break;
  13. default:
  14. }
  15. }

第十五章 异常

1. 异常的概念及作用

  • 程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常,java语言是很完善的语言,提供了异常的处理方式,当程序执行过程中出现了不正常情况,java把该异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加的健壮。
  • 异常是一个类,可以通过构造方法实例化异常类对象

2. 异常是什么时候创建的

  1. public class ExceptionTest03 {
  2. public static void main(String[] args) {
  3. /*
  4. 程序执行到此处发生了ArithmeticException异常,
  5. 底层new了一个ArithmeticException异常对象,
  6. 然后抛出了,由于是main方法调用了100 / 0,
  7. 所以这个异常ArithmeticException抛给了main方法,
  8. main方法没有处理,将这个异常自动抛给了JVM。
  9. JVM最终终止程序的执行。
  10. ArithmeticException 继承 RuntimeException,属于运行时异常。
  11. 在编写程序阶段不需要对这种异常进行预先的处理。
  12. */
  13. System.out.println(100 / 0);
  14. // 这里的HelloWorld没有输出,没有执行。
  15. System.out.println("Hello World!");
  16. }
  17. }

3. 异常的继承机制

image.png

  • Exception的直接子类:编译时异常(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错,因此得名编译时异常,也叫受检异常:CheckedException、受控异常)
  • RuntimeException:运行时异常(在编写程序阶段程序员可以预先处理,也可以不管,都行;也叫非受检异常:UnCheckedException、非受控异常)
  • 编译时异常和运行时异常,都是发生在运行阶段;编译阶段异常是不会发生的,编译时异常因为什么而得名因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,因此得名。
  • 所有异常都是在运行阶段发生的。因为只有程序运行阶段才可以new对象。因为异常的发生就是new异常对象。

3.1 编译时异常和运行时异常的区别

  1. - 编译时异常一般发生的概率比较高。对于一些发生概率较高的异常,需要在运行之前对其进行预处理。
  2. - 运行时异常一般发生的概率比较低。没必要提前对这种发生概率较低的异常进行预处理。

4. 异常的处理

  1. public class ExceptionTest05 {
  2. // 第一种处理方式:在方法声明的位置上继续使用:throws,来完成异常的继续上抛。抛给调用者。
  3. // 上抛类似于推卸责任。(继续把异常传递给调用者。)
  4. /*
  5. public static void main(String[] args) throws ClassNotFoundException {
  6. doSome();
  7. }
  8. */
  9. // 第二种处理方式:try..catch进行捕捉。
  10. // 捕捉等于把异常拦下了,异常真正的解决了。(调用者是不知道的。)
  11. public static void main(String[] args) {
  12. try {
  13. doSome();
  14. } catch (ClassNotFoundException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. public static void doSome() throws ClassNotFoundException{
  19. System.out.println("doSome!!!!");
  20. }
  21. }

注意: 只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。 另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行。 try..catch捕捉异常之后,后续代码可以执行。 在以后的开发中,处理编译时异常,应该上报还是捕捉呢,怎么选? 如果希望调用者来处理,选择throws上报。 其它情况使用捕捉的方式。

  • 一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM,JVM只有终止,异常处理机制的作用就是增强程序的健壮性:

怎么能做到,异常发生了也不影响程序的执行。所以一般main方法中的异常建议使用try..catch进行捕捉。main就不要继续上抛了。

  • throws后面也可以写多个异常,可以使用逗号隔开。

4.1 深入try..catch

1、catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
2、catch可以写多个。建议catch的时候,精确的一个一个处理。这样有利于程序的调试。
3、catch写多个的时候,从上到下,必须遵守从小到大。

4.2 异常对象有两个非常重要的方法

  1. - 获取异常简单的描述信息:
  2. String msg = exception.getMessage();
  3. - 打印异常追踪的堆栈信息:
  4. exception.printStackTrace();
  1. public class ExceptionTest08 {
  2. public static void main(String[] args) {
  3. // 这里只是为了测试getMessage()方法和printStackTrace()方法。
  4. // 这里只是new了异常对象,但是没有将异常对象抛出。JVM会认为这是一个普通的java对象。
  5. NullPointerException e = new NullPointerException("空指针异常fdsafdsafdsafds");
  6. // 获取异常简单描述信息:这个信息实际上就是构造方法上面String参数。
  7. String msg = e.getMessage(); //空指针异常fdsafdsafdsafds
  8. System.out.println(msg);
  9. // 打印异常堆栈信息
  10. // java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的;所以Hello world
  11. //可能会在堆栈追踪信息之前打印
  12. e.printStackTrace();
  13. for(int i = 0; i < 1000; i++){
  14. System.out.println("i = " + i);
  15. }
  16. System.out.println("Hello World!");
  17. }
  18. }

4.3 关于try..catch中的finally子句

1、在finally子句中的代码是最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常,finally子句必须和try一起出现,不能单独编写。

2、finally语句通常使用在哪些情况下呢?
通常在finally语句块中完成资源的释放/关闭
因为finally中的代码比较有保障
即使try语句块中的代码出现异常,finally中代码也会正常执行

  1. public class ExceptionTest11 {
  2. public static void main(String[] args) {
  3. /*
  4. try和finally,没有catch可以吗?可以。
  5. try不能单独使用。
  6. try finally可以联合使用。
  7. 以下代码的执行顺序:
  8. 先执行try...
  9. 再执行finally...
  10. 最后执行 return (return语句只要执行方法必然结束。)
  11. */
  12. try {
  13. System.out.println("try...");
  14. return;
  15. } finally {
  16. // finally中的语句会执行。能执行到。
  17. System.out.println("finally...");
  18. }
  19. // 这里不能写语句,因为这个代码是无法执行到的。
  20. //System.out.println("Hello World!");
  21. }
  22. }
  1. public class ExceptionTest12 {
  2. public static void main(String[] args) {
  3. try {
  4. System.out.println("try...");
  5. // 退出JVM
  6. System.exit(0); // 退出JVM之后,finally语句中的代码就不执行了!
  7. } finally {
  8. System.out.println("finally...");
  9. }
  10. }
  11. }
  1. public class ExceptionTest13 {
  2. public static void main(String[] args) {
  3. int result = m();
  4. System.out.println(result); //100
  5. }
  6. /*
  7. java语法规则(有一些规则是不能破坏的,一旦这么说了,就必须这么做!):
  8. java中有一条这样的规则:
  9. 方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法!)
  10. java中还有一条语法规则:
  11. return语句一旦执行,整个方法必须结束(亘古不变的语法!)
  12. */
  13. public static int m(){
  14. int i = 100;
  15. try {
  16. // 这行代码出现在int i = 100;的下面,所以最终结果必须是返回100
  17. // return语句还必须保证是最后执行的。一旦执行,整个方法结束。
  18. return i;
  19. } finally {
  20. i++;
  21. }
  22. }
  23. }
  24. /*
  25. 反编译之后的效果
  26. public static int m(){
  27. int i = 100;
  28. int j = i;
  29. i++;
  30. return j;
  31. }
  32. */

4.4 final finally finalize有什么区别

final 关键字
final修饰的类无法继承
final修饰的方法无法覆盖
final修饰的变量不能重新赋值。

  1. finally 关键字<br /> try一起联合使用。<br /> finally语句块中的代码是必须执行的。
  2. finalize 标识符<br /> 是一个Object类中的方法名。<br /> 这个方法是由垃圾回收器GC负责调用的。

4.5 方法覆盖的遗留问题

  1. class Animal {
  2. public void doSome(){
  3. }
  4. public void doOther() throws Exception{
  5. }
  6. }
  7. class Cat extends Animal {
  8. // 编译正常。
  9. public void doSome() throws RuntimeException{
  10. }
  11. // 编译报错。
  12. /*public void doSome() throws Exception{
  13. }*/
  14. // 编译正常。
  15. /*public void doOther() {
  16. }*/
  17. // 编译正常。
  18. /*public void doOther() throws Exception{
  19. }*/
  20. // 编译正常。
  21. public void doOther() throws NullPointerException{
  22. }
  23. }
  1. - 父类方法抛出一个FileNotFoundException,这时候子类可以抛出FileNotException或者其子类,例如我自己写了File1Exception,File2Exception,他们都继承自FileNotException,这时候子类可以同时抛出File1ExceptionFile2Exception,因为他们都是FileNotFoundException,满足“子类抛出的异常类型不能比父类抛出的异常类型更宽泛”这个条件 同时子类还可以抛出RuntimeExceptioin这是运行时异常,不受上面条件的约束

5. Java中怎么自定义异常

第一步:编写一个类继承Exception或者RuntimeException.
第二步:提供两个构造方法,一个无参数的,一个带有String参数的。

  1. public class MyException extends Exception{ // 编译时异常
  2. public MyException(){
  3. }
  4. public MyException(String s){
  5. super(s);
  6. }
  7. }
  8. /*
  9. public class MyException extends RuntimeException{ // 运行时异常
  10. }
  11. */