Java URL对象 - 新的java.net.URL()

4

我是一个初学者,想尝试运行一些简单的Java程序。 这是我的代码:

import java.net.*;
import java.io.*;

class example1 {

    public static void main(String args[]){

    try{
        URL hp = new URL("http://www.java2s.com");
        System.out.println("it all worked?");
    }catch (MalformedURLException e){
        System.err.println("New URL failed");
        System.err.println("exception thrown: " + e.getMessage());
    }

    System.out.println(hp.getProtocol());

    }
}

Java编译器出现了“cannot find symbol: hp”错误,这表明url对象hp没有被以下代码行创建:

URL hp = new URL("http://www.java2s.com");

但是,catch语句不应该报告错误吗?

我尝试编译没有try-catch块的代码,但是会出现一个错误,说“未报告异常MalformedURLException; 必须捕获或声明抛出”。

如果我删除引用hp的最后一行,程序就可以编译和运行,但只显示“it all worked?”。

我相信这里有一个简单的解释,但我对Java的知识不多。谢谢。

2个回答

5

当你在try-catch块内定义hp时,它的可见性仅限于try块内。因此,在try-catch块外的print语句中会出现编译错误。

请按照以下方式在try块开始之前定义hp

URL hp = null;
try{
        hp = new URL("http://www.java2s.com");
        System.out.println("it all worked?");
        System.out.println(hp.getProtocol());
    }catch (MalformedURLException e){
        System.err.println("New URL failed");
        System.err.println("exception thrown: " + e.getMessage());
    }

为了更好地理解,请阅读本节中的14.4.2 Scope of Local Variable Declarations部分,链接在这里
另外,为了更安全和正确地编写代码,您应该使用throw子句来抛出捕获到的MalformedURLException
catch (MalformedURLException e){
            System.err.println("New URL failed");
            System.err.println("exception thrown: " + e.getMessage());
            throw new MalformedURLException("Invalid URL!");
        }

你还需要更新主函数来抛出这个异常:- public static void main(String[] args) throws MalformedURLException 如果你不这样做,在 URL 格式错误的情况下,你的代码将继续运行!

你的解决方案(第一个代码块)存在一个小问题,即当 MalformedURLException 被抛出时,“hp” 将为 null,并且最终的 println 语句将抛出 NullPointerException。(你在评论中提到了这一点:“如果 URL 格式错误,你的代码将继续执行”)。另一种选择是将该 println 语句简单地移动到 try 块中。 - Tim
@Tim - 你看完整段代码了吗?我在第二部分添加了throw子句(因此它永远不会到达print语句,因为它被抛出了)。当然,print语句可以移动到try块内,但这是OP的选择。 - CoolBeans

5
其他答案已经给你一些有用的建议来避免这个错误。但是我想尝试解释一下,为什么你对这个错误的理解是有误的。
这一行代码:
URL hp = new URL("http://www.java2s.com");

这段代码一次性完成了两个任务。它声明了一个变量(编译器通常称之为“符号”),名为hp,可以指向URL的实例;并创建了一个URL实例,并使hp指向它。

你将错误解释为“url对象hp未被创建”。首先,hp不是一个对象——它最多是一个对对象的引用,当然也可以是null,在这种情况下它是一个对空的引用。但是,在其声明的范围内,符号hp存在,无论是否将对象引用分配给它。

如果对象创建失败了——即语句中的new URL ...部分失败了——那么最可能会抛出异常,正如您所期望的那样。但是,即使由于一些晦涩的原因而导致创建失败但没有抛出异常,那么hp很可能是null,在这种情况下,对变量hp进行有效的解引用尝试将导致NullPointerException

所有这些只是为了说明您收到的错误与hp是否被赋值无关,仅表明在您尝试使用它的范围内没有声明hp

问题在于try块创建了它自己的范围,因此在其中声明的变量无法在块外部访问。如果你的try块中的第一行只是URL hp;,那么你会收到完全相同的错误。正如其他答案所示,解决这个问题的方法是在try块之外声明hp,以使后续的引用有效。(将最后一行移动到try块中也可以,但是限制该块的内容仅包括需要特定错误处理的语句是有意义的。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接