web-dev-qa-db-ja.com

デフォルトパッケージからクラスをインポートする方法

重複の可能性: default-packageのJavaクラスにアクセスする方法?


Eclipse 3.5を使用しており、デフォルトのパッケージとともにいくつかのパッケージ構造を持つプロジェクトを作成しました。デフォルトパッケージにクラスが1つあります-Calculations.Javaそして、そのクラスを任意のパッケージ(たとえば、com.company.calc)。デフォルトパッケージにあるクラスを使用しようとすると、コンパイラエラーが発生します。デフォルトパッケージのクラスを認識できません。問題はどこにありますか?

Calculations.Java-ソースコード

public class Calculations {
    native public int Calculate(int contextId);
    native public double GetProgress(int contextId);
    static  {
        System.loadLibrary("Calc");
    }
}

クラスを他のパッケージに入れることはできません。このクラスには、Delphiで実装されているいくつかのネイティブメソッドがあります。そのクラスをいずれかのフォルダーに配置した場合、そのDLLを変更する必要がありますが、これは避けたいものです(本当に-できません)。それが、クラスをデフォルトパッケージに入れる理由です。

86
Michał Ziober

Java言語仕様 から:

名前のないパッケージから型をインポートすると、コンパイル時エラーになります。

リフレクションまたは他の間接メソッドを介してクラスにアクセスする必要があります。

79
McDowell

デフォルトパッケージ内のクラスは、パッケージ内のクラスによってインポートできません。このため、デフォルトパッケージを使用しないでください。

42
matt b

問題の回避策があります。リフレクションを使用してそれを達成できます。

まず、インターフェイスを作成ターゲットクラスCalculatonsに対して:

package mypackage;

public interface CalculationsInterface {  
    int Calculate(int contextId);  
    double GetProgress(int contextId);  

}

次に、ターゲットクラスを作成しますそのインターフェイスを実装します

public class Calculations implements mypackage.CalculationsInterface {
    @Override
    native public int Calculate(int contextId);
    @Override
    native public double GetProgress(int contextId);
    static  {
        System.loadLibrary("Calc");
    }
}

最後に、se reflectionCalculationsクラスのインスタンスを作成し、それをCalculationsInterface型の変数に割り当てます:

Class<?> calcClass = Class.forName("Calculations");
CalculationsInterface api = (CalculationsInterface)calcClass.newInstance();
// Use it 
double res = api.GetProgress(10);
7

私はあなたにこの提案をすることができます、私のCとC++プログラミングの経験から知っている限り、一度、同じ種類の問題が発生したときに、「。 JNIネイティブ機能を実装した関数。たとえば、プログラムをパッケージ「com.mypackage」に追加する場合、「。C」ファイルの関数/メソッドを実装するJNIのプロトタイプを次のように変更します。

JNIEXPORT jint JNICALL
Java_com_mypackage_Calculations_Calculate(JNIEnv *env, jobject obj, jint contextId)
{
   //code goes here
}

JNIEXPORT jdouble JNICALL
Java_com_mypackage_Calculations_GetProgress(JNIEnv *env, jobject obj, jint contextId)
{
  //code goes here
}

私はデルファイに慣れていないので、あなたに保証することはできませんが、これを最終的に言うでしょう(DelphiとJNIについてグーグルで学んだ後、いくつかのことを学びました):ネイティブのDelphi実装を提供した人(あなたがいない場合)関数名を次のように変更するコード:

function Java_com_mypackage_Calculations_Calculate(PEnv: PJNIEnv; Obj: JObject; contextId: JInt):JInt; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
var
//Any variables you might be interested in
begin
  //Some code goes here
end;



function Java_com_mypackage_Calculations_GetProgress(PEnv: PJNIEnv; Obj: JObject; contextId: JInt):JDouble; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
var
//Any variables you might be interested in
begin
//Some code goes here
end;

しかし、最後のアドバイス:あなた(デルファイプログラマの場合)または彼らはこれらの関数のプロトタイプを変更してdllファイルを再コンパイルしますが、dllファイルがコンパイルされると、パッケージ名を変更することはできません「Java」ファイルを何度も何度も。なぜなら、変更されたプレフィックスを使用して、デルファイ内の関数のプロトタイプを変更する必要があるためです(例:Java_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

これで問題が解決すると思います。ありがとう、敬意を表します

4
Harshal Malshe

私が以下で見つけたところから:-

実際、できます。

リフレクションAPIを使用すると、これまでのどのクラスにもアクセスできます。少なくとも私はできました:)

Class fooClass = Class.forName("FooBar");
Method fooMethod =
    fooClass.getMethod("fooMethod", new Class[] { String.class });

String fooReturned =
    (String) fooMethod.invoke(fooClass.newInstance(), "I did it");
4
Adnan Ghaffar

残念ながら、パッケージに含まれていないクラスはインポートできません。これは非常にがっかりする理由の1つです。私がしようとしているのは一種のプロキシです-あなたのコードを何でも使用できるパッケージに入れますが、本当にデフォルトのパッケージに何かが必要な場合は、実際のコードでクラスに呼び出しを転送する非常に単純なクラスにします。または、さらに簡単に、拡張するだけです。

例を挙げると:

import my.packaged.DefaultClass;

public class MyDefaultClass extends DefaultClass {}
package my.packaged.DefaultClass;

public class DefaultClass {

   // Code here

}
1
Jon