Cara mengimpor kelas dari paket default

98

Kemungkinan Duplikat: Bagaimana cara mengakses kelas-java di paket-default?


Saya menggunakan Eclipse 3.5 dan saya telah membuat proyek dengan beberapa struktur paket bersama dengan paket default. Saya memiliki satu kelas dalam paket default - Calculations.java dan saya ingin menggunakan kelas itu di salah satu paket (misalnya di com.company.calc). Ketika saya mencoba untuk menggunakan kelas yang ada dalam paket default, itu memberi saya kesalahan kompiler. Itu tidak dapat mengenali kelas dalam paket default. Dimana masalahnya?

Calculations.java - kode sumber

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

Saya tidak dapat memasukkan kelas saya ke dalam paket lain. Kelas ini memiliki beberapa metode asli yang diimplementasikan di Delphi. Jika saya meletakkan kelas itu di salah satu folder, saya harus membuat perubahan pada DLL yang ingin saya hindari (sungguh - saya tidak bisa). Itulah mengapa saya menempatkan kelas saya dalam paket default.

Michał Ziober
sumber
1
Saya menemukan tautan ini: stackoverflow.com/questions/283816/… setelah membuat pertanyaan ini.
Michał Ziober
Tentu saja, bagian penting dari pertanyaan ini adalah bahwa kelas dan kodenya harus ada dalam paket default . Sampai sekarang, jawaban lain selain menggunakan refleksi API (benar-benar, berlebihan untuk sesuatu yang sederhana ini) adalah tidak solusi. Ini membingungkan bagaimana Java mencoba memiliki kuenya (mencegah paket default) dan memakannya juga (membuat JNI begitu berbelit-belit, kebanyakan dari kita akhirnya menggunakan DLL yang membutuhkan paket default).
ADTC
Alasannya tampak bersejarah, tetapi terkadang menggigit. misal "` `T.java: import static a.Foo. *; kelas T {Bar bar = bar baru (); } a / Foo.java: paket a; public class Foo {public static final class Bar {}} `` Kompilasi di atas baik-baik saja, namun, jika Foo ditempatkan dalam paket default, itu tidak berfungsi. Oleh karena itu, saya tidak dapat mengimpor Foo. * Secara statis untuk menggunakan steno Bar, bukan Foo.Bar.
Kedar Mhaswade

Jawaban:

87

Dari spesifikasi bahasa Java :

Ini adalah kesalahan waktu kompilasi untuk mengimpor tipe dari paket tanpa nama.

Anda harus mengakses kelas melalui refleksi atau metode tidak langsung lainnya.

McDowell
sumber
1
Wah saya benar-benar tidak tahu java sama sekali. Itu sangat membantu. Kurasa aku harus memindahkan kelasku ke dalam satu paket ...
anhoppe
46

Kelas dalam paket default tidak dapat diimpor oleh kelas dalam paket. Inilah mengapa Anda sebaiknya tidak menggunakan paket default.

matt b
sumber
Ini harus menjadi jawaban yang diterima default, karena ini yang paling berguna. Terima kasih.
Neoraptor
8

Ada solusi untuk masalah Anda. Anda dapat menggunakan refleksi untuk mencapainya.

Pertama, buat antarmuka untuk kelas target Anda Calculatons:

package mypackage;

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

}

Selanjutnya, buat kelas target Anda mengimplementasikan antarmuka itu :

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

Terakhir, gunakan refleksi untuk membuat instance Calculationskelas dan menugaskannya ke variabel tipe CalculationsInterface:

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

Saya dapat memberikan saran ini, Sejauh yang saya tahu dari pengalaman Pemrograman C dan C ++ saya, Suatu ketika, ketika saya memiliki masalah yang sama, saya menyelesaikannya dengan mengubah struktur tertulis dll di ".C" File dengan mengubah nama fungsi yang mengimplementasikan fungsionalitas asli JNI. misalnya, Jika Anda ingin menambahkan program Anda ke dalam paket "com.mypackage", Anda mengubah prototipe JNI yang mengimplementasikan fungsi / metode File ".C" menjadi yang ini:

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
}

Karena saya baru mengenal delphi, saya tidak dapat menjamin Anda tetapi akan mengatakan ini akhirnya, (Saya belajar beberapa hal setelah googling tentang Delphi dan JNI): Tanyakan orang-orang itu (Jika Anda bukan orangnya) yang menyediakan implementasi Delphi dari native kode untuk mengubah nama fungsi menjadi seperti ini:

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;

Tapi, saran terakhir: Meskipun Anda (Jika Anda adalah programmer delphi) atau mereka akan mengubah prototipe dari fungsi-fungsi ini dan mengkompilasi ulang file dll, setelah file dll dikompilasi, Anda tidak akan dapat mengubah nama paket Anda. File "Java" lagi & lagi. Karena, ini sekali lagi akan meminta Anda atau mereka untuk mengubah prototipe dari fungsi di delphi dengan prefiks yang diubah (mis. JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Saya pikir ini menyelesaikan masalah. Terima kasih dan salam, Harshal Malshe

Harshal Malshe
sumber
Ini bagus untuk siapa saja yang mencoba menggunakan Perpustakaan Asli dalam proyek mereka.
Randnum
5

Dari beberapa tempat saya temukan di bawah ini: -

Nyatanya, Anda bisa.

Dengan menggunakan API refleksi, Anda sejauh ini dapat mengakses kelas apa pun. Setidaknya saya bisa :)

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

String fooReturned =
    (String) fooMethod.invoke(fooClass.newInstance(), "I did it");
Adnan Ghaffar
sumber
2
Sepertinya refleksi adalah satu-satunya cara untuk pergi. Saya memiliki pustaka JNI yang menolak untuk bekerja ketika berada dalam paket apa pun selain paket default. Saya tidak membangun DLL jadi saya tidak dapat membangunnya kembali. Apa pun yang saya lakukan harus di Jawa. Terima kasih telah menyelamatkan hari ini :)
ADTC
3

Sayangnya, Anda tidak dapat mengimpor kelas tanpa berada di dalam paket. Inilah salah satu alasan mengapa sangat tidak disarankan. Apa yang akan saya coba adalah semacam proxy - masukkan kode Anda ke dalam paket yang dapat digunakan apa saja, tetapi jika Anda benar-benar membutuhkan sesuatu dalam paket default, buatlah itu menjadi kelas yang sangat sederhana yang meneruskan panggilan ke kelas dengan kode yang sebenarnya. Atau, yang lebih sederhana, perpanjang saja.

Sebagai contoh:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}
Jon
sumber
1

Buat paket baru Dan kemudian pindahkan kelas paket default dalam paket baru dan gunakan kelas tersebut

Khushboo Kashyap
sumber
Selamat datang di StackOverflow! Mungkin Anda dapat menambahkan lebih banyak detail, untuk menjelaskan dengan lebih baik bagian terpenting dari jawaban Anda. Sudah membaca Bagaimana cara menulis jawaban yang baik? untuk informasi lebih lanjut. Selain itu, setelah Anda mendapatkan lebih banyak reputasi, Anda akan dapat memposting ini sebagai komentar daripada sebagai jawaban, yang akan lebih sesuai.
Francesco B.
-1
  1. Buat paket baru.
  2. Pindahkan file Anda dari paket default ke yang baru.
Evgueni
sumber
-3
  1. Buat paket "root" (folder) di proyek Anda, misalnya.

    sumber paket; (... / path_to_project / source /)

  2. Pindahkan YourClass.class ke dalam folder sumber. (... / path_to_project / source / YourClass.class)

  3. Impor seperti ini

    import source.YourClass;

Andrey
sumber
1
jawaban buruk, jika dia menginginkan ini, dia membutuhkannya secara default, bukan dalam beberapa paket khusus
Enerccio