10

Eclipse ワークスペースの java.lang パッケージにカスタム クラス String を作成しようとしました。最初は、同じパッケージに同じクラスを作成できないのではないかと疑っていましたが、まったく驚いたことに、同じパッケージにクラス (文字列) を作成できました。つまり、java.lang です。

今、私は混乱し
てい
ます。
3) このタイプの Java クラスの作成が Java で許可されている場合、何が使用されるでしょうか。

4

3 に答える 3

9

java.lang パッケージに新しいクラスを作成できます。禁止されていたら、Oracle の開発者はどうやって Java を開発できたのでしょうか? 彼らは私たちと同じ javac を使用していると確信しています。

ただし、java.lang.ClassLoader (クラスローダーが拡張する) では許可されないため、ロードすることはできません。ロードされるすべてのクラスがこのチェックを通過します。

...
        if ((name != null) && name.startsWith("java.")) {
            throw new SecurityException
                ("Prohibited package name: " + name.substring(0, name.lastIndexOf('.')));
        }
...

だからあなたは次のようなものになります

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:649)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:785)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at Test1.main(Test1.java:11)

あなたのような既存のクラスをシャドーするクラスに関してはjava.lang.String、System ClassLoader (デフォルトのもの) が「親が最初」の戦略を使用するため、それらをロードすることはできません。そのため、rt.jar の String.class を自分のバージョンに置き換える必要があります。または、パスをブートストラップ クラス ローダーの検索パスに付加する java オプションを使用してオーバーライドします。-Xbootclasspath/p:だからあなたはできる

1)実際の String.java コンテンツを String.java にコピーペーストします

2) メソッドを変更します。

public static String valueOf(double d) {
    return "Hi";
}

String.javaをコンパイルします

3) テストクラスを作成する

public class Test1 {

    public static void main(String[] args) throws Exception {
        System.out.println(String.valueOf(1.0d));
    }
}

4)として実行します

java -Xbootclasspath/p:path_to_your_classes Test1

そしてあなたは見るでしょう

Hi
于 2013-01-15T07:14:08.740 に答える
4

これは、クラスのシャドーイングと呼ばれます。

1.) Java クラスは静的にリンクされていませんが、クラスのロード時にリンクされているため可能です。

2.) 許可されていない場合、クラス全体のロードを達成するのははるかに困難になります。次に、たとえば、特定の Java バージョンに対してプロジェクトをビルドする必要もあります。Java クラスはバージョンごとに変更される可能性があるためです。これは、保守可能なアプローチにはなりません。

3.) osgi はこれを利用して、同じバンドルの異なるバージョンをロードできるようにします。もう 1 つの一般的な使用例は、フレームワーク内のバグのあるクラスを置き換えることです。この場合、他に回避策はありません。ただし、エラーのデバッグが困難な場合があるため、この手法は慎重に使用する必要があります。

ただし、java.* パッケージ内のクラスをシャドウすることは許可されていないことに注意してください。Java セキュリティ サンドボックスが壊れてしまうためです。したがって、実行時に問題が発生します。

于 2013-01-15T07:07:03.733 に答える
2

はい、 java.langという名前のパッケージと、 Stringという名前のクラスを作成できます。

ただし、String クラスを実行することはできません。

1)それが可能な理由:コンパイラはクラスを正常にコンパイルします。

2)それが許可されている場合の理由:パッケージとクラスに有効な名前があるため、コンパイラーは文句を言いません。

3)このタイプの Java クラスの作成が Java で許可されている場合、どのような用途がありますか :しかし、この String クラスの使用はあまりありません。ブートストラップ クラス ローダーは、sun の java.lang パッケージからクラスをロードします。したがって、カスタム String クラスはロードされないため、実行中に失敗します。

ブートストラップ クラス ローダーは JVM 実装の一部であり、Java API (java.lang.String を含む) のクラスをロードします。また、ロードされるクラスごとに、JVM は、ブートストラップまたはユーザー定義のいずれのクラス ローダーがクラスをロードしたかを追跡します。そのため、カスタム String クラスをロードしようとすると、String クラスが既にロードされているため失敗します。

于 2013-01-15T07:06:07.177 に答える