如何从默认包导入类

时间:2010-02-03 15:54:26

标签: java java-native-interface native-methods default-package

  

可能重复:How to access java-classes in the default-package?


我正在使用Eclipse 3.5,我创建了一个包含一些包结构和默认包的项目。我在默认包中有一个类 - 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进行更改(实际上 - 我不能)。这就是我将我的课程放在默认包中的原因。

9 个答案:

答案 0 :(得分:78)

来自Java language spec

  

从未命名的包导入类型是编译时错误。

您必须通过反射或其他间接方法访问该类。

答案 1 :(得分:41)

默认包中的类不能由包中的类导入。这就是您不应该使用默认包的原因。

答案 2 :(得分:6)

您的问题有一个解决方法。您可以使用反射来实现它。

首先,为目标类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);

答案 3 :(得分:4)

我可以给你这个建议, 据我所知的C和C ++编程经验, 有一次,当我遇到同样的问题时,我通过改变实现JNI本机功能的函数的名称来改变“.C”文件中的dll编写结构来解决它。  例如,如果您想在程序包“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”文件的名称&amp;再次。 因为,这将再次要求您或他们使用更改的前缀更改delphi中函数的原型(例如JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

我认为这解决了这个问题。 感谢致敬, Harshal Malshe

答案 4 :(得分:4)

从我在下面找到的地方: -

事实上,你可以。

使用Reflections 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");

答案 5 :(得分:1)

不幸的是,如果没有它在一个包中,你就无法导入它。这是非常沮丧的原因之一。我会尝试的是一种代理 - 将您的代码放入任何可以使用的包中,但如果您确实需要默认包中的某些内容,请将其设置为一个非常简单的类,它使用实际代码将调用转发给类。或者,更简单,只需延长它。

举个例子:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}

答案 6 :(得分:-1)

创建一个新包 然后在新包中移动默认包的类并使用这些类

答案 7 :(得分:-2)

  1. 创建&#34; root&#34;例如,项目中的包(文件夹)。

    包源; (... / path_to_project /源极/)

  2. 将YourClass.class移动到源文件夹中。 (... / path_to_project /源极/ YourClass.class)

  3. 像这样导入

    import source.YourClass;

答案 8 :(得分:-2)

  1. 创建一个新包。
  2. 将文件从默认包移动到新包。