异常处理机制】异常处理中throws和throw的区别?_第2页回答

2021-11-11 09:39发布

19条回答
帅帅马
2楼 · 2021-11-14 10:33

throws:用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁。

  用在方法声明后面,跟的是异常类名

  可以跟多个异常类名,用逗号隔开

  表示抛出异常,由该方法的调用者来处理

  throws表示出现异常的一种可能性,并不一定会发生这些异常

throw:则是用来抛出一个具体的异常类型。

  用在方法体内,跟的是异常对象名

  只能抛出一个异常对象名

  表示抛出异常,由方法体内的语句处理

  throw则是抛出了异常,执行throw则一定抛出了某种异常  

分别介绍

throws在方法后边声明异常,其实就是自己不想对异常做出任何的处理,告诉别人自己可能出现的异常,交给别人处理,然别人处理

package com.xinkaipu.Exception;

class Math{

    public int div(int i,int j) throws Exception{

        int t=i/j;

        return t;

    }

}



public class ThrowsDemo {

    public static void main(String args[]) throws Exception{

        Math m=new Math();

   }

}

throw:就是自己处理一个异常,有两种方式要么是自己捕获异常try...catch代码块,要么是抛出一个异常(throws 异常)

package com.xinkaipu.Exception;

 

public class TestThrow

{

    public static void main(String[] args) 

    {

        try

        {

            //调用带throws声明的方法,必须显式捕获该异常

            //否则,必须在main方法中再次声明抛出

            throwChecked(-3);            

        }

        catch (Exception e)

        {

            System.out.println(e.getMessage());

        }

        //调用抛出Runtime异常的方法既可以显式捕获该异常,

        //也可不理会该异常

        throwRuntime(3);

    }

    public static void throwChecked(int a)throws Exception

    {

        if (a > 0)

        {

            //自行抛出Exception异常

            //该代码必须处于try块里,或处于带throws声明的方法中

            throw new Exception("a的值大于0,不符合要求");

        }

    }

    public static void throwRuntime(int a)

    {

        if (a > 0)

        {

            //自行抛出RuntimeException异常,既可以显式捕获该异常

            //也可完全不理会该异常,把该异常交给该方法调用者处理

            throw new RuntimeException("a的值大于0,不符合要求");

        }

    }

}



20200921文 - 做更棒的自己!
3楼 · 2021-11-14 10:44

当然,你需要明白异常在Java中式以一个对象来看待。
并且所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,但是一般情况下Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行。
直接进入正题哈:
1.用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常。

1.1 throw是语句抛出一个异常。
语法:throw (异常对象);
throw e;

1.2 throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
语法:[(修饰符)](返回值类型)(方法名)([参数列表])[throws(异常类)]{......}
public void doA(int a) throws Exception1,Exception3{......}

举例:

throws E1,E2,E3只是告诉程序这个方法可能会抛出这些异常,方法的调用者可能要处理这些异常,而这些异常E1,E2,E3可能是该函数体产生的。
throw则是明确了这个地方要抛出这个异常。

如: void doA(int a) throws IOException,{
try{
......

}catch(Exception1 e){
throw e;
}catch(Exception2 e){
System.out.println("出错了!");
}
if(a!=b)
throw new Exception3("自定义异常");
}

代码块中可能会产生3个异常,(Exception1,Exception2,Exception3)。
如果产生Exception1异常,则捕获之后再抛出,由该方法的调用者去处理。

果产生Exception2异常,则该方法自己处理了(即System.out.println("出错了!");)。所以该方法就不会再向外抛出
Exception2异常了,void doA() throws Exception1,Exception3
里面的Exception2也就不用写了。
而Exception3异常是该方法的某段逻辑出错,程序员自己做了处理,在该段逻辑错误的情况下抛出异常Exception3,则该方法的调用者也要处理此异常。

throw语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throws语句用在方法声明后面,表示再抛出异常,由该方法的调用者来处理。

throws主要是声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个异常。
throw是具体向外抛异常的动作,所以它是抛出一个异常实例。

throws说明你有那个可能,倾向。
throw的话,那就是你把那个倾向变成真实的了。

同时:
1、throws出现在方法函数头;而throw出现在函数体。
2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常。
3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

LERRR
4楼 · 2021-11-15 08:50

1)作用不同: throw用于程序员自行产生并抛出异常; throws用于声明在该方法内抛出了异常

2) 使用的位置不同: throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表的后面,不能单独使用。


回答: 2021-12-17 09:23

1)作用不同: throw用于程序员自行产生并抛出异常; throws用于声明在该方法内抛出了异常

2) 使用的位置不同: throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表的后面,不能单独使用。


visonx
5楼 · 2021-11-15 08:52

catch语句可以有多个,分别处理不同类的例外。Java运行时系统从上到下分别对每个catch语句处理的例外类型进行检测,直到找到类型相匹配的catch语句为止。这里,类型匹配指catch所处理的例外类型与生成的例外对象的类型完全一致或者是它的父类,因此,catch语句的排列顺序应该是从特殊到一般

回答: 2021-12-17 10:24

1)作用不同: throw用于程序员自行产生并抛出异常; throws用于声明在该方法内抛出了异常

2) 使用的位置不同: throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表的后面,不能单独使用。

3)内容不同: throw抛出一个异常对象,且只能是一个; throws后面跟异常类,而且可以有多个。


1、作用不同:throw用于程序员自行产出并抛出异常;throws用于声明在该方法内抛出了异常 2、使用的位置不同:throw位于方法体内部,可以作为单独语句使用;throws必须跟在方法参数列表的后面,不能单独使用

樱田妮妮NiNi
7楼 · 2021-11-16 17:19

异常处理中throws和throw的区别:

       1、作用不同:throw用于程序员自行产出并抛出异常;throws用于声明在该方法内抛出了异常

       2、使用的位置不同:throw位于方法体内部,可以作为单独语句使用;throws必须跟在方法参数列表的后面,不能单独使用。

       3、内容不同:throw抛出一个异常对象,且只能是一个;throws后面跟异常类,而且可以有多个

我的网名不再改
8楼 · 2021-11-17 11:35

首先:

1.用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常。

1.1   throw是语句抛出一个异常。
语法:throw (异常对象);
         throw e;

1.2   throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
语法:[(修饰符)](返回值类型)(方法名)([参数列表])[throws(异常类)]{......}
            public void doA(int a) throws Exception1,Exception3{......}

 

2.接着我们来看一段代码:

main函数:

  public static void main(String[] args) {        try {
            exceptionTest("d:\\a","d:\\c");
        }catch (Exception e){
            System.out.println(e);
        }

    }

 



异常测试函数:
public static void exceptionTest(String inputFileName,String outputFileName)  {    try {        int a=1/0;
    }catch (Exception e){
        System.out.println("出现数字运算异常");        throw  e;
    }
}


这是一段最普通的异常处理代码,程序输出结果为

在exceptionTest函数中,我们的try代码块中出现了分母为0的情况,此时jvm会抛出一个ArithmeticExcepiton的异常,接着我们在catch语句找那个使用Exception这个父类(默认能捕获所有异常)捕获到了异常,此时我们打印出了出现数字运算异常,并将此异常对象抛出,给上层方法体接受处理,即主函数处理,主函数捕捉到exceptionTest抛出的异常后,将改异常打印出来。

 

3.throws关键字是声明在方法体上的,表示该方法可能会抛出某种类型的异常(但并非一定抛出)

我们修改exceptionTest的代码,修改如下:

主函数(不变)

//以文件流的方式读写文件public static void main(String[] args) {    try {
        exceptionTest("d:\\a","d:\\c");
    }catch (Exception e){
        System.out.println(e);
    }

}

 


异常测试函数
 public static void exceptionTest(String inputFileName,String outputFileName)   {        try {            //文件异常测试
            BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream("d:\\a.txt"));            //            String className="com.demo";
            Class clazz=Class.forName(className);
        }catch (Exception e){
            System.out.println("出现文件读取异常和类名获取异常");            throw  e;
        }
    }


这个时候我们运行程序,编译器会报错,直接编译不通过,如果我们把exceptionTest中的throw e给注释了
即修改exceptionTest代码为:
public static void exceptionTest(String inputFileName,String outputFileName)   {        try {            //文件异常测试
            BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream("d:\\a.txt"));            //            String className="com.demo";
            Class clazz=Class.forName(className);
        }catch (Exception e){
            System.out.println("出现文件读取异常和类名获取异常");//            throw  e;        }
    }

 

此时再运行程序,编译通过,程序输出为:

未注释之前编译器直接报错,编译器的提示是:

Unhandled exceptions: java.io.FileNotFoundException, java.lang.ClassNotFoundException

那是因为我们的方法中有未处理的两个异常,我们可以捕捉他们,然后输出信息到控制台

但是此时我们要用throw e将此异常抛出给上层方法体,必须在方法的声明中用throws FileNotFoundException,ClassNotFoundException来处理

即修改exceptionTest的的代码为:

  public static void exceptionTest(String inputFileName,String outputFileName) throws FileNotFoundException, ClassNotFoundException {        try {            //文件异常测试
            BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream("d:\\a.txt"));            //            String className="com.demo";
            Class clazz=Class.forName(className);
        }catch (Exception e){
            System.out.println("出现文件读取异常和类名获取异常");            throw  e;
        }
    }

必须要在方法体中声明这两个异常,是因为我们在try的代码块中调用的两个方法中声明了这两个异常,

首先是

new FileInputStream("d:\\a.txt")),
我们看下这个类的源码:
 * @param      name   the system-dependent file name.     * @exception  FileNotFoundException  if the file does not exist,     *                   is a directory rather than a regular file,     *                   or for some other reason cannot be opened for
     *                   reading.     * @exception  SecurityException      if a security manager exists and its     *               checkRead method denies read access     *               to the file.     * @see        java.lang.SecurityManager#checkRead(java.lang.String)     */    public FileInputStream(String name) throws FileNotFoundException {        this(name != null ? new File(name) : null);
    }

新建一个文件输出流中,构造函数的方法体上已经用throws声明了FileNotFoundException这个异常

Class.forName(className)这个方法中,我们再看Class.forName这个静态函数的源码:

  * {@code X} to be initialized.     *
     * @param      className   the fully qualified name of the desired class.     * @return     the {@code Class} object for the class with the     *             specified name.     * @exception LinkageError if the linkage fails     * @exception ExceptionInInitializerError if the initialization provoked     *            by this method fails     * @exception ClassNotFoundException if the class cannot be located     */
    @CallerSensitive    public static Class forName(String className)                throws ClassNotFoundException {
        Class caller = Reflection.getCallerClass();        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

改方法上也用throws声明了ClassNotFoundException这个异常,

所以外层方法体调用他们的时候必须要对他们进行try-catch,

同样我们在testExcepiton函数中捕捉完后,想将改异常抛出,则必须在方法体中声明异常的类型,

然后再交由上层方法体处理。

 

总结:

throws只是在方法上的声明,表示函数可能会抛出改异常

throw是抛出实际的异常,如果在try的代码块中使用可能会抛出异常的函数,catch捕获后想要再次抛出给上层方法体,则需要再方法体上再次声明。

 


fayyuyang
9楼 · 2021-12-03 09:45

在Java异常处理时,会有throws和throw两种关键字。二者的区别在于:

 throw代表动作,表示抛出一个异常的动作;throws代表一种状态,代表方法可能有异常抛出。throw用在方法实现中,而throws用在方法声明中throw只能用于抛出一种异常,而throws可以抛出多个异常


相关问题推荐

  • 回答 11

    基本执行过程如下:1)程序首先执行可能发生异常的try语句块。2)如果try语句没有出现异常则执行完后跳至finally语句块执行;3)如果try语句出现异常,则中断执行并根据发生的异常类型跳至相应的catch语句块执行处理。4)catch语句块可以有多个,分别捕获不同类型...

  • 回答 16

    异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译...

  • 回答 10

    Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获...

  • 回答 5

    OutOf MemoryError这种错误可以细分为多种不同的错误,每种错误都有自身的原因和解决办法,如下所示:java.lang.OutOfMemoryError: Java heap space 错误原因:此OOM是由于JVM中heap的最大值不满足需要。 解决方法:1) 调高heap的最大值,即-Xmx的值调大。...

  • 回答 6

    问题的根本原因是工程中某个jar包的版本(jar包编译时的所用的jdk版本)高于工程build path中jdk的版本,这个是不兼容的! 编程中遇到此异常Unsupported major.minor version 52.0(根据版本号,这里可以为其他数值,52是1.8jdk jar包与 1.8以下低版本jdk不匹配)...

没有解决我的问题,去提问