首页 > 编程语言 >Java中异常处理对程序执行流程的影响

Java中异常处理对程序执行流程的影响

时间:2024-10-13 22:33:19浏览次数:1  
标签:Java 流程 程序执行 try println finally catch 异常 out

Java 的异常处理机制为程序员提供了一种有效的手段来处理运行时可能发生的各种错误和异常情况。它通过捕获处理异常来避免程序的崩溃,同时还能进行适当的恢复或终止操作。下面将从多个角度对异常处理对程序执行流程的影响进行分类说明,并结合详细示例来说明其影响。

1. 正常执行流程与异常中断的流程

在没有异常的情况下,Java 程序按照顺序执行,每个语句依次运行。但在出现异常时,程序的正常执行流程会被中断,并且立即转到异常处理逻辑,跳过异常发生后到异常捕获之间的代码。具体来说,异常处理中断了当前的执行流程,将其交给适当的 catch 块或者上层调用者处理。

示例:正常流程与异常中断

public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("Start of main method");
        try {
            int result = divide(10, 0);  // 这里会抛出异常
            System.out.println("This will not be printed");
        } catch (ArithmeticException e) {
            System.out.println("Caught an exception: " + e.getMessage());
        }
        System.out.println("End of main method");
    }

    public static int divide(int a, int b) {
        return a / b;  // 0 作为除数会抛出 ArithmeticException
    }
}

执行流程分析

  • divide(10, 0) 执行时,程序遇到除以零的情况,抛出了 ArithmeticException,程序的正常执行流程被中断。
  • 异常被 catch 块捕获并处理,程序跳过了 System.out.println("This will not be printed"),而是直接执行 catch 块中的代码。
  • 最终,程序恢复执行,继续运行 catch 块之后的代码,即打印出 "End of main method"。

2. try-catch 结构中的控制流

try-catch 结构中,Java 程序执行到 try 块时,会尝试执行 try 块中的代码。如果没有异常发生,catch 块不会执行,程序继续执行 try-catch 之后的代码;如果 try 块中的代码抛出了异常,catch 块会被触发,控制权转移到 catch 块。

示例:try-catch 的控制流

public class TryCatchDemo {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int result = 10 / 0;  // 抛出 ArithmeticException
            System.out.println("This line will not be executed");
        } catch (ArithmeticException e) {
            System.out.println("Exception caught: " + e);
        }
        System.out.println("After try-catch block");
    }
}

执行流程分析

  • try 块中的 int result = 10 / 0; 会抛出异常,导致 try 块中断,跳转到 catch 块。
  • catch 块捕获异常后处理,并打印异常信息。
  • 最后,程序继续执行 catch 块之后的代码,即打印 "After try-catch block"。

3. finally 块的执行

finally 块是异常处理的一部分,无论是否抛出异常,finally 块中的代码都会被执行。它通常用于资源清理,如关闭文件、数据库连接等。

示例:finally 块的执行

public class FinallyDemo {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int result = 10 / 0;  // 抛出 ArithmeticException
        } catch (ArithmeticException e) {
            System.out.println("Exception caught: " + e);
        } finally {
            System.out.println("Finally block executed");
        }
    }
}

执行流程分析

  • try 块中发生 ArithmeticException,控制流转移到 catch 块。
  • 无论是否有异常,finally 块总会执行,打印 "Finally block executed"。

如果没有异常:

public class FinallyNoExceptionDemo {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int result = 10 / 2;  // 没有异常
        } catch (ArithmeticException e) {
            System.out.println("Exception caught: " + e);
        } finally {
            System.out.println("Finally block executed");
        }
    }
}

执行流程

  • 没有异常,程序正常执行 try 块中的代码,跳过 catch,然后 finally 块照常执行。

4. 抛出异常的执行流程(throwthrows

  • throw:用于在程序中显式地抛出异常。抛出异常后,当前代码块的执行立即停止,程序跳转到异常处理器。
  • throws:用于方法签名,表示该方法可能会抛出指定类型的异常,调用者需要处理这些异常。

示例:显式抛出异常

public class ThrowDemo {
    public static void main(String[] args) {
        try {
            validateAge(15);  // 传入非法年龄
        } catch (IllegalArgumentException e) {
            System.out.println("Caught exception: " + e.getMessage());
        }
    }

    public static void validateAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("Age must be 18 or older");
        }
    }
}

执行流程分析

  • validateAge(15) 会显式抛出 IllegalArgumentException,异常会立即中断 validateAge 的执行,转移到 catch 块处理。

5. 多重异常捕获

Java 支持多个 catch 块处理不同类型的异常。当 try 块抛出异常时,JVM 会按照 catch 块的顺序依次检查,如果匹配到适当的异常类型,执行相应的 catch 块,其它 catch 块将被跳过。

示例:多重异常捕获

public class MultipleCatchDemo {
    public static void main(String[] args) {
        try {
            int[] arr = new int[5];
            arr[5] = 10;  // 数组越界异常
            int result = 10 / 0;  // 除以零异常
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index out of bounds: " + e);
        } catch (ArithmeticException e) {
            System.out.println("Arithmetic exception: " + e);
        }
    }
}

执行流程分析

  • 数组越界时,程序进入 ArrayIndexOutOfBoundsExceptioncatch 块,打印异常信息,后面的 ArithmeticException 不会被捕获。

6. 异常的传播(Exception Propagation)

如果一个方法中没有处理异常(即没有 try-catch 块),异常会沿着方法调用栈向上传递,直到找到适当的异常处理程序。如果所有调用链上都没有处理异常,程序会终止并打印堆栈信息。

示例:异常传播

public class ExceptionPropagationDemo {
    public static void main(String[] args) {
        try {
            method1();
        } catch (ArithmeticException e) {
            System.out.println("Exception handled in main: " + e);
        }
    }

    public static void method1() {
        method2();  // 调用 method2
    }

    public static void method2() {
        int result = 10 / 0;  // 这里抛出 ArithmeticException
    }
}

执行流程分析

  • method2 抛出异常,但没有 catch 块处理。
  • 异常传播到 method1,但 method1 也没有处理异常。
  • 最终,异常被 main 方法中的 catch 块捕获。

7. 受检异常与非受检异常的影响

Java 将异常分为两大类:受检异常(Checked Exception)和 非受检异常(Unchecked Exception)。

  • 受检异常:必须在编译时处理,要么捕获要么声明抛出,例如 IOException
  • 非受检异常:如 NullPointerExceptionArithmeticException,这些是 RuntimeException 的子类,不强制要求处理。

示例:受检异常的处理

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class CheckedExceptionDemo {
    public static void main(String[] args) {


        try {
            File file = new File("nonexistent.txt");
            FileReader fr = new FileReader(file);  // 可能抛出 FileNotFoundException
        } catch (FileNotFoundException e) {
            System.out.println("File not found: " + e);
        }
    }
}

执行流程分析

  • FileReader 可能抛出 FileNotFoundException,这是一种受检异常,必须在编译时处理。
  • 没有处理受检异常会导致编译错误。

8. .带资源的try,即try with resource, 可以自动关闭资源,当程序调出try 块之后,即执行到 catch 或 finally中的时候,资源已经关闭了,拿不到InputStream了

在 Java 中,try-with-resources 语法是为了简化资源的管理,并确保在使用完资源后自动进行清理(关闭)。通常,资源是指那些实现了 AutoCloseableCloseable 接口的对象,例如文件、输入输出流、数据库连接等。try-with-resources 的核心作用就是在代码块执行完毕之后,无论是否发生异常,都会自动关闭资源。

try-with-resources 的执行流程

当使用 try-with-resources 语句时,资源会在 try 块执行结束或发生异常时自动关闭。这意味着当程序执行到 catchfinally 块时,资源已经关闭了,因此在 catchfinally 中无法再访问已关闭的资源(例如 InputStream 等)。

其执行流程如下:

  1. 资源初始化:在 try 块开始之前,所有资源会在 try 语句中声明并初始化。
  2. try 块执行try 块中的代码正常执行,如果没有异常,则直接执行完后资源关闭。
  3. catch 块执行(可选):如果 try 块中发生了异常,程序会跳转到相应的 catch 块。
  4. 资源自动关闭:不论是否抛出异常,资源都会在 try 块结束后自动关闭。
  5. finally 块执行(可选):如果有 finally 块,程序在关闭资源后会执行 finally 中的代码。

try-with-resources 示例

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesDemo {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
            String line = br.readLine();  // 正常读取文件
            System.out.println(line);
        } catch (IOException e) {
            System.out.println("Caught an IOException: " + e.getMessage());
        } finally {
            System.out.println("Finally block executed");
        }
    }
}

执行流程:

  1. 资源初始化BufferedReaderFileReadertry 块的开头被创建。
  2. try 块执行br.readLine() 尝试读取文件的内容。如果读取成功且没有异常发生,try 块正常结束。
  3. 资源关闭:无论是否抛出异常,在 try 块执行完毕或异常发生后,BufferedReaderFileReader 都会被自动关闭。
  4. catch 块执行(如果有异常):如果在 try 块中发生了 IOException,程序跳到 catch 块处理异常。
  5. finally 块执行:关闭资源之后,无论是否有异常,finally 块中的代码都会执行。

问题:catchfinally 中无法获取资源

由于 try-with-resources 语法确保资源在 try 块结束时自动关闭,因此在进入 catchfinally 块之前,资源已经被关闭了。如果尝试在 catchfinally 块中再次访问资源,例如 InputStream,则会抛出异常,提示资源已关闭。

示例:无法在 catch 中访问已关闭的资源

import java.io.*;

public class TryWithResourcesCatchDemo {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("nonexistent.txt"))) {
            String line = br.readLine();  // 此行会抛出异常
            System.out.println(line);
        } catch (IOException e) {
            // 资源已经关闭,下面这行代码会抛出 IllegalStateException 或其他类似异常
            try {
                System.out.println("Trying to read after exception: " + br.readLine());  // 不能访问已关闭的资源
            } catch (IOException ex) {
                System.out.println("Caught another IOException: " + ex.getMessage());
            }
        }
    }
}

在上述代码中,br.readLine()catch 块中访问已关闭的 BufferedReader,因此会抛出 IOException,提示资源已关闭。

如何处理在 catchfinally 中访问资源的需求

如果必须在 catchfinally 块中访问资源的内容或获取未完全处理的输入/输出,可以采取以下策略:

  1. 提前读取并存储数据:如果在 try 块中需要读取输入流(如 InputStreamReader),可以在 try 块内部先将数据读入一个变量或数据结构(如 Stringbyte[]),然后在 catchfinally 中使用这些已保存的数据。

  2. 延迟关闭资源:手动管理资源的关闭,避免使用 try-with-resources,以便在异常发生时可以在 catchfinally 中访问资源。但这种做法会让代码复杂化,需要手动确保资源在最终被正确关闭。

示例:提前读取数据

import java.io.*;

public class TryWithResourcesSolutionDemo {
    public static void main(String[] args) {
        StringBuilder fileContent = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                fileContent.append(line).append("\n");
            }
        } catch (IOException e) {
            System.out.println("Exception caught: " + e.getMessage());
        } finally {
            System.out.println("File content: " + fileContent.toString());
        }
    }
}

在此示例中,数据在 try 块中被完整读取并存储在 fileContent 中,因此在 finally 块中能够访问文件的内容,而不需要直接依赖已关闭的 BufferedReader 对象。

总结

  • try-with-resources 语法在 try 块结束后会自动关闭资源,无论是否发生异常。
  • 资源在 catchfinally 中已经关闭,因此不能在这些块中再次访问资源,如 InputStreamReader
  • 为了解决在 catchfinally 中访问资源的问题,可以提前将所需数据读取到内存中,或者选择手动管理资源的关闭(但这种做法不推荐,容易出错)。

9. .finally 块中抛出异常,会屏蔽掉 catch 块中异常

在 Java 中,finally 块中的异常确实会屏蔽掉 catch 块中抛出的异常。这是因为 finally 块的执行优先于 catch 块中抛出的异常的传播。在这种情况下,finally 块抛出的异常会取代 catch 块中的异常,导致程序无法感知和处理 catch 块抛出的异常。

让我们详细解释一下这个机制,并通过代码演示其效果。

异常处理流程

  • 当一个异常在 try 块中被抛出时,程序会进入 catch 块处理该异常。
  • 不论 catch 块是否抛出异常,finally 块总是会执行。
  • 如果 finally 块中抛出了新的异常,这个异常会覆盖之前的异常,并导致程序最终抛出的是 finally 中的异常,而不是 catch 中的异常。

示例:finally 块屏蔽 catch 块的异常

以下代码演示了 finally 块如何屏蔽 catch 块中的异常:

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("Exception in try block");
        } catch (RuntimeException e) {
            System.out.println("Caught exception: " + e.getMessage());
            throw new RuntimeException("Exception in catch block");  // 在 catch 中抛出新的异常
        } finally {
            System.out.println("Executing finally block");
            throw new RuntimeException("Exception in finally block");  // 在 finally 中抛出新的异常
        }
    }
}

输出:

Caught exception: Exception in try block
Executing finally block
Exception in thread "main" java.lang.RuntimeException: Exception in finally block

执行流程分析:

  1. try:首先,在 try 块中抛出一个 RuntimeException,程序立即跳转到对应的 catch 块。
  2. catch:在 catch 块中,程序捕获到 try 块中的异常,并打印 "Caught exception: Exception in try block"。然后,catch 块再次抛出一个新的异常(Exception in catch block)。
  3. finally:在抛出 catch 块中的异常之后,程序转向 finally 块,finally 块的内容总是会执行。在 finally 块中,再次抛出一个新的异常(Exception in finally block)。
  4. 异常屏蔽:尽管 catch 块中抛出了异常,但由于 finally 块也抛出了异常,finally 块的异常会覆盖(屏蔽)掉 catch 块的异常。因此,最终抛出的异常是 finally 中的异常,而不是 catch 中的异常。

为什么会发生这种情况?

在 Java 中,finally 块的设计目的是确保在不论发生什么情况时,都能执行清理工作或其他必要的后续操作。由于 finally 块优先于异常传播的执行顺序,一旦 finally 块抛出了异常,这个异常会直接影响程序的最终状态。Java 虚拟机会优先处理 finally 块的异常,而不是之前发生的异常。

如何处理这种情况?

为了避免 finally 块中的异常屏蔽掉 catch 块中的异常,常见的做法是:

  1. 不在 finally 块中抛出异常:确保 finally 块中的代码尽量不抛出异常,或者对可能抛出的异常进行捕获和处理。
  2. 记录多个异常:如果必须抛出 finally 中的异常,可以考虑使用 addSuppressed 方法将 finally 中的异常附加到 catch 块中的异常,确保不会丢失任何重要信息。

使用 addSuppressed 处理多个异常

Java 7 引入了 addSuppressed 方法,可以将多个异常一起记录下来。这样,catch 块中的异常不会被 finally 中的异常完全屏蔽。

以下是一个使用 addSuppressed 的示例:

public class ExceptionDemo {
    public static void main(String[] args) {
        RuntimeException primaryException = null;
        try {
            throw new RuntimeException("Exception in try block");
        } catch (RuntimeException e) {
            primaryException = e;
            System.out.println("Caught exception: " + e.getMessage());
            throw new RuntimeException("Exception in catch block");
        } finally {
            System.out.println("Executing finally block");
            try {
                throw new RuntimeException("Exception in finally block");
            } catch (RuntimeException finallyException) {
                if (primaryException != null) {
                    primaryException.addSuppressed(finallyException);  // 将 finally 的异常附加到 catch 的异常上
                } else {
                    throw finallyException;  // 如果没有 catch 异常,直接抛出 finally 的异常
                }
            }
        }
    }
}

输出:

Caught exception: Exception in try block
Executing finally block
Exception in thread "main" java.lang.RuntimeException: Exception in catch block
    Suppressed: java.lang.RuntimeException: Exception in finally block

在这个例子中:

  • try 块抛出了异常,导致 catch 块处理异常。
  • catch 块再次抛出了新的异常,但在 finally 块中也抛出了异常。
  • 为了保留 catch 块中的异常,finally 块中的异常被附加为 catch 异常的“抑制异常”(suppressed exception)。因此,程序不会丢失 finally 块中的异常。

最终的输出显示了 catch 块的异常以及 finally 块中的抑制异常,解决了屏蔽问题。

总结

  1. finally 块抛出的异常会屏蔽 catch 块中的异常,这意味着最终抛出的异常会是 finally 中的异常,而不是 catch 中的异常。
  2. 如果需要保留 catchfinally 中的异常,可以通过 Java 7 引入的 addSuppressed 方法将 finally 块中的异常附加到 catch 块的异常上,避免丢失信息。
  3. 避免在 finally 块中抛出异常,除非有明确的需求,通常 finally 块应该专注于清理工作而非抛出新的异常。

10. **强烈不建议在finally中放置return 语句。

10.0.1.正常情况下 try块会缓存return 值,并在执行return 语句之前插入finally 块进行执行,故finally中的return 会执行,而方法就此return 了,try块中原本的return 语句不会被执行。
10.0.2.更重要的是try块中的return 会被缓存起来,然后执行 fiannly, 此时方法return基本类型 与 引用类型的情况是截然不同的,情况非常隐蔽,现在finally 块中很正常没有return,仅仅在finally 中修改了return 值, 其影响遵守值传递/引用传递原则,那么当方法return 为基本类型值的情况下,try 中被缓存的 return 值完全不会不会被finally块中的修改而影响;当方法return 为引用类型值的情况下,try 中被缓存的 return 值其实会被finally块中的修改而影响,遵循引用传递原则。而详情见如下示例分析
**
下面通过实验来看这几种情况的执行顺序到底是什么。

1、try中有return,finally中没有
public class TryCatchTest {

public static void main(String[] args) {
	System.out.println("test()函数返回:" + test());
}

private static int test(){
	int i = 0;
	try {
		System.out.println("Try block executing: " + ++i);
		return i;
	}catch (Exception e){
		System.out.println("Catch Error executing: " + ++i);
		return -1;
	}finally {
		System.out.println("finally executing: " + ++i);
	}
}

}
结果如下:

Try block executing: 1
finally executing: 2
test()函数返回:1

return的是对象时,看看在finally中改变对象属性,会不会影响try中的return结果。

public class TryCatchTest {
public int vaule = 0;

public static void main(String[] args) {
	System.out.println("test()函数返回:" + test().vaule);
}

private static TryCatchTest test(){
	TryCatchTest t = new TryCatchTest();
	try {
		t.vaule = 1;
		System.out.println("Try block executing: " + t.vaule);
		return t;
	}catch (Exception e){
		t.vaule = -1;
		System.out.println("Catch Error executing: " + t.vaule);
		return t;
	}finally {
		t.vaule = 3;
		System.out.println("finally executing: " + t.vaule);
	}
}

}
Try block executing: 1
finally executing: 3
test()函数返回:3

2、try和finally中均有return
private static int test(){
int i = 0;
try {
System.out.println("Try block executing: " + ++i);
return i;
}catch (Exception e){
System.out.println("Catch Error executing: " + ++i);
return -1;
}finally {
System.out.println("finally executing: " + ++i);
return i;
}
}
结果如下:

Try block executing: 1
finally executing: 2
test()函数返回:2

3、catch和finally中均有return
private static int test(){
int i = 0;
try {
System.out.println("Try block executing: " + ++i);
throw new Exception();
}catch (Exception e){
System.out.println("Catch Error executing: " + ++i);
return -1;
}finally {
System.out.println("finally executing: " + ++i);
return i;
}
}
输出结果:

Try block executing: 1
Catch Error executing: 2
finally executing: 3
test()函数返回:3

总结
1、不管有没有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算之后执行的;

对于含有return语句的情况,这里我们可以简单地总结如下:

try语句在返回前,将其他所有的操作执行完,保留好要返回的值,而后转入执行finally中的语句,而后分为以下三种情况:

情况一:如果finally中有return语句,则会将try中的return语句“覆盖”掉,直接执行finally中的return语句,得到返回值,这样便无法得到try之前保留好的返回值。

情况二:如果finally中没有return语句,也没有改变要返回值,则执行完finally中的语句后,会接着执行try中的return语句,返回之前保留的值。

情况三:如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况:

1)如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。
2)如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。

标签:Java,流程,程序执行,try,println,finally,catch,异常,out
From: https://www.cnblogs.com/gongchengship/p/18463147

相关文章

  • 初学Java基础Day18---面相对象之抽象类及其抽象方法,接口的使用及其面试题
    一,抽象类及其抽象方法的使用1.抽象方法:没有代码块,使用abstract修饰的方法,交给非抽象子类去实现注意:抽象方法必须在抽象类中。2.抽象类:使用abstract修饰3.代码实现://抽象类publicabstractclassPerson{//抽象方法publicabstractvoideat();}//在......
  • Java面试题———MyBatis篇
    目录1、Mybatis中#{}和${}的区别2、当实体类中的属性名和表中的字段名不一样,怎么办3、MyBatis动态SQL了解吗4、ResultType和ResultMap有什么区别1、Mybatis中#{}和${}的区别在Mybatis中#{}和${}都可以用于在sql语句中拼接参数,但是在使用方面有很多的区别1、处理方式......
  • Java面试题———Spring篇
    目录1、谈谈你对SpringIOC的理解2、Spring中有哪些依赖注入方式3、你用过哪些Spring注解4、SpringBean的作用域有几种5、Spring中的bean线程安全吗6、谈谈你对SpringAOP的理解7、AOP的代理有几种方式8、Spring的通知类型有哪些9、了解Spring的事务管理吗10、Spring......
  • 【java面经thinking】一
    目录类加载过程加载:连接初始化GC回收机制(垃圾回收)区域判断对象是否存活回收机制HashMap类加载器加载标识加载机制缓存自定义加载器:JVM内存结构常量池string设置成final按下网址发生类加载过程分为加载,连接和初始化的过程。加载:将.class文件的二进制字节......
  • Java语言中1.方法调用栈 2.栈帧 3.局部变量表 4.操作数栈 5.动态链接 6.方法的入参存
    在Java语言中,理解方法调用栈、栈帧、局部变量表、操作数栈等概念非常重要,它们与方法的执行和内存管理密切相关。下面是对这些概念的详细解释及它们之间的关系:1.方法调用栈(MethodCallStack)方法调用栈是每个线程维护的一块内存区域,用于存储线程执行时的栈帧(每个栈帧对应一次......
  • Seata的AT模式执行流程
    Seata的AT模式是Seata的默认模式。总共分为几步1.登记分支先给每个要参与的服务(分支事务)登记一下,记录下它们是谁,要做什么。2.执行操作每个服务登记好后就开始执行自己的任务,执行前后记下每个服务操作前后的数据状态,以防万一需要回滚。3.检查结果等所有服务都执行完了,TC会......
  • Seata的AT模式的执行流程
    Seata的AT模式:AT模式是Seata的默认模式,也是一种最终一致的分阶段事务模式,在一阶段,Seata拦截业务SQL,解析SQL语义,找到要更新的业务数据,并保存快照数据和行锁‌。简单来说就是看中结果,结果需要符合业务实际逻辑步骤准备undo-log(数据快照),简单说就是建个数据库用于备份数据,谁需要备份......
  • java项目--零钱通(OOP)
    参考上一篇,项目在主方法中运行的弊端,不易修改,也不能随用随调,结合面向对象的优势,因此有了以下代码的实现:分两个部分,一个类是完成零钱通的各个功能,另一个类用于调用该类的方法。代码如下(功能类展示):/*该类是完成零钱通的各个功能的类*/publicclassOOP{booleanloop......
  • java实现--零钱通
    项目说明:参照微信小程序的零钱通,可以完成收益入账,消费,查看明细,退出系统等功能。以下是功能模块的具体代码:importjava.text.SimpleDateFormat;importjava.util.Scanner;importjava.util.Date;publicclassfirst{publicstaticvoidmain(String[]args){......
  • Java 和 Python 的终极对决:毕业设计选谁才不掉头发?
    前言:老铁们,毕业设计来了,你准备好了么?听说最近有不少同学陷入了毕业设计选择恐慌,尤其是你手边摆着两把编程界的“大宝剑”:Java和Python,不知选哪把能少掉几根头发,甚至怀疑自己还能不能顺利毕业?其实,这个问题很简单,就好像你在超市里面对两袋薯片——“哎,这袋多一点,那袋口味更好,真......