2016-04-02 8 views
1

Ich sah diesen Code von Java-Tutorial Oracle und ich bin verwirrt, wie es tatsächlich funktioniert. Ich habe einige Fragen, die ich hoffe, jemand könnte mir freundlicherweise helfen Antwortnicht in der Lage, Java-Tutorial Orakel Internationalisierung zu verstehen Customizing-Ressourcenpakete Beispiel laden

1) Ich sehe nicht public List<Locale> getCandidateLocales(String baseName, Locale locale) wurde von überall aufgerufen, so wie wird es tatsächlich ausgeführt?

2), was als Argumente an public List<Locale> getCandidateLocales(String baseName, Locale locale) geben wird

3) public List<Locale> getCandidateLocales(String baseName, Locale locale) eine List<Locale> zurückgibt, was ist der Zweck ein List<Locale> der Rückkehr

4) public List<Locale> getCandidateLocales(String baseName, Locale locale) Rückkehr super.getCandidateLocales(baseName, locale);, wenn keine der if-Anweisung erfüllt ist, welche bezieht sich die Klasse auf das Schlüsselwort super?

public class RBControl { 
    public static void main(String[] args) { 
    test(Locale.CHINA); 
    test(new Locale("zh", "HK")); 
    test(Locale.TAIWAN); 
    test(Locale.CANADA); 
    } 

    private static void test(Locale locale) { 
    ResourceBundle rb = ResourceBundle.getBundle("Internationalisation/RBControl", locale, 
     new ResourceBundle.Control() { 
     @Override 
     public List<Locale> getCandidateLocales(String baseName, Locale locale) { 
      if (baseName == null) 
      throw new NullPointerException(); 
      if (locale.equals(new Locale("zh", "HK"))) { 
      return Arrays.asList(
       locale, 
       Locale.TAIWAN, 
       // no Locale.CHINESE here 
       Locale.ROOT); 
      } else if (locale.equals(Locale.TAIWAN)) { 
      return Arrays.asList(
       locale, 
       // no Locale.CHINESE here 
       Locale.ROOT); 
      } 
      return super.getCandidateLocales(baseName, locale); 
     } 
     }); 
    System.out.println("locale: " + locale); 
    System.out.println("\tregion: " + rb.getString("region")); 
    System.out.println("\tlanguage: " + rb.getString("language")); 
    } 
} 

Nochmals vielen Dank für jede Hilfe!

Antwort

1

Ehrlich gesagt, kann es ziemlich schwierig sein, Ihre Fragen zu beantworten, da Ihr Code-Stil älter ist als Java 7 (sind Sie ein Archäologe?), Aber ich werde es versuchen.

  1. Ich kann Ihnen nur versichern, dass getCandidateLocales(String, String) tatsächlich aufgerufen wird, wenn der Code für die gültigen Dateinamen oder Klassennamen Suche von Textressourcen zu laden. Zum Beispiel:

    // ResourceBundle.java line 1314 
    private static ResourceBundle getBundleImpl(String baseName, Locale locale, 
                  ClassLoader loader, Control control) { 
        // (...) many lines removed 
        // line 1352 - loop through files to find the best one 
        ResourceBundle baseBundle = null; 
        for (Locale targetLocale = locale; 
         targetLocale != null; 
         targetLocale = control.getFallbackLocale(baseName, targetLocale)) { 
         // line 1356, there you are 
         List<Locale> candidateLocales = control.getCandidateLocales(baseName, targetLocale); 
         if (!isKnownControl && !checkList(candidateLocales)) { 
          throw new IllegalArgumentException("Invalid Control: getCandidateLocales"); 
         } 
    
         bundle = findBundle(cacheKey, candidateLocales, formats, 0, control, baseBundle); 
    
         // lengthy comment removed for clarity 
         if (isValidBundle(bundle)) { 
          // checking if it is the right one, removed 
         } 
        } 
    
        // logic to deal with missing file, removed  
        return bundle; 
    } 
    
  2. ich es jetzt glauben sollte offensichtlich sein, aber lassen Sie mich in die Details gehen. Angenommen, Sie haben Ihre Nachrichten in Form von Eigenschaftendateien: messages.properties - Basis, Standardsprachressourcen, messages_fr.properties - französische Basisressourcen, messages_fr_CA.properties - französische kanadische Ressourcen und schließlich messages_de.proprties - deutsche Basisressourcen. Der Basisname lautet so, als könnten Sie den Basisdateinamen messages erraten. Candidate-Gebietsschema ist das Gebietsschema der Benutzeroberfläche.
    Wenn Sie an einer Desktop-Anwendung (höchst unwahrscheinlich) oder an einer mobilen Anwendung arbeiten, können Sie UI Locale abrufen, indem Sie einfach Locale.getDetault(Locale.Category.DISPLAY) aufrufen. In älteren Versionen von Java wäre es nur Locale.getDefault(). In einer Webanwendung hängt die Lösung tatsächlich sowohl von der Technologie (z. B. Spring, JSF, Thymeleaf, Play, ...) als auch von Ihrer Herangehensweise bei der Erkennung von Locale ab. Wie auch immer, du solltest zuerst das am meisten spezialisierte versuchen, als dich zurückzuziehen. Zum Beispiel sollte der Französisch-Kanadische Benutzer (Sprachtag fr-CA) den Inhalt von messages_fr_CA.properties gesehen haben, während andere Benutzer der französischen Sprache mit Inhalten von messages_fr.properties bedient werden sollten. Ebenso sollte an jedem anderen Ort die Übersetzung aus messages.properties berücksichtigt werden.
    Mit dieser Methode werden die Fallback-Locales für einen Benutzer generiert (dh für die Eingabe Locale.forLanguageTag("fr-CA") wird die Eingabe selbst, das französische Gebietsschema ("fr") und eine nicht definierte Gebietsschema-Markierung ("und") zurückgegeben man teilt die ResourceBundle die Standarddatei verwendet

  3. die Liste der Ausweich Gegenden gibt, wie ich oben erklärt

  4. sie das Verfahren in einer übergeordneten Klasse aufruft -... ResourceBundle.Control die anonyme innere Klasse definierte in Die von Ihnen angehängte Codeliste stammt tatsächlich von ResourceBundle.Control,

+0

Vielen Dank für die ausführliche Erklärung! es ist mehr als ich jemals gehofft hatte!Übrigens war ich fasziniert von Ihrem Kommentar, dass dieser Code-Stil älter ist als Java7. Ich habe den Code selbst nicht gefunden, ich habe ihn tatsächlich im Java-Tutorial Oracle gefunden. Bedeutet das, dass die Oracle Tutorials veraltet sind? – Thor

+1

@Tony: Nun, leider braucht es Zeit, um die Dinge auf dem neuesten Stand zu halten, also denke ich, die Antwort ist zu einem gewissen Grad ja. Der Code funktioniert immer noch, aber es gibt Dinge, die aktualisiert werden müssen, d. H. 'Objects.requireNonNull (Basisname);' anstelle von manueller Nullprüfung und 'Locale.forLanguageTag (" zh-HK ")' anstatt direkt einen Konstruktor aufzurufen. Letzteres könnte jedoch umstritten sein. –