Как импортировать класс из пакета по умолчанию

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/… после создания этих вопросов.
Michał Ziober 03
Конечно, важным моментом в этом вопросе является то, что класс и его код должны находиться в пакете по умолчанию . На данный момент любой ответ, кроме использования API отражения (на самом деле, излишество для чего-то такого простого) , не является решением. Поразительно, как Java пытается получить свой пирог (отговорить пакет по умолчанию) и съесть его (сделайте JNI настолько запутанным, что большинство из нас в конечном итоге использует библиотеки DLL, требующие пакета по умолчанию).
ADTC
Причина кажется исторической, но иногда кусается. например, `` T.java: import static a.Foo. *; class T {Bar bar = new Bar (); } a / Foo.java: пакет a; public class Foo {public static final class Bar {}} `` Вышеупомянутое прекрасно компилируется, однако, если Foo помещается в пакет по умолчанию, он не работает. Таким образом, я не могу статически импортировать Foo. *, Чтобы использовать сокращенную строку Bar вместо Foo.Bar.
Kedar Mhaswade

Ответы:

87

Из спецификации языка Java :

Импорт типа из безымянного пакета является ошибкой времени компиляции.

Вам нужно будет получить доступ к классу через отражение или другой косвенный метод.

Макдауэлл
источник
1
Вау, я вообще не знаю java. Это было большим подспорьем. Думаю, мне придется переместить мой класс в пакет ...
Анхопп
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 ++, однажды, когда у меня была такая же проблема, я решил ее, изменив структуру, записанную 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, я не могу гарантировать вам, но скажу это наконец (я узнал несколько вещей после поиска в Google о 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)

Думаю, это решает проблему. С уважением и уважением, Харшал Малше

Харшал Мальше
источник
Это хорошо для всех, кто пытается использовать собственные библиотеки в своих проектах.
Randnum 01
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

Создайте новый пакет, а затем переместите классы пакета по умолчанию в новый пакет и используйте эти классы

Хушбу Кашьяп
источник
Добро пожаловать в StackOverflow! Возможно, вы можете добавить больше деталей, чтобы лучше объяснить наиболее важные части вашего ответа. Прочтите, как написать хороший ответ? Чтобы получить больше информации. Кроме того, как только вы наберете больше репутации, вы сможете опубликовать это как комментарий, а не как ответ, что было бы более подходящим.
Francesco B.
-1
  1. Создайте новый пакет.
  2. Переместите файлы из пакета по умолчанию в новый.
Евгений
источник
-3
  1. Создайте, например, «корневой» пакет (папку) в вашем проекте.

    исходный код пакета; (... / путь_к_проекту / источник /)

  2. Переместите YourClass.class в исходную папку. (... / путь_к_проекту / источник / YourClass.class)

  3. Импортировать как это

    источник импорта.YourClass;

Андрей
источник
1
плохой ответ, если он этого хочет, ему это нужно по умолчанию, а не в каком-то нестандартном пакете
Enerccio