Як імпортувати клас із пакета за замовчуванням


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


Звичайно, важливим бітом цього питання є те, що клас та його код повинні бути в пакеті за замовчуванням . На сьогодні будь-яка відповідь, окрім використання 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 поміщений у пакет за замовчуванням, він не працює. Таким чином, я не можу статично імпортувати Foo. * Так, щоб використовувати строкову панель замість Foo.Bar.
Кедар Массваде

Відповіді:


87

З специфікації мови Java :

Це помилка часу компіляції для імпорту типу з безіменного пакету.

Вам доведеться отримати доступ до класу за допомогою відображення або якогось іншого непрямого методу.


1
Нічого, я справді не знаю Java. Це була чудова допомога. Напевно, мені доведеться перенести свій клас у пакет ...
anhoppe

46

Класи в пакеті за замовчуванням не можна імпортувати класами в пакетах. Ось чому не слід використовувати пакет за замовчуванням.


Це має бути прийнята за замовчуванням відповідь, оскільки вона є найбільш корисною. Дякую.
Неораптор

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", ви змінюєте прототип, що реалізує ".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)

Я думаю, що це вирішує проблему. Спасибі і з повагою, Харшал Малше


Це добре для тих, хто намагається використовувати Рідні бібліотеки у своїх проектах.
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

Створіть новий пакет А потім перемістіть класи за замовчуванням у новий пакет і використовуйте ці класи


Ласкаво просимо до StackOverflow! Можливо, ви можете додати більше деталей, щоб краще пояснити найважливіші частини своєї відповіді. Прочитайте, як мені написати гарну відповідь? для отримання додаткової інформації. Крім того, як тільки ви отримаєте більше репутації, ви зможете розмістити це як коментар, а не відповідь, що було б більш доречно.
Франческо Б.

-1
  1. Створіть новий пакет.
  2. Перемістіть ваші файли з пакета за замовчуванням до нового.

-3
  1. Наприклад, створіть "root" пакет (папку) у своєму проекті.

    джерело пакету; (... / path_to_project / source /)

  2. Перемістіть YourClass.class у папку з джерелом. (... / path_to_project / source / YourClass.class)

  3. Імпортуйте так

    джерело імпорту.YourClass;


1
погана відповідь, якщо він хоче цього, він знадобиться йому за замовчуванням, а не в якомусь спеціальному пакеті
Enerccio
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.