기본 패키지에서 클래스를 가져 오는 방법


98

중복 가능성 : 기본 패키지의 자바 클래스에 액세스하는 방법은 무엇입니까?


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 2010


물론이 질문의 중요한 부분은 클래스 해당 코드 가 기본 패키지에 있어야한다는 것입니다 . 현재로서는 리플렉션 API를 사용하는 것 이외의 다른 답변 (실제로이 간단한 것에 대한 과잉) 은 해결책 이 아닙니다 . Java가 케이크 (기본 패키지 사용을 권장하지 않음)를 사용하고 먹는 방법 (JNI를 너무 복잡하게 만들고 대부분 기본 패키지를 필요로하는 DLL을 사용하게 됨)은 놀랍습니다.
ADTC

그 이유는 역사적으로 보이지만 때로는 물기도합니다. 예 :```T.java : import static a.Foo. *; class T {Bar bar = 새로운 Bar (); } a / Foo.java : 패키지 a; public class Foo {public static final class Bar {}}```위의 내용은 정상적으로 컴파일되지만 Foo가 기본 패키지에 포함되어 있으면 작동하지 않습니다. 따라서 Foo.Bar 대신 속기 Bar를 사용하기 위해 Foo. *를 정적으로 가져올 수 없습니다.
Kedar Mhaswade 2016

답변:


87

로부터 Java 언어 사양 :

이름이 지정되지 않은 패키지에서 유형을 가져 오는 것은 컴파일 시간 오류입니다.

리플렉션 또는 다른 간접적 인 방법을 통해 클래스에 액세스해야합니다.


1
와, 정말 자바를 전혀 몰라요. 큰 도움이되었습니다. 내 수업을 패키지로 옮겨야 할 것 같아 ...
anhoppe

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 ++ 프로그래밍 경험에서 아는 한, 같은 종류의 문제가 발생했을 때 ".C"파일의 이름을 변경하여 dll 작성 구조를 변경하여 해결했습니다. JNI 네이티브 기능을 구현 한 함수입니다. 예를 들어, "com.mypackage"패키지에 프로그램을 추가하려면 ".C"파일의 함수 / 메소드를 구현하는 JNI의 프로토 타입을 다음과 같이 변경합니다.

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
}

델파이를 처음 접했기 때문에 장담 할 수는 없지만 마침내 이렇게 말할 것입니다. (델파이와 JNI에 대해 인터넷 검색을 한 후 몇 가지를 배웠습니다.) : 네이티브의 델파이 구현을 제공 한 사람들에게 물어보십시오. 함수 이름을 다음과 같이 변경하는 코드 :

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;

그러나 마지막 조언 : 당신이 (당신이 델파이 프로그래머라면) 또는 그들이 이러한 함수의 프로토 타입을 변경하고 dll 파일을 재 컴파일 할지라도, 일단 dll 파일이 컴파일되면, 당신은 당신의 패키지 이름을 변경할 수 없습니다. "Java"파일을 반복합니다. 왜냐하면 이것은 변경된 접두사 (예 : JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)로 델파이에서 함수의 프로토 타입을 변경해야하기 때문입니다.

이것이 문제를 해결했다고 생각합니다. 감사합니다. Harshal Malshe


이것은 프로젝트에서 네이티브 라이브러리를 사용하려는 모든 사람에게 좋습니다.
Randnum

5

아래에서 찾은 곳에서 :-

실제로 할 수 있습니다.

Reflections 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을 빌드하지 않았으므로 다시 빌드 할 수 없습니다. 내가하는 일은 자바에 있어야한다. 저장 해주셔서 감사합니다 :)
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를 소스 폴더로 이동하십시오. (... / path_to_project / source / YourClass.class)

  3. 이렇게 가져 오기

    import source.YourClass;


1
그는의이 원하는 경우 나쁜 대답, 그는없는 일부 사용자 지정 패키지에 기본적으로 그것을 필요로
Enerccio
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.