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


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.