5

のソースでjavax.swing.text.DefaultCaret.Handler.insertUpdate(DocumentEvent)、次の行を見つけました (1685 行目から):

if (e instanceof AbstractDocument.UndoRedoDocumentEvent) {
    setDot(offset + length);
    return;
}

しかし、私がこれを試すと:

package javax.swing.text;

public class Foo {
    public static void main(String[] args) {
        Object o = new Object();
        if (o instanceof AbstractDocument.UndoRedoDocumentEvent) {
            System.out.println("yay");
        } else {
            System.out.println("aww");
        }
    }
}

それは与えるでしょう:

Exception in thread "main" java.lang.IllegalAccessError: tried to access class javax.swing.text.AbstractDocument$UndoRedoDocumentEvent from class javax.swing.text.Foo
    at javax.swing.text.Foo.main(Foo.java:6)

なぜ私はinstanceofそのクラスに反対することはできませんが、DefaultCaret.Handlerできるのですか?

Java バージョン 1.6.0_20 の使用

$ java -version
java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.7) (6b20-1.9.7-0ubuntu1~10.04.1)
OpenJDK Client VM (build 19.0-b09, mixed mode, sharing)

アップデート:

回答に基づいて、次のことを試しました。

ファイルFoo.java:

package javax.swing.text;

public class Foo {
    public static void main(String[] args) {
        Object o = new Object();
        if (o instanceof Outer.Inner) {
            System.out.println("yay");
        } else {
            System.out.println("aww");
        }
    }
}

ファイルOuter.java:

package javax.swing.text;

public class Outer {
    class Inner {
    }
}

これは正常に機能し、期待どおりに「aww」を出力します。

両方のファイルがパッケージに含まれていることに注意してくださいjavax.swing.text。また、最初の質問でFoo.javaすでにパッケージに含まれていたことにも注意してください。javax.swing.text

私が知る限り、パッケージは「密封」されていません。rt.jar(パッケージを含むもの)のマニフェストにjavax.swing.text「封印」が含まれていませんでした。コマンドPackage.getPackage("javax.swing.text").isSealed()は false を返します。

したがって、パッケージの他のクラスはできますがinstance of、自分の内部クラスに対してはできますが、に対してはできません。AbstractDocument.UndoRedoDocumentEvent

これはなぜですか?

4

2 に答える 2

3

UndoRedoDocumentパッケージで保護されDefaultCaret.Handlerているように見えUndoRedoDocument、同じパッケージに含まれています(javax.swing.text私の記憶が正しければ)。

于 2011-04-09T17:55:39.337 に答える
1

最初のアイデアは、パッケージ javax.swing.text が封印されており、それに新しいクラスを追加することは許可されていないということです。独自のパッケージでも同じことが起こりますか?


編集:私のコメントから:

少し遅れましたが、あなたのクラスとスイングクラスが異なるクラスローダーによってロードされ、異なるクラスローダーからロードされたパッケージは、同じ名前であっても同じパッケージとは見なされないことが理由である可能性があると思います.

Name.class.getClassLoader()、 またはで使用されているクラス ローダを確認できますobject.getClass().getClassLoader()。これらを印刷します。(swing クラスの ClassLoader は である可能性があります。これはnull、(VM によって実装され、クラスがロードされる前に作成された) ブートストラップ クラス ローダーを表しますClass)ClassLoaderアプリケーションのクラス ローダーは、おそらく別のものです。

独自のクラス ローダーでクラスを作成するには、URLClassLoader を使用します。これには、アプリケーションのクラス ローダーを親として持つ必要がありますが (クラスが相互にアクセスできるようにするため)、別の URL を使用します (通常のクラス パスにないクラスをロードするなど)。

次のようなことができます。

  • Outerクラスをアプリケーションのクラスパスに入れます。
  • 次のように (同じクラスパスに) メイン クラスを作成します。

    class Main {
        public static void main(String[] ignored) throws Exception {
            URL url = new URL("file:///path/to/other/dir");
            ClassLoader cl = new URLClassLoader(url, Main.class.getClassLoader());
            Class<?> testClass = cl.loadClass("package.Test");
            testClass.getMethod("test").invoke(null);
        }
    }
    
  • 次のようなテスト クラスを Outer と同じパッケージに作成しますが、メイン クラスの URL をルートとします。

    class Test {
       public static void test() {
          Object o = new Object();
          if (o instanceof Outer.Inner) {
              System.out.println("yay");
          } else {
              System.out.println("aww");
         }
       }
    }
    

私の理論が正しければ、これは同じタイプの例外を与えるはずです。(私は試していません。)

于 2011-04-09T17:56:15.670 に答える