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


98

重複の可能性:デフォルトパッケージのjava-classesにアクセスする方法


私は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に変更を加える必要があります(実際には-できません)。そのため、クラスをデフォルトパッケージに配置しました。


1
この質問を作成した後、次のリンクを見つけました:stackoverflow.com/questions/283816/…
のMichałZiober


もちろん、この質問の重要な部分は、クラスそのコードがデフォルトのパッケージに含まれている必要があることです。現在のところ、リフレクションAPIを使用する以外の答え(実際には、この単純なものに対する過剰)は解決策ではありません。Javaがどのようにしてケーキ(デフォルトパッケージを推奨しない)を作り、それを食べようとするのか(JNIを複雑にして、ほとんどの場合、デフォルトパッケージを必要とするDLLを使用することになります)は気が遠くなるほどで​​す。
ADTC、2015

その理由は歴史的なもののようですが、時々噛み付きます。例 `` T.java:import static a.Foo。*; クラスT {Bar bar = new Bar(); } a / Foo.java:パッケージa; public class Foo {public static final class Bar {}} `` `上記は正常にコンパイルされますが、Fooがデフォルトパッケージに配置されている場合は機能しません。したがって、Foo.Barの代わりに短縮形のBarを使用するために、Foo。*を静的にインポートすることはできません。
Kedar Mhaswade、2016

回答:


87

Java言語仕様

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

リフレクションまたはその他の間接的な方法でクラスにアクセスする必要があります。


1
うわ、私は本当にjavaをまったく知りません。それは大きな助けでした。クラスをパッケージに移動する必要があると思います...
anhoppe

46

デフォルトパッケージ内のクラスは、パッケージ内のクラスによってインポートできません。これが、デフォルトのパッケージを使用してはならない理由です。


これが最も役立つので、これがデフォルトの受け入れられた回答であるべきです。ありがとうございました。
Neoraptor

8

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

まず、ターゲットクラスのインターフェイス作成します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");
    }
}

最後に、リフレクション使用しCalculationsクラスのインスタンスを作成し、それをタイプの変数に割り当てますCalculationsInterface

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

5

私はあなたにこの提案を与えることができます、私のCおよびC ++プログラミングの経験から知る限り、同じような問題があったときに、「。C」ファイルのdll記述構造を変更して解決しました。 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を初めて使用するので、保証はできませんが、最後にこう言います(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;

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

これで問題は解決すると思います。よろしくお願いいたします。HarshalMalshe


これは、プロジェクトでネイティブライブラリを使用しようとするすべてのユーザーに適しています。
ランダム

5

私が以下で見つけたいくつかから:-

実際、それは可能です。

リフレクション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");

2
反射が唯一の方法のようです。私は、デフォルト以外のパッケージで動作することを単に拒否するJNIライブラリを持っています。DLLをビルドしなかったため、再ビルドできません。私が行うことはすべてJavaで行う必要があります。日を保存していただきありがとうございます:)
ADTC

3

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

例を挙げましょう:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}

1

新しいパッケージを作成してから、デフォルトパッケージのクラスを新しいパッケージに移動し、それらのクラスを使用します


StackOverflowへようこそ!おそらく、詳細を追加して、回答の最も重要な部分をよりよく説明することができます。良い答えを書くにどうすればいいですか?詳細については。また、評判が高まると、これを回答ではなくコメントとして投稿できるようになります。
Francesco B.

-1
  1. 新しいパッケージを作成します。
  2. ファイルをデフォルトのパッケージから新しいパッケージに移動します。

-3
  1. たとえば、プロジェクトに「ルート」パッケージ(フォルダー)を作成します。

    パッケージソース; (... / path_to_project / source /)

  2. YourClass.classをソースフォルダに移動します。(... / path_to_project / source / YourClass.class)

  3. このようにインポート

    import source.YourClass;


1
不正解です。これが必要な場合は、カスタムパッケージではなくデフォルトで必要です
Enerccio
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.