Varsayılan paketten bir sınıf nasıl alınır


98

Possible Duplicate: Varsayılan paketteki java sınıflarına nasıl erişilir?


Eclipse 3.5 kullanıyorum ve varsayılan paket ile birlikte bazı paket yapılarına sahip bir proje oluşturdum. Varsayılan pakette bir sınıfım var - Calculations.java ve bu sınıfın herhangi bir pakette (örneğin içinde com.company.calc) kullanılmasını istiyorum. Varsayılan pakette bulunan sınıfı kullanmaya çalıştığımda, bana bir derleyici hatası veriyor. Varsayılan paketteki sınıfı tanıyamaz. Sorun nerede?

Calculations.java - kaynak kodu

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

Sınıfımı başka bir pakete koyamam. Bu sınıf, Delphi'de uygulanan bazı yerel yöntemlere sahiptir. Bu sınıfı klasörlerden herhangi birine koyarsam, kaçınmak istediğim DLL'de değişiklikler yapmam gerekecek (gerçekten - yapamam). Bu yüzden sınıfımı varsayılan pakete koydum.


1
Bu soruyu oluşturduktan sonra şu bağlantıyı buldum: stackoverflow.com/questions/283816/… .
Michał Ziober


Tabii ki, bu sorunun önemli kısmı, sınıfın ve kodunun varsayılan pakette olması gerektiğidir . Bugün itibarıyla, kullanım yansıma API dışında herhangi bir cevap (gerçekten, bir şey bu basit bir gereğinden fazla) olduğu değil bir çözüm. Java'nın kendi pastasına sahip olmaya (varsayılan paketi caydırmaya) ve onu da yemeye çalışması akıllara durgunluk vericidir (JNI'yi o kadar kıvrımlı yapın, çoğumuz varsayılan paket gerektiren DLL'leri kullanırız).
ADTC

Nedeni tarihi görünüyor, ancak bazen ısırıyor. örneğin, `` T.java: statik a.Foo. * içe aktar; sınıf T {Bar bar = new Bar (); } a / Foo.java: paket a; public class Foo {public static final class Bar {}} `` Yukarıdaki iyi derlenir, ancak Foo varsayılan pakete yerleştirilirse çalışmaz. Bu nedenle, Foo.Bar yerine stenografi Bar kullanmak için Foo. * 'I statik olarak içe aktaramıyorum.
Kedar Mhaswade

Yanıtlar:


87

Gönderen Java dili spec :

Adsız paketten bir tür almak derleme zamanı hatasıdır.

Sınıfa yansıtma veya başka bir dolaylı yöntemle erişmeniz gerekecek.


1
Vay canına gerçekten java bilmiyorum. Bu çok yardımcı oldu. Sanırım sınıfımı bir pakete
taşımam gerekecek

46

Varsayılan paketteki sınıflar, paketlerdeki sınıflar tarafından içe aktarılamaz. Bu nedenle varsayılan paketi kullanmamalısınız.


Bu, en yararlı olduğu için varsayılan olarak kabul edilen yanıt olmalıdır. Teşekkür ederim.
Neoraptor

8

Sorununuz için bir çözüm var. Bunu başarmak için yansımayı kullanabilirsiniz.

Öncelikle, hedef sınıfınız için bir arayüz oluşturunCalculatons :

package mypackage;

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

}

Ardından, hedef sınıfınızın bu arabirimi uygulamasını sağlayı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");
    }
}

Son olarak, bir sınıf örneği oluşturmak için yansımayı kullanın Calculationsve bunu bir tür değişkenine atayın CalculationsInterface:

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

5

Size şu öneriyi verebilirim, C ve C ++ Programlama tecrübemden bildiğim kadarıyla, bir kez aynı türden bir problem yaşadığımda, ".C" Dosyasındaki dll yazılı yapısını değiştirerek ismini değiştirerek çözdüm. JNI yerel işlevselliğini uygulayan işlev. örneğin, programınızı "com.mypackage" paketine eklemek isterseniz, ".C" Dosyasının işlevini / yöntemini uygulayan JNI prototipini bununla değiştirirsiniz:

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
}

Delphi'de yeni olduğum için, size garanti veremem ama sonunda şunu söyleyeceğim (Delphi ve JNI hakkında googledikten sonra birkaç şey öğrendim): Delphi'nin yerli uygulamasını sağlayan kişilere (eğer siz değilseniz) sorun. işlev adlarını şunun gibi değiştirmek için kod:

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;

Ancak, son bir tavsiye: Siz (delphi programcısı iseniz) veya onlar bu fonksiyonların prototiplerini değiştirecek ve dll dosyasını yeniden derleyecek olsanız da, dll dosyası derlendikten sonra paket adınızı değiştiremezsiniz. "Java" dosyasını tekrar & tekrar. Çünkü, bu yine sizin veya onların delphi'deki işlevlerin prototiplerini değiştirilmiş öneklerle değiştirmenizi gerektirecektir (örn. JAVA_yourpackage_with_underscores_for_inner_packages_JavaFileName_MethodName)

Sanırım bu sorunu çözüyor. Teşekkürler ve saygılar, Harshal Malshe


Bu, projelerinde Yerel Kitaplıkları kullanmaya çalışan herkes için iyidir.
Randnum

5

Aşağıda bulduğum yerlerden: -

Aslında yapabilirsiniz.

Yansıma API'sini kullanarak şimdiye kadar herhangi bir sınıfa erişebilirsiniz. En azından başardım :)

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
Görünüşe göre düşünmek, gitmenin tek yolu. Varsayılan paket dışındaki herhangi bir pakette çalışmayı reddeden bir JNI kitaplığım var. DLL'yi ben oluşturmadım, bu yüzden yeniden oluşturamıyorum. Yaptığım her şey Java'da olmalı. Günü kurtardığınız için teşekkürler :)
ADTC

3

Maalesef, bir pakette olmadan bir sınıfı içe aktaramazsınız. Bu, son derece cesaretinin kırılmasının nedenlerinden biridir. Deneyeceğim şey bir çeşit proxy - kodunuzu herhangi bir şeyin kullanabileceği bir pakete koyun, ancak varsayılan pakette gerçekten bir şeye ihtiyacınız varsa, bunu çağrıları gerçek kodla sınıfa ileten çok basit bir sınıf yapın. Ya da daha basit, sadece uzatın.

Bir örnek vermek gerekirse:

import my.packaged.DefaultClass;

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

public class DefaultClass {

   // Code here

}

1

Yeni bir paket oluşturun Ve sonra varsayılan paket sınıflarını yeni pakette taşıyın ve bu sınıfları kullanın


StackOverflow'a hoş geldiniz! Cevabınızın en önemli kısımlarını daha iyi açıklamak için belki daha fazla ayrıntı ekleyebilirsiniz. İyi bir cevabı nasıl yazabilirim? daha fazla bilgi için. Ayrıca, daha fazla itibar kazandıktan sonra, bunu bir cevap yerine yorum olarak gönderebileceksiniz, bu daha uygun olacaktır.
Francesco B.

-1
  1. Yeni bir paket oluşturun.
  2. Dosyalarınızı varsayılan paketten yenisine taşıyın.

-3
  1. Örneğin, projenizde "kök" paketi (klasör) oluşturun.

    paket kaynağı; (... / projeye_ yol / kaynak /)

  2. YourClass.class'ı bir kaynak klasöre taşıyın. (... / proje_ yolu / kaynak / Sınıfınız.class)

  3. Bunun gibi içe aktar

    import source.YourClass;


1
kötü cevap, eğer bunu istiyorsa, varsayılan olarak ihtiyacı var, özel bir pakette değil
Enerccio,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.