2010-02-03 55 views
74

thể trùng lặp: How to access java-classes in the default-package?Làm thế nào để import class từ gói mặc định


Tôi đang sử dụng Eclipse 3.5 và tôi đã tạo ra một dự án với một số cấu trúc gói cùng với các gói mặc định. Tôi có một lớp trong gói mặc định - Calculations.java và tôi muốn sử dụng lớp đó trong bất kỳ gói nào (ví dụ: com.company.calc). Khi tôi cố gắng sử dụng lớp đó trong gói mặc định, nó cho tôi một lỗi trình biên dịch. Nó không thể nhận ra lớp trong gói mặc định. Vấn đề ở đâu?

Calculations.java - mã nguồn

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

tôi không thể đặt lớp học của tôi trong bất kỳ gói khác. Lớp này có một số phương thức gốc được triển khai trong Delphi. Nếu tôi đặt lớp đó vào bất kỳ thư mục nào, tôi sẽ phải thực hiện các thay đổi cho DLL mà tôi muốn tránh (thực sự - tôi không thể). Đó là lý do tại sao tôi đưa lớp của mình vào gói mặc định.

+1

Tôi tìm thấy liên kết này: http://stackoverflow.com/questions/283816/how-to-access-java-classes-in-the-default-package sau khi tạo câu hỏi này. –

+0

có thể trùng lặp của [Cú pháp để nhập một lớp trong một gói mặc định trong Java là gì?] (Http://stackoverflow.com/questions/2030148/whats-the-syntax-to-import-a-class-in-a -default-package-in-java) – Pops

+0

Tất nhiên, bit quan trọng của câu hỏi này là lớp ** và ** mã của nó ** phải nằm trong gói mặc định **. Hiện tại, bất kỳ câu trả lời nào khác ngoài việc sử dụng API phản chiếu * (thực sự, quá mức cần thiết cho một cái gì đó đơn giản này) * là ** không ** một giải pháp. Đó là tâm-boggling như thế nào Java cố gắng để có bánh của nó (ngăn cản gói mặc định) và ăn nó quá (làm cho JNI rất phức tạp, hầu hết chúng ta kết thúc bằng cách sử dụng DLL yêu cầu gói mặc định). – ADTC

Trả lời

70

Từ Java language spec:

Đó là một lỗi thời gian biên dịch để nhập khẩu một loại từ gói giấu tên.

Bạn sẽ phải truy cập lớp học thông qua phản ánh hoặc một số phương pháp gián tiếp khác.

+1

Tôi sử dụng sự phản chiếu để giải quyết vấn đề của mình. –

+0

Wow Tôi thực sự không biết java chút nào. Đó là một trợ giúp lớn. Đoán tôi sẽ phải chuyển lớp học của tôi thành một gói ... – anhoppe

1

Thật không may, bạn không thể nhập một lớp mà không có nó trong gói. Đây là một trong những lý do khiến nó không được khuyến khích. Những gì tôi sẽ thử là một loại proxy - đặt mã của bạn vào một gói mà bất kỳ thứ gì có thể sử dụng, nhưng nếu bạn thực sự cần một thứ gì đó trong gói mặc định, hãy tạo một lớp rất đơn giản để chuyển tiếp cuộc gọi đến lớp bằng mã thực. Hoặc, thậm chí đơn giản hơn, chỉ cần mở rộng.

Để đưa ra một ví dụ:

import my.packaged.DefaultClass; 

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

public class DefaultClass { 

    // Code here 

}
37

Lớp học trong gói mặc định không thể được nhập khẩu bởi các lớp trong gói. Đây là lý do tại sao bạn không nên sử dụng gói mặc định.

4

Tôi có thể cung cấp cho bạn đề xuất này, Theo như được biết từ kinh nghiệm Lập trình C và C++, Một lần, khi tôi gặp vấn đề tương tự, tôi đã giải quyết nó bằng cách thay đổi cấu trúc viết dll trong ".C" bằng cách thay đổi tên của hàm thực hiện chức năng gốc JNI. ví dụ: Nếu bạn muốn thêm chương trình của mình vào gói "com.mypackage", Bạn thay đổi nguyên mẫu của việc triển khai JNI ".C" File của chức năng/phương pháp này một:

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 
} 

Kể từ khi tôi mới đến Delphi, tôi không thể đảm bảo với bạn nhưng sẽ nói điều này cuối cùng, (Tôi đã học được vài điều sau khi googling về Delphi và JNI): Hỏi những người (Nếu bạn không phải là một trong những) người cung cấp việc thực hiện Delphi đa mã gốc để thay đổi tên hàm một cái gì đó như thế này:

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; 

Nhưng, một lời khuyên cuối cùng: Mặc dù bạn (Nếu bạn là delphi lập trình viên) hoặc chúng sẽ thay đổi nguyên mẫu của các hàm này và biên dịch lại tệp dll, khi tệp dll được biên dịch, bạn sẽ không thể thay đổi tên gói của tệp "Java" của bạn lại một lần nữa &. Bởi vì, điều này một lần nữa sẽ yêu cầu bạn hoặc họ thay đổi các nguyên mẫu của các chức năng trong delphi với tiền tố thay đổi (ví dụ JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Tôi nghĩ rằng đây giải quyết vấn đề. Trân trọng cảm ơn, Harshal Malshe

+0

Điều này là tốt cho bất cứ ai đang cố gắng sử dụng Thư viện bản địa trong các dự án của họ. – Randnum

+0

yep. hoạt động như sự quyến rũ! – nikk

3

Từ một số nơi tôi tìm thấy dưới đây: -

Trong thực tế, bạn có thể.

Sử dụng API phản xạ bạn có thể truy cập bất kỳ lớp nào từ trước tới nay. Ít nhất tôi đã có thể :)

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

String fooReturned = 
    (String) fooMethod.invoke(fooClass.newInstance(), "I did it"); 
+0

Nó làm việc cho tôi một cách hoàn hảo !, cảm ơn! – Israelm

+1

Có vẻ như phản ánh là cách duy nhất để đi. Tôi có một thư viện JNI đơn giản từ chối làm việc khi trong bất kỳ gói nào khác ngoài gói mặc định. Tôi đã không xây dựng các DLL vì vậy tôi không thể xây dựng lại nó. Bất cứ điều gì tôi cần phải có trong Java. Cảm ơn bạn đã tiết kiệm trong ngày :) – ADTC

-1
  1. Tạo "root" gói (thư mục) trong dự án của bạn, ví dụ.

    nguồn gói; (.../path_to_project/source /)

  2. Di chuyển YourClass.class vào thư mục nguồn. (.../path_to_project/nguồn/YourClass.class)

  3. nhập như thế này

    source.YourClass nhập khẩu;

+1

câu trả lời xấu, nếu anh ta muốn điều này, anh ấy cần nó trong mặc định, không phải trong một số gói tùy chỉnh – Enerccio

-1
  1. Tạo gói mới.
  2. Chuyển tệp của bạn từ gói mặc định sang gói mới.
5

Có một giải pháp cho sự cố của bạn. Bạn có thể sử dụng sự phản chiếu để đạt được nó.

Đầu tiên, tạo một giao diện cho lớp mục tiêu của bạn Calculatons:

package mypackage; 

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

} 

Tiếp theo, hãy lớp mục tiêu của bạn thực hiện giao diện:

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

Cuối cùng, sử dụng phản ánh để tạo ra một thể hiện của Calculations lớp và gán nó cho một biến loại CalculationsInterface:

Class<?> calcClass = Class.forName("Calculations"); 
CalculationsInterface api = (CalculationsInterface)calcClass.newInstance(); 
// Use it 
double res = api.GetProgress(10); 
Các vấn đề liên quan