2015-05-12 3 views
9

Angenommen, wir diese Klasse und ihre innere Klasse haben:Was ist der empfohlene/richtige Weg, um auf Felder in einer inneren Klasse zuzugreifen?

/* Outer.java */ 
public class Outer { 
    private static class Inner { 
     private final Object foo; 

     public Inner(Object foo) { 
      this.foo = foo; 
     } 

     public Object getFoo() { 
      return foo; 
     } 
    } 

    Inner inner = parse(/* someMistery */); 

    // Question: to access foo, which is recommended? 
    Object bar = inner.getFoo(); 
    Object baz = inner.foo; 
} 

Ich bin überrascht, dass inner.foo funktioniert.

Da foo ist private, kann es nur durch getFoo() zugegriffen werden, nicht wahr?

+1

Java-Zugriffsregeln sind kompliziert (noch mehr für 'protected'). aber wenn es funktioniert, sollten Sie glücklich sein, warum sich beschweren :) – ZhongYu

Antwort

11

Da foo privat ist, kann es nur über getFoo() zugegriffen werden, richtig?

In diesem Fall hat Outer Zugang zu ihm zu, weil Inner Mitglied Outer ist.

6.6.1 sagt:

[Wenn] das Mitglied oder Konstruktor private deklariert wird, [dann] Zugriff erlaubt ist, wenn und nur wenn es innerhalb des Körpers der Top-Level-Klasse tritt, der die Erklärung umschließt des Mitglieds oder Konstruktors.

Beachten Sie, dass es angegeben ist innerhalb des Körpers der Top-Level- Klasse zugänglich zu sein, der die Erklärung einschließt.

Das bedeutet zum Beispiel:

class Outer { 
    static class Foo { 
     private Foo() {} 
     private int i; 
    } 
    static class Bar {{ 
     // Bar has access to Foo's 
     // private members too 
     new Foo().i = 2; 
    }} 
} 

Ob ein Getter verwenden oder nicht wirklich eine Frage des Geschmacks ist. Die wichtige Erkenntnis hierbei ist, dass äußere Klassen Zugriff auf die privaten Mitglieder ihrer verschachtelten Klassen haben.

Als Empfehlung, würde ich persönlich sagen:

  • Wenn die verschachtelte Klasse private ist (nur die äußere Klasse Zugriff darauf hat), würde ich nicht einmal die Mühe, es einen Getter zu geben, es sei denn der Getter tut eine Berechnung. Es ist willkürlich, und jemand anderes kann mitkommen und beschließen, es nicht zu benutzen. Wenn die Stile gemischt sind, hat der Code eine Ungenauigkeit. (Do inner.foo und inner.getFoo() wirklich das gleiche tun? Wir müssen Zeit gehen Prüfung der Inner Klasse, um herauszufinden.)
  • Aber Sie könnten durch einen Getter sowieso gehen, wenn das der Stil ist, mit denen Sie sich wohl fühlen.
  • Wenn die verschachtelte Klasse nicht private ist, verwenden Sie den Getter, so dass der Stil einheitlich ist.

Wenn Sie wirklich wollen die private sich dahinter zu verstecken, auch von der äußeren Klasse können Sie eine Fabrik mit einer lokalen oder anonymen Klasse verwenden:

interface Nested { 
    Object getFoo(); 
} 

static Nested newNested(Object foo) { 
    // NestedImpl has method scope, 
    // so the outer class can't refer to it by name 
    // e.g. even to cast to it 
    class NestedImpl implements Nested { 
     Object foo; 

     NestedImpl(Object foo) { 
      this.foo = foo; 
     } 

     @Override 
     public Object getFoo() { 
      return foo; 
     } 
    } 

    return new NestedImpl(foo); 
} 

Als pedantisch Notiz, Ihre static class Inner {} ist technisch eine statische verschachtelte Klasse, keine innere Klasse.class Inner {} (ohne static) wäre eine innere Klasse.

Dies ist specifically defined so zu sein:

Das static Schlüsselwort T die Deklaration einer Elementtyp C innerhalb des Körpers einer nicht-Innen Klasse oder Schnittstelle ändern kann. Sein Effekt ist zu erklären, dass C keine innere Klasse ist.

+1

pedantisch, "statisch, Mitglied, Klasse" :) Verschachtelte Klasse enthält mehr, wie lokale Klasse und Anon-Klasse; obwohl es wahr ist, dass nur eine Mitgliedsklasse statisch sein kann – ZhongYu

+0

@ bayou.io Ja, wenn wir spezifisch sind. Da lokale Klassen und anonyme Klassen immer innerlich sind, sind alle stati- schen verschachtelten Klassen Mitgliedsklassen. – Radiodef

+1

Interessanterweise würde ich nicht verstehen, dass "Bar" innerhalb des Körpers der Toplevel-Klasse ist, aber es funktioniert. (Und Eclipse weiß es nicht, weil es beschwert, dass das private 'i' nicht benutzt wird.). Ich denke, "innerhalb" kann auf verschiedene Arten verstanden werden :) – eckes

0

Es hängt alles von Ihrem Stück Code ab, wo Sie auf dieses Objekt zugreifen möchten. Da es sich um eine statische geschachtelte Klasse handelt, können Sie auf beide Arten auf Ihr Objekt zugreifen. Siehe diesen Link http://www.javatpoint.com/static-nested-class zum besseren Verständnis der inneren Klassen.

Verwandte Themen