4

Я программировал Java в течение последних двух месяцев, но я опытный программист на python и C. Я знаю, что из-за этого я делаю ошибки.Java Singleton + внутренний класс missunderstand

Я прихожу к этому вопросу для очистки предупреждений моего проекта в студии Android.

Я использую класс Singleton с внутренними классами, чтобы сохранить все параметры конфигурации в одном месте и разрешить всем другим классам доступ к нему с необходимостью передачи конфигурации.

Вот основной код моего Singleton

public class syscfg { 

    public List<CommData> Commlist; 
    public static CommConfigIP4 MyCommConfig;// = new CommConfig(); 

    private static syscfg instance = null; 
    private static boolean ConfigStat = false; 

    /** JAVA singleton control methods**/ 
    protected syscfg(){ 
     // pues eso 

     if(ConfigStat == false){ 
      Log.i("SD_app_log", "SYSCFG: Module Initialization"); 
      ConfigStat = true; 
      MyCommConfig = new CommConfigIP4(); 
      init_config(); 
     }else{ 
      Log.i("SD_app_log", "SYSCFG: Module Loaded"); 
     } 
    } 

    public static syscfg getInstance(){ 
     if(instance == null){ 
      instance = new syscfg(); 
     } 
     return instance; 
    } 

    public class CommConfigIP4{ 
     public int discoveryPort = 30303; 
     public byte[] MyMAC; 
     public String MyType = ""; 
     public String MyIP; 

     public byte[] getIPbytearray(){ 
//   byte[] IPout= new byte[4]; 
      try{ 
       byte[] IPout = (InetAddress.getByName(MyIP)).getAddress(); 
       return IPout; 
      }catch (Exception e){ 
       return null; 
      } 

     } 

В моей связи Java файл/класс у меня есть:

public class Communications { 

    private syscfg CFid ; 
    ... 
    public Communications(Context ctx){ 
     ... 
     CFid = syscfg.getInstance(); 
     init_comms(); //init_comms calls whoami 
    } 

    private void whoami(){ 
     ... 
     CFid.MyCommConfig.MyType = netint.getName(); 
     ... 
    } 
} 

Так, когда я первый имел все элементы (переменные, классы и методы) в syscfg, поскольку статическая студия Android показала предупреждение о том, что статический член получил доступ через ссылку на экземпляр. После некоторых исследований и документации я нашел рекомендацию не использовать статические переменные и методы, и я попытался их устранить. Но тогда я получаю ошибку nullpointexception в

CFid.MyCommConfig.MyType = netint.getName(); 

С отладчиком я обнаружил, что CFid.MyCommConfig = null

Я использую синглтон, чтобы избежать использования статического класса на syscfg и доступ через конкретизацию и не используя имя класса.

Теперь мои одноплодные коды как один размещено здесь с CommConfigIP4 статическими, и я еще раз, что мне посоветовать, используя быть_наст предупреждения:

syscfg.MyCommConfig.MyType = netint.getName(); 

вместо того, чтобы использовать экземпляр Acces-де-конфигурации.

Что здесь происходит? Что мне не хватает?

Спасибо, Гильермо

+0

Синглтон - плохая идея. Google упорно трудился, чтобы изгнать их из их кода. Вы тоже должны. https://code.google.com/p/google-singleton-detector/ – duffymo

+0

Этот класс не Singleton: а также отсутствие синхронизации в заводском методе, класс в любом пакете может расширить его, так что вы можете 't контролировать, кто его создает. –

+0

Вы также должны использовать соглашения об именах Java: ClassesLikeThis, variablesLikeThis, STATIC_CONSTANTS_LIKE_THIS. Трудно следовать этому коде как есть. –

ответ

0

В вашем Whoami() метод вы сделаете эту ссылку:

CFid.MyCommConfig.MyType = netint.getName(); 

... однако, "MyCommConfig" является статическим свойством класса "syscfg", в то время как переменная «CFid» относится к экземпляру этого класса. Другими словами, все экземпляры «syscfg» (как и само определение класса) все относятся к одной и той же копии переменной «MyCommConfig» (что является статическими средствами).

По этой причине менее сложно сослаться на переменную «MyCommConfig», указав «syscfg.MyCommConfig», поскольку это дает понять, что вы ссылаетесь на статическую переменную, а не на экземпляр.

Кстати, вы должны учитывать стандартные условные обозначения Java-кода для кэширования имен классов и переменных, поскольку это сделает ваш код более читаемым для других Java-программистов.

0

Вы должны объявить вложенный класс, чтобы быть статическим:

public static class CommConfigIP4 

А затем раскомментировать код, который инициализирует статическую переменную в верхней части вашего внешнего класса.

0

Чтобы избежать этих предупреждений, вы должны реализовать синглтон таким образом. Я изменил код, чтобы сделать его понятным:

public class Syscfg { 

    public Config getConfig() { 
     return c; 
    } 

    // Obtain the same instance always 
    public static Syscfg getInstance() { 
     return s == null ? new Syscfg() : s; 
    } 

    // Important for singleton 
    private Syscfg() { 
     c = new Config(); 
    } 

    private static Syscfg s; 
    private Config c; 

    class Config { 

     public String[] getConfigs() { 
      return configs; 
     } 

     private String[] configs = {"10.10.10.10", "userName", "userPass"}; 
    } 

} 

Так что, если вы хотите знать, конфиги, используемые в другом классе, например, класса Test, то вы можете использовать

public class Test { 

    public static void main(String[] args) { 
     System.out.println(Arrays.toString(Syscfg.getInstance().getConfig().getConfigs())); 
    } 

} 

Результат: [10.10.10.10, userName, userPass]

+2

Я предлагаю вам использовать одноэлементный подход ENUM из-за бесплатного предоставления механизма сериализации и гарантии против нескольких экземпляров (рефлексивная атака) в соответствии с Блок Джоша на эффективной Java;) –