2014-10-19 5 views
2
package generics; 
public class InnerClassGenerics{ 
    class Innerclasss{ 

    } 
    public static void main(String[] args) { 
     InnerClassGenerics icg=new InnerClassGenerics(); 
     Innerclasss innerclass=icg.new Innerclasss(); 
    } 
} 

Выше код возможен и компилируется штраф !!!Можно ли использовать параметризующие общие внутренние классы?


Почему код ниже не компилируется и возможно ли параметризовать внутренние классы?

package generics; 
public class InnerClassGenerics<T>{ 
    class Innerclasss<T>{ 

    } 
    public static void main(String[] args) { 
     InnerClassGenerics<String> icg=new InnerClassGenerics<>(); 
     Innerclasss<String> innerclass=new Innerclasss<>(); 
    } 
} 

В приведенном выше коде, если класс выполнен как статический, он отлично работает !!! Почему это невозможно без статического ключевого слова?

+1

Это не имеет ничего общего с дженериками, просто говоря. – Smutje

+0

Возможный дубликат [внутренний класс Java и статический вложенный класс] (http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class) – Smutje

+0

Ваш параметр типа '' во внутреннем классе скрывает '' от внешнего класса. В любом случае вы должны исправить свой пример (вы пытаетесь создать нестатический внутренний класс из синего, без использования какого-либо экземпляра внешнего класса). – Pshemo

ответ

4

Обычно, если не будет никакого универсального типа на внешнем классе вы могли бы написать такой код:

Outer outer = new Outer(); 
Inner inner = outer.new Inner(); 

, потому что каждый метод внутреннего класса уже знает, какие типы следует использовать.

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

Посмотрите на этот код:

class Outer<T> { 
    private T someValue; 

    class Inner { 
     T getOuterValue(){ 
      return someValue; 
     } 
     void setOuterValue(T value){ 
      someValue=value; 
     } 
    } 
    //rest of code 
} 

Это означает, что экземпляр класса Inner также зависит от общего типа от его внешнего класса (ов).Именно поэтому при создании ссылки на внутренний класс вам нужно явно использовать внешний класс с родовым типом, написав его как

Outer<String> outer = new Outer<>(); 
Outer<String>.Inner inner = outer.new Inner(); 
^^^^^^^^^^^^^ 

или явно говорят, что внешний класс использует raw type (который не рекомендуется), как

Outer.Inner inner = outer.new Inner(); 

Итак, чтобы сделать ваш код работать вам нужно:

  1. добавить о тип класса макс (предпочтительно с его общим типом)

  2. invoke конструктор внутреннего класса на экземпляр внешнего класса (так же, как нестатические методы не могут быть вызваны без примера, должны создаваться нестатические (внутренние) классы используя внешний экземпляр класса)

    InnerClassGenerics<String>.Innerclasss<String> innerclass = icg.new Innerclasss<>(); 
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^         ^^^^ 
         point 1           point 2 
    

Также вы не должны давать одинаковые имена общим типам во вложенных классах и ее внешние классы, как в этом случае

public class InnerClassGenerics<T>{ 
    class Innerclasss<T>{ 
     ... 
    } 
} 

потому T от InnerclasssскрываетT от своего внешнего класса InnerClassGenerics (не то, что он вызывает текущую проблему, но это может сделать вашу жизнь трудной позже).

+0

Точное объяснение .. спасибо! – Terminator

+0

@ Терминатор Добро пожаловать :) – Pshemo

-1

Итак, у вас есть это определение класса, и оно не будет скомпилировано, потому что у вас есть 2 типа: T. Сделайте это так, и это будет скомпилировать:

public class OuterClass <O> 
{ 
    public class InnerClass <I> 
    { 
    } 
} 

Кроме того, заметьте, что вы инстанцирование нестатического класса из статического метода. Полный код должен выглядеть так:

public class OuterClass <O> 
{ 
    public static class InnerClass <I> 
    { 
    } 

    public OuterClass() 
    { 
    } 
    public InnerClass<O> getInnerClass() 
    { 
     return new InnerClass<O>(); 
    } 

    public static void main (String[] args) 
    { 
     OuterClass<String> outer = new OuterClass<>(); 
     InnerClass<String> inner = outer.getInnerClass(); 
    } 
} 

Для этого кода требуется Java 8 для компиляции.

+1

Ну, это может быть проблема с Java 7, но 'InnerClass inner' все еще вызывает ошибку компилятора. Разве это не должно быть 'OuterClass .InnerClass '? – Tom

+0

@Tom На Java8 (Eclipse) он компилируется просто отлично – msrd0

+0

Вышеупомянутый код бросает ошибку времени компиляции. (Невозможно сделать статическую ссылку на нестатический тип InnerClass) – Terminator

Смежные вопросы