2013-06-10 4 views
2

У меня есть 2 классов: Дата и лицо
Лицо имеет два атрибута класса DateВнутренний класс и это() конструктор

Случай 1

Date класс отдельный класс от класса Person. У меня есть этот кусок кода работает правильно:

private String name; 
private Date born; 
private Date died; // null indicates still alive. 

public Person(String initialName, int birthMonth, int birthDay, 
     int birthYear) { 
    // requirement from the instructor: 
    // **implement using the this() constructor** 
    this(initialName, new Date(birthMonth, birthDay, birthYear), null); 
} 

Случай 2: Внутренний класс (требование по присваивание)

Я поставил Date как частный внутренний класс Person

Теперь выше код конструктора больше не работает. Вот сообщение об ошибке:

Описания Пути к ресурсу Location Type Нет ограждающий экземпляр типа лица не доступен из-за некоторые промежуточный вызов конструктора Person.java/Wk03_Ch10_FileIO_Ch13_Interfaces/wk03_Ch10_FileIO_Ch13_Inner_Classes линии 43 Java задаче`

Как решить проблему? Я могу это сделать:

Date dt = new Date(birthMonth, birthDay, birthYear); 

К сожалению this() должен быть первой строкой в ​​конструкторе

Другой работа вокруг

public Person(String initialName, int birthMonth, int birthDay, 
     int birthYear) { 
    // implement using the this() constructor 
    this.name = initialName; 
    this.born = new Date(birthMonth, birthDay, birthYear); 
    this.died = null; 
} 

Однако последний кусок коды не удовлетворяет мои требования инструктора использования метода this() внутри конструктора.

+0

Дата статическая? – BevynQ

+0

Нет. Я должен использовать частный внутренний класс (я думаю) – user2469763

+0

@BevynQ Я попытался создать закрытый закрытый внутренний класс Date, и мой оригинальный код работает. Поэтому я попрошу инструктора, если это приемлемо. Между тем, любым другим способом? Спасибо – user2469763

ответ

0

Хотя я бы никогда не создал класс Date внутри класса Person (звучит как плохая идея с точки зрения приложения!), Вы, кажется, сказали, что это требование в каком-то задании.

Если вы настроены так:

public class Person { 

    ... 

    class Date { 
     ... 
    } 

} 

Тогда внутри методов Person, вам нужно будет вызывать конструктор Date с:

this.new Date(...) 

То есть синтаксис Java использует. Вам нужен экземпляр экземпляра типа Person, для которого создаются объекты внутреннего класса. Дело во внутренних классах (независимо от того, являются ли они членами, локальными или анонимными) состоит в том, что каждый экземпляр существует, связанный с экземпляром внешнего класса. Так что, если у меня был человек экземпляр p, я мог бы сказать:

p.new Date(...) 

Большая проблема здесь, однако, что вы не можете создать даты в Person конструктору, которые используют быть созданный около к человеку!Например, это fails:

public Person() { 
    this(this.new Date()); 
} 

, так как стоимость this не готова к использованию на этом пути еще (хотя интересно, вы можете иногда использовать this внутри конструкторов в других случаях, например, сохранение его в массивах, например).

Как вы поняли, что делает Dateстатический вложенный класс это хорошо, потому что экземпляры статических вложенных классов не привязаны к каким-либо экземпляров класса ограждающей, так что это самое лучшее решение. Если вам действительно нужен внутренний класс, вы не сможете передать новую дату как «аргумент» выражения this() и связать его с человеком, которого вы создаете! Возможно, это и есть пункт назначения (это класс выпускников? :-))

+1

В теории вы правы. Но, проверено на ideone ([пример кода] (http://ideone.com/HFIxVL)) и не работает. –

+0

@LuiggiMendoza +1 Ницца, спасибо! Я просто пытался это сделать. +1 для получения первой. Имеет смысл, потому что закрывающий экземпляр не существует до тех пор, пока не будет создан конструктор. Весь «задание» очень подозрительно. Может быть, непонимание? :) –

+0

Вот сообщение об ошибке: Описание \t \t Resource Path \t \t Расположение Тип не может ссылаться на «это», ни «супер», а явно вызывая конструктор \t \t Person.java/Wk03_Ch10_FileIO_Ch13_Interfaces/wk03_Ch10_FileIO_Ch13_Inner_Classes \t линия 43 \t Java Проблема – user2469763

2

Вы не можете создавать классы внутреннего члена (не static) в вызове другому конструктору. От JLS §8.8.7.1:

Явный оператор вызова конструктора в конструктор тела (СИК: вызов this()) не может ссылаться на любые переменные экземпляра или методы экземпляра или внутренних классов, объявленных в этом классе или любой суперкласс или использовать this или super в любом выражении; в противном случае возникает ошибка времени компиляции.

Причина в том, что внутренним классам, не относящимся к классу static, может потребоваться доступ к классу во время его создания. Например:

public class OuterClass { 

    private String name; 
    private InnerClass inner; 

    public OuterClass(String name, InnerClass inner) { 
     this.name = name; 
     this.inner = inner; 
    } 

    public OuterClass(String name) { 
     this(name, new InnerClass()); // Will not compile 
    } 

    public class InnerClass { 

     public InnerClass() { 
      // Access to name is allowed since this inner class isn't static 
      System.out.println(name); 
     } 
    } 
} 

Основная проблема здесь состоит в том, что, когда мы строим не- static внутреннего класса, он может получить доступ лиц, не являющиеся членов static из его ограждающего экземпляра (OuterClass, но ограждающие OuterClass еще не сделали его вызов в super() и поэтому считается небезопасным для доступа. Фактически, если этот код был разрешен для компиляции, он должен был распечатать null из-за порядка вызова конструктора. Короче говоря, InnerClass будет создан до вызова this.name = name, аналогичная концепция к информации, представленной в this question.

Решение сделать InnerClassstatic внутренний класс и передать имя к нему непосредственно:

public class OuterClass { 

    private String name; 
    private InnerClass inner; 

    public OuterClass(String name, InnerClass inner) { 
     this.name = name; 
     this.inner = inner; 
    } 

    public OuterClass(String name) { 
     this(name, new InnerClass(name)); 
    } 

    public static class InnerClass { 

     public InnerClass(String name) { 
      System.out.println(name); 
     } 
    } 
} 

InnerClass не может получить доступ к name из OuterClass когда он объявил static, поэтому мы должны передать его в явном виде на строительство сейчас, но это лучше, так как исходный код был бы сломан в любом случае.

Edit:

По Вашему вопросу:

Что меня смутило, что я могу создать объект в Date типа в конструкторе Person «s, до тех пор, как это не внутри метод this(). Я могу это сделать: Date dt = new Date(birthMonth, birthDay, birthYear); В чем разница между вышеуказанным и this(...., new Date(birthMonth, birthDay, birthYear), ...)?

Разница заключается в том, что при вызове вне this(), все звонки на super() имели место, они занимают место как часть this() из-за неявные вызовы на super(), поэтому объект достиг точки, где это считается приемлемым для доступа. Ваш экземпляр Date не может получить доступ к классу Person, потому что нет никакого контекста для Person и его полей, поэтому компилятор не разрешает его.

Вкратце, после того, как был вызван this(), по крайней мере, звонки на super() произошли, что является движущей силой этого ограничения, а также почему обескураживаются переопределяемые вызовы методов. Если метод переопределяется подклассом, а затем вызывается в конструкторе суперкласса, поля из подкласса могут быть доступны до того, как подкласс уже был инициализирован, даже если в возвращаются поля final. В принципе, все это касается защиты себя от доступа к вашему классу до вызова super().

+0

Что меня смутило, так это то, что я могу создать объект типа Date в конструкторе Person, если он не находится внутри метода this(). Я могу сделать это: 'Date dt = new Date (birthMonth, birthDay, birthYear);' В чем разница между вышеуказанным и 'this (...., new Date (birthMonth, birthDay, birthYear), ...) '? – user2469763

+0

@ user2469763 См. Мое редактирование – Brian

+0

Спасибо Брайан. Мне жаль, что я не могу проголосовать за ваш ответ. – user2469763