Como importar uma classe do pacote padrão

98

Possível duplicata: Como acessar as classes java no pacote padrão?


Estou usando o Eclipse 3.5 e criei um projeto com alguma estrutura de pacote junto com o pacote padrão. Eu tenho uma classe no pacote padrão - Calculations.java e quero fazer o uso dessa classe em qualquer um dos pacotes (por exemplo, em com.company.calc). Quando tento fazer uso da classe que está no pacote padrão, recebo um erro do compilador. Não é capaz de reconhecer a classe no pacote padrão. Onde está o problema?

Calculations.java - código-fonte

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

Não posso colocar minha aula em nenhum outro pacote. Esta classe possui alguns métodos nativos que são implementados em Delphi. Se eu colocar essa classe em qualquer uma das pastas, terei que fazer alterações naquela DLL que desejo evitar (realmente - não posso). É por isso que coloquei minha classe no pacote padrão.

Michał Ziober
fonte
1
Encontrei este link: stackoverflow.com/questions/283816/… depois de criar essas perguntas.
Michał Ziober
Obviamente, a parte importante dessa questão é que a classe e seu código devem estar no pacote padrão . A partir de agora, qualquer resposta diferente de usar a API de reflexão (na verdade, um exagero para algo tão simples) não é uma solução. É incompreensível como o Java tenta pegar seu bolo (desencorajar o pacote padrão) e comê-lo também (torne o JNI tão complicado que a maioria de nós acaba usando DLLs que requerem o pacote padrão).
ADTC de
O motivo parece histórico, mas às vezes é doloroso. por exemplo, `` `T.java: import static a.Foo. *; classe T {Barra barra = nova Barra (); } a / Foo.java: pacote a; public class Foo {public static final class Bar {}} `` `O código acima compila bem, entretanto, se Foo for colocado no pacote padrão, não funciona. Portanto, não posso importar estaticamente Foo. * Para usar Bar abreviado em vez de Foo.Bar.
Kedar Mhaswade

Respostas:

87

Da especificação da linguagem Java :

É um erro de tempo de compilação importar um tipo de um pacote sem nome.

Você terá que acessar a classe por meio de reflexão ou algum outro método indireto.

McDowell
fonte
1
Uau, eu realmente não sei nada sobre java. Isso foi uma grande ajuda. Acho que terei que mover minha classe em um pacote ...
anhoppe
46

As classes no pacote padrão não podem ser importadas por classes nos pacotes. É por isso que você não deve usar o pacote padrão.

matt b
fonte
Esta deve ser a resposta padrão aceita, pois é a mais útil. Obrigado.
Neoraptor
8

Existe uma solução alternativa para o seu problema. Você pode usar reflexão para alcançá-lo.

Primeiro, crie uma interface para sua classe de destino Calculatons:

package mypackage;

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

}

Em seguida, faça com que sua classe de destino implemente essa interface :

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

Por fim, use reflexão para criar uma instância de Calculationsclasse e atribuí-la a uma variável do tipo CalculationsInterface:

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

Posso te dar esta sugestão, pelo que sei de minha experiência em programação C e C ++, uma vez, quando eu tive o mesmo tipo de problema, resolvi alterando a estrutura escrita dll no arquivo ".C" alterando o nome do função que implementou a funcionalidade nativa JNI. por exemplo, se você gostaria de adicionar seu programa no pacote "com.mypackage", você altera o protótipo do JNI que implementa a função / método do arquivo ".C" para este:

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
}

Como sou novo no Delphi, não posso garantir a você, mas direi isso finalmente, (aprendi algumas coisas após pesquisar no Google sobre Delphi e JNI): Pergunte a essas pessoas (se não for você) que forneceram a implementação Delphi do nativo código para alterar os nomes das funções para algo assim:

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;

Mas, um conselho final: embora você (se você for o programador delphi) ou eles alterem os protótipos dessas funções e recompilem o arquivo dll, uma vez que o arquivo dll seja compilado, você não será capaz de alterar o nome do pacote do seu Arquivo "Java" novamente e novamente. Porque, isso exigirá novamente que você ou eles alterem os protótipos das funções em delphi com prefixos alterados (por exemplo, JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Acho que isso resolve o problema. Obrigado e cumprimentos, Harshal Malshe

Harshal Malshe
fonte
Isso é bom para qualquer pessoa que tente usar bibliotecas nativas em seus projetos.
Randnum 01 de
5

De algum onde encontrei abaixo: -

Na verdade, você pode.

Usando a API de reflexões você pode acessar qualquer classe até agora. Pelo menos consegui :)

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
fonte
2
Parece que a reflexão é o único caminho a percorrer. Eu tenho uma biblioteca JNI que simplesmente se recusa a funcionar quando em qualquer pacote diferente do padrão. Eu não construí a DLL, então não posso reconstruí-la. Tudo o que faço tem que ser em Java. Obrigado por salvar o dia :)
ADTC
3

Infelizmente, você não pode importar uma classe sem que ela esteja em um pacote. Este é um dos motivos pelos quais é altamente desencorajado. O que eu tentaria é uma espécie de proxy - coloque seu código em um pacote que qualquer coisa possa usar, mas se você realmente precisar de algo no pacote padrão, torne-o uma classe muito simples que encaminhe chamadas para a classe com o código real. Ou, ainda mais simples, apenas estenda.

Para dar um exemplo:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}
Jon
fonte
1

Crie um novo pacote e então mova as classes do pacote padrão em um novo pacote e use essas classes

Khushboo Kashyap
fonte
Bem-vindo ao StackOverflow! Talvez você possa adicionar mais detalhes, para explicar melhor as partes mais importantes de sua resposta. Leia como escrevo uma boa resposta? Para maiores informações. Além disso, depois de obter mais reputação, você poderá postar como um comentário em vez de uma resposta, o que seria mais apropriado.
Francesco B.
-1
  1. Crie um novo pacote.
  2. Mova seus arquivos do pacote padrão para o novo.
Evgueni
fonte
-3
  1. Crie um pacote (pasta) "raiz" em seu projeto, por exemplo.

    fonte do pacote; (... / path_to_project / source /)

  2. Mova YourClass.class para uma pasta de origem. (... / path_to_project / source / YourClass.class)

  3. Importar assim

    import source.YourClass;

Andrey
fonte
1
resposta ruim, se ele quer isso, ele precisa no default, não em algum pacote customizado
Enerccio