Ответ 1
Это ошибка времени компиляции для импорта типа из неназванного пакета.
Вам нужно будет получить доступ к классу через отражение или какой-либо другой косвенный метод.
Возможный дубликат: Как получить доступ к 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, которую я хочу избежать (на самом деле - я не могу). Поэтому я поместил свой класс в пакет по умолчанию.
Это ошибка времени компиляции для импорта типа из неназванного пакета.
Вам нужно будет получить доступ к классу через отражение или какой-либо другой косвенный метод.
Классы в пакете по умолчанию не могут быть импортированы классами в пакетах. Вот почему вы не должны использовать пакет по умолчанию.
Существует решение для вашей проблемы. Вы можете использовать отражение, чтобы достичь этого.
Сначала создайте интерфейс для вашего целевого класса 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);
Я могу дать вам это предложение, Насколько известно из моего опыта программирования на C и С++, Однажды, когда у меня была одна и та же проблема, я решил ее, изменив структуру данных dll в файле ".C", изменив имя функции, которая реализовала встроенную функцию JNI. например, Если вы хотите добавить свою программу в пакет "com.mypackage", Вы изменяете прототип JNI, реализующего ".C" функцию/метод файла:
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)
Я думаю, что это решает проблему. Спасибо и приветствую, Харшал Мальше
От некоторых, где я нашел ниже: -
На самом деле вы можете.
Используя 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");
К сожалению, вы не можете импортировать класс, не входя в пакет. Это одна из причин, по которым он сильно обескуражен. То, что я хотел бы попробовать, - это своего рода прокси-сервер - поместите ваш код в пакет, который может использовать любой, но если вам действительно нужно что-то в пакете по умолчанию, сделайте это очень простым классом, который переадресовывает вызовы классу с помощью реального кода. Или, еще проще, просто расширьте его.
Чтобы привести пример:
import my.packaged.DefaultClass;
public class MyDefaultClass extends DefaultClass {}
package my.packaged.DefaultClass;
public class DefaultClass {
// Code here
}
Создайте новый пакет. Затем переместите классы пакета по умолчанию в новый пакет и используйте эти классы.
Создайте, например, "корневой" пакет (папку) в вашем проекте.
источник пакета; (.../path_to_project/источник/)
Переместите YourClass.class в исходную папку. (.../path_to_project/источник/YourClass.class)
Импортируйте как это
import source.YourClass;