結論
次のように記述すれば良い。openConnectionについては必要である場合のみ記述する。
public class Main {
private static final MyURLStreamHandler HANDLER = new MyURLStreamHandler();
private static class MyURLStreamHandler extends URLStreamHandler {
@Override
protected URLConnection openConnection(URL u) {
throw new UnsupportedOperationException("MyURLStreamHandler#openConnection(URL) is an unsupported operation.");
}
}
public static void main(String[] args) throws Exception {
URL url = new URL(null, "unknown-protocol://user:pass@example.com.:888/path", HANDLER);
System.out.println(url);
}
}
jshell> class MyURLStreamHandler extends URLStreamHandler {
...> @Override
...> protected URLConnection openConnection(URL u) {
...> throw new UnsupportedOperationException("MyURLStreamHandler#openConnection(URL) is an unsupported operation.");
...> }
...> }
| 次を作成しました: クラス MyURLStreamHandler
jshell> MyURLStreamHandler HANDLER = new MyURLStreamHandler();
HANDLER ==> MyURLStreamHandler@12edcd21
jshell> URL url = new URL(null, "unknown-protocol://user:pass@example.com.:888/path", HANDLER);
url ==> unknown-protocol://user:pass@example.com.:888/path背景
Javaのアプリケーションで、URLの文字列からprotocolやauthorityを取り出したいことがある。この用途にはjava.net.URLクラスの利用が考えられる。
しかし、java.net.URLの new URL(spec) コンストラクタは特殊なプロトコルのURLには利用できない。これは、 sun.net.www.protocol.<protocol_name>.Handler.java クラスが解決できないとExceptionが発生するように実装されているため。
逆に言えば、特殊なプロトコルの場合は上記のパッケージにHandler.javaを作れば良いことになる。
問題点
以下の食い違いからsun.net.www.protocol.<protocol_name>.Handler.java作成できない場合がある。
- URL上のプロトコルの箇所は
-(ハイフン)の利用が許可されている - Javaのパッケージ名は
-(ハイフン)の利用が禁止されている
例えば、次のURLは正しいURLであるが、対応するパッケージを作ることができない。
unknown-protocol://user:pass@example.com.:888/path
解決策
独自にhandlerを作成し、 new URL(context, spec, handler) コンストラクタを利用する。具体的には記事冒頭の結論を参照してほしい。

きっとなにかの やくにたつから…