如何从默认包导入类

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


我正在使用 Eclipse 3.5,并且我已经创建了一个包结构和默认包一起的项目。我在默认包中有一个类 -计算,java,我想在任何包中使用这个类(例如在 com.company.calc中)。当我尝试使用默认包中的类时,它会给我一个编译器错误。它无法识别默认包中的类。问题出在哪里?

Java-源代码

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

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

159165 次浏览

Unfortunately, you can't import a class without it being in a package. This is one of the reasons it's highly discouraged. What I would try is a sort of proxy -- put your code into a package which anything can use, but if you really need something in the default package, make that a very simple class which forwards calls to the class with the real code. Or, even simpler, just have it extend.

To give an example:

import my.packaged.DefaultClass;


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


public class DefaultClass {


// Code here


}

Classes in the default package cannot be imported by classes in packages. This is why you should not use the default package.

From the Java language spec:

It is a compile time error to import a type from the unnamed package.

You'll have to access the class via reflection or some other indirect method.

I can give you this suggestion, As far as know from my C and C++ Programming experience, Once, when I had the same kinda problem, I solved it by changing the dll written structure in ".C" File by changing the name of the function which implemented the JNI native functionality. for example, If you would like to add your program in the package "com.mypackage", You change the prototype of the JNI implementing ".C" File's function/method to this one:

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
}

Since I am new to delphi, I can not guarantee you but will say this finally, (I learned few things after googling about Delphi and JNI): Ask those people (If you are not the one) who provided the Delphi implementation of the native code to change the function names to something like this:

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;

But, A final advice: Although you (If you are the delphi programmer) or them will change the prototypes of these functions and recompile the dll file, once the dll file is compiled, you will not be able to change the package name of your "Java" file again & again. Because, this will again require you or them to change the prototypes of the functions in delphi with changed prefixes (e.g. JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

I think this solves the problem. Thanks and regards, Harshal Malshe

From some where I found below :-

In fact, you can.

Using reflections API you can access any class so far. At least I was able to :)

Class fooClass = Class.forName("FooBar");
Method fooMethod =
fooClass.getMethod("fooMethod", new Class[] { String.class });


String fooReturned =
(String) fooMethod.invoke(fooClass.newInstance(), "I did it");
  1. Create "root" package (folder) in your project, for example.

    package source; (.../path_to_project/source/)

  2. Move YourClass.class into a source folder. (.../path_to_project/source/YourClass.class)

  3. Import like this

    import source.YourClass;

  1. Create a new package.
  2. Move your files from the default package to the new one.

There is a workaround for your problem. You can use reflection to achieve it.

First, create an interface for your target class Calculatons :

package mypackage;


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


}

Next, make your target class implement that interface:

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

Finally, use reflection to create an instance of Calculations class and assign it to a variable of type CalculationsInterface :

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

Create a new package And then move the classes of default package in new package and use those classes