105

可能重复:如何访问默认包中的 java 类?


我正在使用 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(真的 - 我不能)。这就是为什么我把我的课程放在默认包中。

4

9 回答 9

92

来自Java 语言规范

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

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

于 2010-02-03T16:02:05.903 回答
55

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

于 2010-02-03T15:59:55.797 回答
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);
于 2016-09-29T09:38:22.667 回答
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”文件一次又一次。因为,这将再次要求您或他们使用更改的前缀更改 delphi 中函数的原型(例如 JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

我认为这可以解决问题。谢谢和问候, Harshal Malshe

于 2010-03-14T10:02:03.747 回答
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");
于 2014-04-09T12:01:23.957 回答
3

不幸的是,如果一个类不在包中,您就无法导入它。这也是它非常不受欢迎的原因之一。我会尝试一种代理——将您的代码放入一个任何东西都可以使用的包中,但如果您真的需要默认包中的某些东西,请将其设为一个非常简单的类,该类将调用转发到带有真实代码的类。或者,更简单,只是让它扩展。

举个例子:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}
于 2010-02-03T15:58:43.740 回答
0

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

于 2018-03-31T12:04:07.973 回答
-1
  1. 创建一个新包。
  2. 将文件从默认包移动到新包。
于 2015-05-09T18:54:55.750 回答
-3
  1. 例如,在您的项目中创建“根”包(文件夹)。

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

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

  3. 像这样导入

    导入源.YourClass;

于 2014-05-12T10:58:28.323 回答