为什么 java.net.URI 构造函数不为字母字符串抛出 URISyntaxException?

Why doesn't the java.net.URI constructor throw a URISyntaxException for alphabetic strings?

为什么当我传入 "abc" 这样的字符串时,java.net.URI 构造函数没有抛出异常?我已将它隔离到下面的测试用例中。

import static org.junit.Assert.assertEquals;

import java.net.URI;
import java.net.URISyntaxException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;


@RunWith(JUnit4.class)
public class HelloWorldTest {
    @Test(expected=URISyntaxException.class)
    public void testAlphabeticStringWithUriConstructor()
        throws URISyntaxException {
        URI uri = new URI("abc");
    }
}

编译后 运行 生成以下内容:

$ java -cp .:lib/junit-4.12.jar:lib/hamcrest-core-1.3.jar org.junit.runner.JUnitCore HelloWorldTest
JUnit version 4.12
.E
Time: 0.005
There was 1 failure:
1) testAlphabeticStringWithUriConstructor(HelloWorldTest)
java.lang.AssertionError: Expected exception: java.net.URISyntaxException
    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:32)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
    at org.junit.runner.JUnitCore.main(JUnitCore.java:36)

FAILURES!!!
Tests run: 1,  Failures: 1

根据javadocs for URI, the constructor java.net.URI should throw a URISyntaxException "if the given string violates RFC 2396, as augmented by the above deviations" with some minor deviations included. And the URI constructor does catch other malformed URIs. But for some reason it seems to be okay with this one. Is it possible that "abc" is a valid URI? RFC 2396 - Uniform Resource Identifier (URI): Generic Syntax没有明确说明是不是。

最终,这是一个问题,因为我想在尝试发出 HTTP 请求之前验证用户提供的字符串是否为 URI。

嗯,"abc" 是一个完全有效的 URI 字符串。假设我想引用当前目录中名为 abc 的文件。这就是方法!

我猜你真的想使用 URL,在这种情况下会抛出以下异常:

Exception in thread "main" java.net.MalformedURLException: no protocol: abc
    at java.net.URL.<init>(URL.java:586)
    at java.net.URL.<init>(URL.java:483)
    at java.net.URL.<init>(URL.java:432)
    at offlineAnalysis.Main.main(Main.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

URI 与 URL 不同,但我不打算解释它已经有答案:What is the difference between a URI, a URL and a URN?