2014-08-27 2 views
-1

Объект, созданный конструктором в следующем коде, может вызываться несколько раз. Разве я написал код плохо, делая таким образом, я надеюсь, что это написано в соответствующих конвенцияхНеправильно ли этот код вызывать один и тот же конструктор один раз

import java.util.Scanner; 
/** 
* this class uses the scanner to take input from the keyboard 
* test if the input is a variable of type double if it is store in a 
* variable called numOne then take next input test again for type double 
* store in variable numTwo, then add the two variables together in the form 
* of variable answer and return to the screen. The user then is asked for 
* continuation as Y/N then appropriate action is taken 
*/ 

public class Calc { 

    /** 
    * this constructer does not throw InputMismatchException 
    */ 

    public Calc() { 
    Scanner in = new Scanner(System.in); // create scanner object 

     System.out.println("please enter 1st " 
      + "number then press enter" 
       + "\nthen enter 2nd number then " 
      + "press enter again"); 

     /*test for a double returns true */ 
     boolean myBool = in.hasNextDouble(); 

     /*the actual test for a double*/ 
     if(myBool == false) {  
       System.out.println("wrong format"); 

      /** 
      * call constructer and instantiate as new object 
      * by creating a new object i hope to have overwriten 
      * the original object stored in memory there by getting 
      * around the problem of hasNextDouble not allowing the 
      * scanner to advance 
      */ 

       Calc c = new Calc(); 

     } else {     // 1st else 
       double numOne = in.nextDouble();  // keyboard input 

      /*test for a double returns true */ 
       boolean myBool2 = in.hasNextDouble(); 

     /*the actual test for a double*/ 
     if(myBool2 == false) { 
       System.out.println("wrong format start again"); 

      /** 
      * call constructer and instantiate as new object 
      * there by removing need for InputMismatchException 
      */ 

       Calc c = new Calc(); 

     } else {     // 2nd else 
       double numTwo = in.nextDouble();  // keyboard input 

       double answer = numOne + numTwo;  // the maths 

     for(int i = 0; i<35; i++) {   // print pattern 
       System.out.print("*"); 
     } 
     System.out.println("\n**** " 
      + "Your 1st number is " 
      + numOne + " ****"); 

     System.out.println("****  "  // print operator 
      + "     " + "+" 
      + " ****"); 

     System.out.println("**** " 
      + "Your 2nd number is " 
      + numTwo + " ****"); 

     System.out.println("****  "  // print line 
      + "    ______ ****"); 

     System.out.println("****  " 
      + "The answer is " 
      + answer + " ****"); 

     for(int i = 0; i<35; i++) {   //print pattern 
       System.out.print("*"); 
     } 
     System.out.println("\nDo you have " 
      + "more calculations Y or N"); 

     String reply = in.next();    //keyboard input 

     if(reply.equalsIgnoreCase("Y")) { 
       Calc c = new Calc(); 
     } else { 
       System.out.println("OK bye then"); 
       in.close();    //close scanner 
     }    //end else 
     } // end 1st else 
     } // end 2nd else 
     } // end constructor 

    public static void main(String[] args) { 
     Calc c = new Calc();   // call constructor 
    } // end main 
} // end class 

// just in case i do something wrong thanks in anticipation Simon. 
+1

Приложите больше усилий для форматирования кода. На данный момент это повсюду ... затем приложите еще несколько усилий, чтобы задать вопрос. Вы включили * много * кода, но только сообщали в общих чертах о «объекте, который создается конструктором» - какой объект? Какой конструктор? –

+1

Кажется, это довольно ужасная идея. Я не знаю, что это технически «неправильно», но я думаю, что многие люди назвали бы это неправильным в производственном коде. – markspace

+0

Если мы игнорируем бесконечный цикл, возникает вопрос: почему вся программа находится внутри конструктора? WTF. Конструктор должен использоваться для создания объекта, а не для выполнения программы. –

ответ

2

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

И поскольку это не выглядит так, как будто вы делаете что-либо со всеми экземплярами Calc, которые вы создаете внутри конструктора, это бессмысленно.

+0

Привет, Eran, почему я помню публичный Calc(), если пользователь не вводит double, я не мог пройти .hasNextDouble, поскольку сканер, похоже, не продвигал ввод. Поэтому я создал новый объект и снова запустил, указывая на возможный цикл. –

+0

@SimonRemington Не имеет смысла вставлять весь этот код в конструктор вообще, так как вы на самом деле не строите объект, вы просто получаете входные данные от пользователя и печатаете некоторые выходы. Я бы поставил весь этот код в статическом методе. И вместо рекурсивных вызовов поместите весь код в цикл while - 'boolean needInput = true, while (needInput) {}'. Внутри цикла, в любом месте, которое вы в настоящее время вызываете конструктор, замените его на 'continue', который перейдет к новой итерации цикла. установите для параметра 'needInput' значение false, когда вы хотите выйти из программы. – Eran

0

Обычно считается, что для выполнения любой работы в конструкторе не существует прямой связи с созданием экземпляра этого объекта. Рассмотрим перенос вашей логики в другой метод на Calc. Таким образом, вы можете использовать один экземпляр Calc и использовать поля в этом экземпляре, возможно, вам повезло бы переписать значения, о которых ваши комментарии упоминают, что вы хотите перезаписать.

Как отметил Эран, ваш текущий шаблон использует рекурсивные вызовы, которые склонны к переполнению стека, если это не сделано правильно. Я бы не стал заходить так далеко, чтобы сказать, что рекурсивные звонки всегда плохие, но вы должны тщательно рассмотреть, является ли это наилучшим примером того, что вы делаете.

+0

привет StriplingWarrior спасибо за ваш вклад, на ваш взгляд, правильная логика? и есть ли другой способ ускорить сканер .hasNextDouble. Причина логики заключается в том, что я читаю, что лучше писать код, который не порождает ошибок, чем полагаться на их улов. –

+0

@SimonRemington: разработчики часто используют цикл для выполнения того, что вы описываете: 'while (true) {if (! In.hasNextDouble()) {outputNoNumberError(); ломать; } double numOne = in.nextDouble(); ...} '. Что касается правильности логики, я не знаком с вашими требованиями, и мне не хочется анализировать десятки строк кода. Это не цель этого сайта. – StriplingWarrior

0

Хотя вы (вероятно) не получите ошибку, это плохая практика во многих отношениях.

Прежде всего, вы не должны делать этого в конструкторе. Предполагается, что конструктор должен создать объект или выбросить исключение, вот и все. Если конструктор требует какого-либо ввода, прочитайте его заранее и передайте его в качестве аргумента конструктору. Конструкторы не предназначены для взаимодействия с пользователем.

Следующий пункт - обработка ошибок. Если пользователь вводит неверный ввод, нет необходимости использовать рекурсию. Конечно, вы не получите StackOverflowError (если только ваш пользователь не сработает несколько тысяч раз), но цикл является лучшим решением.

System.out.print("Enter a double please: "); 
while(!scanner.hasNextDouble()) { 
    System.out.print("Invalid input. Please try again: "); 
    scanner.next(); //discard invalid input 
} 
double input = scanner.nextDouble(); 
+0

J4v4 вы можете подробно рассказать о своем цикле, так как когда я компилирую тот, который вы разместили, он создает только бесконечный цикл для меня, когда я не вписываю двойной или это юмористический способ создания StackOverflowError. Пожалуйста, покажите мне этот цикл, так что я не получаю InputMismatchException спасибо –

+0

@Simon Remington Извините, я не знаком со сканером, поэтому я не использовал методы правильно. Я посмотрел его сейчас и исправил. – J4v4

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