2016-08-09 2 views
1
package Store; 

public class Child extends Parent { 
    private String test = ""; 

    public void ontest() { 
     this.test = "tryyyysssssssssss"; 
     System.out.println("in constructer: " + this.test); 
    } 

    public String gettt() { 
     System.out.println("in child: " + this.test); 
     return this.test; 
    } 
} 

public abstract class Parent { 
    Parent() { 
     ontest(); 
    } 
    public void ontest() { 

    } 
    public String get() { 
     System.out.println(gettt()); 
     return "test"; 
    } 
    public abstract String gettt(); 
} 


public class StoreString { 
    public static void main(String[] args) { 
     Child s = new Child(); 
     System.out.println("vaaaa:" + s.get()); 
    } 
} 

вывода является:Сохранить Строковое значение класса переменной

in constructer: tryyyysssssssssss 
in child: 
vaaaa:test 

Мой вопрос:

Я хотел бы использовать сохраненное значение атрибута в тесте Child класса в методе getttt(). Я не уверен, почему значение test пусто в gettt методе. Может ли кто-нибудь помочь мне, что здесь отсутствует?

+2

private String test = ""; ?? Это пустая строка в дочернем классе. – FallAndLearn

ответ

1

Просто удалите инициализацию по умолчанию тестовой строки:

public class Child extends Parent { 
    private String test; 

    @Override 
    public void ontest() { 
     test = "tryyyysssssssssss"; 
     System.out.println("in constructer: " + test); 
    } 

    @Override 
    public String gettt() { 
     System.out.println("in child: " + test); 
     return test; 
    } 

    public static void main(String[] args) { 
     Child s = new Child(); 
     System.out.println("vaaaa:" + s.gettt()); 
    } 

} 

abstract class Parent { 
    Parent() { 
     ontest(); 
    } 

    public abstract void ontest(); 

    public String get() { 
     return gettt(); 
    } 

    public abstract String gettt(); 
} 

Выход:

in constructer: tryyyysssssssssss 
in child: tryyyysssssssssss 
vaaaa:tryyyysssssssssss 
-3

Конструктор для ребенка должна начинаться с: public Child() {

+1

Проблема не из-за недостающего конструктора – Lin

+0

Спасибо всем за быстрый ответ –

4

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

Ссылка: Java Language specification item 12.5, в частности, список из пяти шагов.

1

Изменение String test=""; к String test;

public class Child extends Parent { 
     private String test; 

     public void ontest() { 
      this.test = "tryyyysssssssssss"; 
      System.out.println("in constructer: " + this.test); 
     } 

     public String gettt() { 
      System.out.println("in child: " + this.test); 
      return this.test; 
     } 
    } 

    public abstract class Parent { 
     Parent() { 
      ontest(); 
     } 
     public void ontest() { 

     } 
     public String get() { 
      System.out.println(gettt()); 
      return "test"; 
     } 
    public abstract String gettt(); 
} 


public class StoreString { 
    public static void main(String[] args) { 
     Child s = new Child(); 
     System.out.println("vaaaa:" + s.get()); 
    } 
} 

Выход

in constructer: tryyyysssssssssss 
in child: tryyyysssssssssss 
tryyyysssssssssss 
vaaaa:test 
2

Причина, почему test пуста есть, поток выполнения при создании экземпляра:

  1. Parent конструктор вызывается
  2. Child.ontest() вызывается (инициализация переменной)
  3. (родительские поля не инициализируются - ничего общего)
  4. (Ребенок constuctor вызывается - ничего не делать)
  5. поля Дочерние инициализирована - отменяет ранее заданное поле test с пустой строкой

Таким образом, вы можете либо удалить значение по умолчанию "", который оставит поле как есть (а именно, инициализированное "tryyyysssssssssss" конструктором Parent) или явный вызов-

1

Проблема заключается в исполнении, указанном JLS 12.5. Это то, что на самом деле происходит.

в явной ссылкой на важные правила здесь

[...]

3: Этот конструктор не начинается с явного вызова конструктора другого конструктора в том же классе (используя это). Если этот конструктор относится к классу, отличному от Object, то этот конструктор начнет с явного или неявного вызова конструктора суперкласса (используя super).

4: Выполнить инициализаторы экземпляра и инициализаторы переменных экземпляра для этого класса, присваивая значения инициализаторов переменных экземпляра соответствующим переменным экземпляра в порядке слева направо, в котором они отображаются текстовыми в исходном коде для класс.

[...]

Оценить аргументы и процесс, что конструктор суперкласса вызов рекурсивно, используя эти же пять шагов. [...]

Выполняется следующее из-за заданного порядка выполнения инициализации объекта. На последнем этапе вы найдете эту проблему, поскольку она снова назначит test в Child.

main starts -> Child s = new Child(); 

Child invokes Parent Constructor as first super call 

Parent constructor call method ontest(). 

ontest -> this.test = "tryyyysssssssssss" 

Parent constructor prints "tryyyysssssssssss" 

Child constructor continues and initalises the default values and sets this.test = "" 

, как @swinkler уже сказал, если вы удалите intialization по умолчанию из test последний шаг обыкновение устанавливать test в пустой String снова.

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