如何从默认包导入类

Mic*_*ber 90 java java-native-interface native-methods default-package

可能重复:如何访问default-package中的java-classes?


我正在使用Eclipse 3.5,我创建了一个包含一些包结构和默认包的项目.我在默认包中有一个类 - Calculations.java,我想在任何一个包中使用该类(例如in com.company.calc).当我尝试使用默认包中的类时,它给了我一个编译器错误.它无法识别默认包中的类.问题出在哪儿?

Calculations.java - 源代码

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

我不能把我的班级放在任何其他包中.这个类有一些在Delphi中实现的本机方法.如果我将该类放在任何文件夹中,我将不得不对我想要避免的DLL进行更改(实际上 - 我不能).这就是为什么我把我的类放在默认包中.

McD*_*ell 80

Java语言规范:

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

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


mat*_*t b 44

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


Moh*_*eid 7

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

首先,为目标类创建一个接口Calculatons:

package mypackage;

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

}
Run Code Online (Sandbox Code Playgroud)

接下来,让目标类实现该接口:

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

最后,使用反射创建Calculations类的实例并将其分配给类型的变量CalculationsInterface:

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


小智 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
}
Run Code Online (Sandbox Code Playgroud)

由于我是 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;
Run Code Online (Sandbox Code Playgroud)

但是,最后一个建议:虽然你(如果你是delphi程序员)或者他们会改变这些函数的原型并重新编译dll文件,但是一旦dll文件被编译,你将无法更改你的包名“Java”文件一次又一次。因为,这将再次要求您或他们使用更改的前缀(例如 JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)更改 delphi 中函数的原型

我认为这可以解决问题。谢谢和问候,哈沙尔·马尔什


Adn*_*far 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");
Run Code Online (Sandbox Code Playgroud)

  • 似乎反射是唯一的出路。我有一个 JNI 库,它在除默认包之外的任何包中都拒绝工作。我没有构建 DLL,所以我无法重建它。我所做的任何事情都必须使用 Java。谢谢你节省了一天:) (2认同)