4

私の Swing プロジェクトでは、Java 5Java 6の両方をサポートする必要があります。カスタムを定義しJComponent( と呼びますPicture)、 に埋め込んだ後、DesignGridLayout マネージャーを使用するJScrollPaneに配置しました。JPanel

DesignGridLayout は、 swing-layoutオープン ソース ライブラリのおかげでベースライン配置をサポートします (Java 5 のベースライン サポートを実装し、新しい Java 6 ベースライン サポートとの互換性を提供します)。

Pictureのクラスは、正しいベースラインを定義できるようにオーバーライドします。 public int getBaseline(int width, int height)override」は完全に正しいわけではないことに注意してください。Java6 のメソッドをオーバーライドしますが、Java5 で定義します。

サンプル アプリを Java5 で実行すると、すべて問題ありません。定義したPictureベースラインが正しく使用されています。

ただし、Java6 を使用すると、Picture#getBaseline()メソッドが呼び出されません! もちろん、私の写真のベースラインの配置はひどいものです(中央揃え)。

Java6 ソースをチェックインした後、ビューポート コンポーネント (私のインスタンス)でが最初に呼び出さBasicScrollPaneUIれることがわかりました。そして、 が返された場合にのみ呼び出されます。getBaseline()getBaselineResizeBehavior()PicturegetBaseline()getBaselineResizeBehavior()Component.BaselineResizeBehavior.CONSTANT_ASCENT

今私の問題は、Java5に存在しない列挙型を返すため、Java5に実装できないgetBaselineResizeBehavior()Java6メソッドであることです。JComponentComponent.BaselineResizeBehavior

getBaselineResizeBehavior()だから私の質問は(最後に)次のとおりです。クラスをJava5環境でコンパイルして実行できるようにするには、どうすれば実装(またはシミュレート?)できますか?

4

4 に答える 4

2

getBaselineResizeBehavior()を実装(またはシミュレート)して、クラスをJava5環境でコンパイルおよび実行できるようにするにはどうすればよいですか?

Component.BaselineResizeBehaviour型が存在しないため、このメソッド宣言をJava5ライブラリでコンパイルすることはできません。

public Component.BaselineResizeBehavior getBaselineResizeBehavior()

Java 6を使用してコンパイルする必要があります。1.5ターゲットにコンパイルする場合でも、クラスはJava 5で実行できますが、存在しないタイプ/メソッドを適切に処理するように注意する必要があります。これらのケースに遭遇したら、テストを追加します。チェックインする前に、開発者がJava5でコードを実行しようとしていることを確認してください。

たとえば、このクラスは...

public class MyPanel extends javax.swing.JPanel {

    public java.awt.Component.BaselineResizeBehavior getBaselineResizeBehavior() {
        return java.awt.Component.BaselineResizeBehavior.OTHER;
    }

    public static void main(String[] args) {
        new MyPanel();
        System.out.println("OK");
    }

}

... javac JDKコンパイラを使用して、次のようにコンパイルおよび実行できます。

X:\fallback>javac -version
javac 1.6.0_05

X:\fallback>javac -target 1.5 MyPanel.java

X:\fallback>"C:\Program Files\Java\jre1.5.0_10\bin\java.exe" -cp . MyPanel
OK

人気のあるIDEはすべて、古いクラスバージョンを生成するためのオプションを提供します。コードパスについて決定する必要がある場合は、リフレクションを使用して、実行時にメソッド/タイプの存在をテストできます。

ターゲットの設定に失敗すると、次のようなエラーが発生します。

Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version n
umber in .class file
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
于 2009-01-05T10:13:55.210 に答える
2

getBaselineResizeBehaviour()を実装したPictureのサブクラス(おそらくPictureJava6と呼ばれる)を作成し、Pictureのインスタンスを作成するときに次のようにします。

public Component pictureFactory() {
    if(javaVersion > "1.6") {
        return new PictureJava6();
    } else {
        return new Picture();
    }
}
于 2009-01-05T11:10:54.563 に答える
0

リフレクションを使用して、CONSTANT_ASCENT の戻り値を名前で取得しようとすることができます。反映できない場合は J5、それ以外の場合は J6 です。これにより、明示的な依存関係が回避され、J5 へのコンパイルが可能になります。

フォール。ダイアログモダリティでこれを行う例です:

try {
    Field  fld=Class.forName("java.awt.Dialog$ModalExclusionType").getField("TOOLKIT_EXCLUDE");
    Method mth=getClass().getMethod("setModalExclusionType",new Class[]{fld.getType()});
    mth.invoke(this,new Object[]{fld.get(null)});
    }
catch(Throwable thr) {
    log.errorln("Unable to configure window to be unaffected by modal dialogs - dialogs may need to be closed to operate help.");
    log.errorln("Use Java 6 or later to avoid modal dialogs conflicting with the help system.");
    log.errorln("Exception: "+thr);
    }

更新: 最初に J5 コードをコメントアウトしてコードを投稿しました。J5コードがJ6では機能しないことを暗示して問題を混乱させることに気付いたので、私はそれを変更しました-そうです。

于 2009-01-05T00:40:49.547 に答える
0

仮想関数とオーバーロードを解決する際に、戻り値の型はメソッド シグネチャの一部として扱われないと思います。オブジェクトを返すように「オーバーライド」メソッドを定義し、最初の回答ごとに返された Enum を反映できる可能性があります。J5でコンパイルしているため、コンパイル時の競合にはなりませんが、JVMはオーバーライドするメソッドを選択する必要があります...実行時例外がスローされる可能性がありますそれでも、試してみる価値はあります。

例えば:

public Object getBaselineResizeBehavior() {
    Object ret;
    // reflect out the return value
    return ret;
    }  

これは、J6 でない限り呼び出されないため、エラー処理は純粋にデバッグ用に System.out にすることができます。したがって、正しくコーディングされたリフレクションは、呼び出された場合に常に機能するはずです。

もちろん、何が起こっているのかを明確にするために、このメソッドにコメントします。

于 2009-01-05T02:19:32.857 に答える