如何从默认包中导入类


98

可能的重复:如何在默认包中访问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进行更改(真的-我不能)。这就是为什么我将班级放在默认包中的原因。


1
创建此问题后,我找到了此链接:stackoverflow.com/questions/283816/…
米哈尔Ziober


当然,这个问题的最重要的一点是类它的代码必须是在默认包中。到目前为止,除了使用反射API之外,其他任何答案(实际上,对于这种简单的方法来说都算是过大都不是解决方案。Java试图如何获得蛋糕(不鼓励使用默认程序包)并吃掉它(令人难以置信的JNI,我们大多数人最终都使用需要默认程序包的DLL),这真是令人难以置信。
ADTC

原因似乎是历史性的,但有时会咬人。例如```T.java:import static a.Foo。*; T类{Bar bar = new Bar(); } a / Foo.java:封装a;public class Foo {public static final class Bar {}}} 因此,我不能静态导入Foo。*以便使用速记Bar代替Foo.Bar。
Kedar Mhaswade

Answers:


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”文件一次又一次。因为,这将再次需要您或他们更改具有更改的前缀的delphi中的函数原型(例如JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

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


这对于尝试在项目中使用本机库的任何人都是有益的。
Randnum

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

不幸的是,没有包,就不能导入类。这是强烈不鼓励的原因之一。我要尝试的是一种代理-将您的代码放入可以使用的任何程序包中,但是如果您确实需要默认程序包中的某些内容,请创建一个非常简单的类,该类将调用与真实代码一起转发给该类。或者,甚至更简单,只需对其进行扩展即可。

举个例子:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}


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

-3
  1. 例如,在您的项目中创建“根”包(文件夹)。

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

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

  3. 像这样导入

    导入source.YourClass;


1
错误的答案,如果他想要的话,则默认情况下需要使用它,而不是在某些自定义程序包中使用
Enerccio
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.