我一直在教自己编码,getter和返回值,以及如何在主程序中调用它们。首先,我尝试编写一个程序来计算长途电话的费用,但运行它时它立即崩溃,而且我知道它与该类有关。
公平的警告,我的时间对于计算AM / PM有点奇怪,但是我已经尽力了。
我认为必须在我的主代码中调用计算-特别是String weekday = call1.calculateweekday();和int时间= call1.calculatetime(); ,但是我对编程非常陌生,我只是刚开始学习这些术语和用法,所以我不知道要做什么。我只知道,当我在主程序中移动这两行时,它就此中断了。
package practice;
import java.util.Scanner;
class Call {
String weekdayinput;
String weekday;
int hour;
String ampm;
int time;
int calculatetime() {
if (ampm.equals("pm") || ampm.equals("PM") || ampm.equals("Pm")) {
time = hour + 1200;
} else if (ampm.equals("am") || ampm.equals("AM") || ampm.equals("Am")) {
time = hour;
}
else {
System.out.println("You entered something either time or AM/PM incorrectly.");
}
return time;
}
String calculateweekday() {
if (weekdayinput.equals("mo") || weekdayinput.equals("Mo") || weekdayinput.equals("MO")) {
weekday = "Monday";
}
else if (weekdayinput.equals("tu") || weekdayinput.equals("Tu") || weekdayinput.equals("TU")) {
weekday = "Tuesday";
}
else if (weekdayinput.equals("we") || weekdayinput.equals("We") || weekdayinput.equals("WE")) {
weekday = "Wednesday";
}
else if (weekdayinput.equals("th") || weekdayinput.equals("Th") || weekdayinput.equals("TH")) {
weekday = "Thursday";
}
else if (weekdayinput.equals("fr") || weekdayinput.equals("Fr") || weekdayinput.equals("FR")) {
weekday = "Friday";
}
else if (weekdayinput.equals("sa") || weekdayinput.equals("Sa") || weekdayinput.equals("SA")) {
weekday = "Saturday";
}
else if (weekdayinput.equals("su") || weekdayinput.equals("Su") || weekdayinput.equals("SU")) {
weekday = "Sunday";
}
else {
System.out.println("You entered your weekday incorrectly.");
}
return weekday;
}
}
public class GettersandREturns {
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
Call call1 = new Call();
String weekday = call1.calculateweekday();
int time = call1.calculatetime();
System.out.println("To calculate the cost per minute of your long-distance call, we'll need some information.");
System.out.println(
"What hour are you planning on making the call. Minutes aren't necessary. Please only enter the hour number. (ex. 8)");
call1.hour = input.nextInt();
input.hasNextLine();
System.out.println("Is the call taking place AM or PM?");
call1.ampm = input.nextLine();
input.hasNextLine();
System.out.println("And what day of the week is that? Please enter weekday with only first two letters. (ex. Fr");
call1.weekdayinput = input.nextLine();
if (time >= 8 && time <= 11 && !weekday.equals("Saturday") && !weekday.equals("Sunday")
|| time >= 1212 && time <= 1206 && !weekday.equals("Saturday") && !weekday.equals("Sunday"))
{
System.out.println("Your call will charge $4.50 a minute.");
}
else if (time == 12 && !weekday.equals("Saturday") && !weekday.equals("Sunday")
|| time >= 1 && time < 8 && !weekday.equals("Saturday") && !weekday.equals("Sunday")
|| time > 1206 && time <= 1211 && !weekday.equals("Saturday") && !weekday.equals("Sunday")) {
System.out.println("Your call will charge $4.00 a minute.");
}
else if (weekday.equals("Saturday") || weekday.equals("Sunday")){
System.out.println("Your call will charge $2.25 a minute.");
}
else {
System.out.println("You must have entered something wrong!");
}
}
}
因此,主意是在周一至周五的上午8:00至下午6:00之间开始的任何通话均按每分钟4.50的费用计费。周一至周五,上午8:00之前或下午6:00之后开始的所有通话均按费率计费 每分钟4.00。最后,在星期六或星期日开始的任何呼叫均按每分钟2.25的费率计费。
但是当我运行该程序时,线程“ main”中出现异常java.lang.NullPointerException 在实践中.call.calculateweekday(GettersandREturns.java:32) 在实践中。GettersandREturns.main(GettersandREturns.java:82)
任何帮助将不胜感激。学习很难。
答案 0 :(得分:1)
在主要功能中,您将创建一个新呼叫并调用该呼叫的功能。
Call call1 = new Call();
String weekday = call1.calculateweekday();
int time = call1.calculatetime();
在这一点上,如果您查看具有以下变量的Call类,则会出现错误
String weekdayinput;
String weekday;
int hour;
String ampm;
int time;
您会看到这些变量并未在开始时进行初始化,因为int的默认值为0,而字符串的默认值为null(编程时有时会遇到nullpointerexceptions)。只要您不尝试访问此变量,null值就不会被禁止,这就是您的函数所要做的。
原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“ boolean java.lang.String.equals(java.lang.Object)”
将是错误
if (ampm.equals("pm") || ampm.equals("PM") || ampm.equals("Pm"))
将抛出异常,因为此时您要访问的ampm或任何其他String为空,并且您试图将空String与字符串进行比较。
请确保在将字符串与任何内容(例如,与
)进行比较之前,先初始化字符串String weekdayinput = "mo";
String weekday "mo";
int hour;
String ampm "am";
int time;
在您要求输入后,应该在工作日和时间调用函数。
Scanner input = new Scanner(System.in);
Call call1 = new Call();
System.out.println("To calculate the cost per minute of your long-distance call, we'll need some information.");
System.out.println(
"What hour are you planning on making the call. Minutes aren't necessary. Please only enter the hour number. (ex. 8)");
call1.hour = input.nextInt();
input.hasNextLine();
System.out.println("Is the call taking place AM or PM?");
call1.ampm = input.nextLine();
input.hasNextLine();
System.out.println("And what day of the week is that? Please enter weekday with only first two letters. (ex. Fr");
call1.weekdayinput = input.nextLine();
String weekday = call1.calculateweekday();
int time = call1.calculatetime();
此外,作为补充说明:您应该阅读“关于”开关,该开关可以代替许多if语句。
答案 1 :(得分:1)
Answer by Wuttke是正确的,应该接受。这里还有一些无关紧要的想法。
通常最好将每个类保存在自己的.java文件中。
成为careful with naming。具有描述性和特定性,使您的代码更易于阅读,查看和修改。因此,将您的Scanner
对象称为scanner
而不是input
。
您可以通过将文本输入转换为全部大写或小写来缩短一些逻辑。
您的代码time > 1206 && time <= 1211
使我感到困惑。我不明白你的意图。
将用户界面与业务逻辑分开。有关各种费用的日期和时间的规则应分开分类。当您的业务规则更改时,这使得使用非常简单的短代码即可进行读取和编辑的地方。商业规则最终总是会改变。
在用户界面代码中执行所有数据输入验证,并将其与业务逻辑代码分开。将已经验证的数据传递到业务逻辑(此处是确定定价的代码)。这个想法是集中在single responsibility上。业务逻辑代码仅应承担了解日间和时间定价方案的工作,而不应与用户进行交互。同样,UI代码不应该知道调用成本计算的实质内容,而应该只知道足以验证数据输入的内容。
使用if
代替一系列switch
语句,如Oracle Tutorial所示。
尽可能使用智能对象,而不要使用哑字符串或纯整数。 Java提供了DayOfWeek
enum,因此请使用这七个预定义的对象,而不要使用笨拙的字符串。同样,我们有一个LocalTime
类,用于一天中没有日期和时区的时间。
Java具有强大的本地化功能。因此,无需对美元符号和星期几的名称进行硬编码。
使用Scanner
之类的资源时,应将其关闭。 try-with-resources语法可自动完成这项工作。
这是一些示例代码。不用于生产,未经测试。但是对于学习Java的人来说应该很有趣。
在实际工作中,我会:
switch
语句替换为Java 12和Java 13中正在预览的新simplified switch
statement。q
)上给用户一个退出选项以退出。 首先,业务逻辑部分。
package work.basil.example;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
public class CallCostEstimator
{
private Set < DayOfWeek > weekdays = EnumSet.of ( DayOfWeek.MONDAY , DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY , DayOfWeek.THURSDAY , DayOfWeek.FRIDAY );
LocalTime daytimeStart = LocalTime.of ( 8 , 0 );
LocalTime daytimeStop = LocalTime.of ( 18 , 0 );
BigDecimal weekday_day_rate = new BigDecimal ( "4.5" );
BigDecimal weekday_night_rate = new BigDecimal ( "4.0" );
BigDecimal weekend_rate = new BigDecimal ( "2.25" );
public BigDecimal estimate ( LocalTime localTime , DayOfWeek dayOfWeek )
{
Objects.requireNonNull ( localTime );
Objects.requireNonNull ( dayOfWeek );
boolean isWeekday = ( weekdays.contains ( dayOfWeek ) );
boolean isDaytimeHours = ( ! localTime.isBefore ( this.daytimeStart ) ) && ( localTime.isBefore ( this.daytimeStop ) );
// Determine price slot
BigDecimal result = null;
if ( ! isWeekday )
{
result = this.weekend_rate; // In other cases we would make a copy before returning an object stored within this class. But `BigDecimal` is immutable, so not necessary.
} else
{ // Else is weekday.
if ( isDaytimeHours )
{
result = this.weekday_day_rate;
} else
{
result = this.weekday_night_rate;
}
}
if ( Objects.isNull ( result ) ) // Should not be possible if our cascade of `if` statements is complete and correct. Defensive programming requires that we check.
{
throw new IllegalStateException ( "Failed to find a price slot." );
}
return result;
}
}
以及用户界面部分。
package work.basil.example;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.format.TextStyle;
import java.util.*;
public class CallCostEstimateConsole
{
public static void main ( String[] args )
{
CallCostEstimateConsole app = new CallCostEstimateConsole ();
app.engageUser ();
}
public void engageUser ( )
{
// Use try-with-resources syntax to auto-close the scanner.
try (
Scanner scanner = new Scanner ( System.in ) ;
)
{
System.out.println ( "To calculate the cost per minute of your long-distance call, we'll need some information." );
Integer hour = null;
while ( Objects.isNull ( hour ) )
{
System.out.println ( "What hour are you planning on making the call? Minutes aren't necessary. Please only enter the hour number, 1-12 for 12-hour clock. (ex. 8)" );
try
{
int input = scanner.nextInt ();
if ( ( input < 1 ) || ( input > 12 ) )
{
System.out.println ( "Hour must be from 1 to 12." );
} else
{
hour = input;
}
} catch ( InputMismatchException e )
{
System.out.println ( "Error: Enter a digits only, for a number from 1 to 12. " );
}
}
String amPm = null;
while ( Objects.isNull ( amPm ) )
{
System.out.println ( "Is the call taking place AM or PM? (type either AM or PM, or am or pm)" );
String input = scanner.next ();
input = input.toUpperCase ();
if ( input.equals ( "AM" ) || ( input.equals ( "PM" ) ) )
{
amPm = input;
} else
{
System.out.println ( "You typed something other than AM or PM." );
continue;
}
// Tweak inputs for 12-hour to 24-hour conversion.
if ( amPm.equals ( "AM" ) && ( hour == 12 ) )
{
hour = 0;
}
}
// If 1 PM through 11 PM, add 12 hours for 24-hour time.
hour = ( amPm.equals ( "PM" ) & ( hour < 12 ) ) ? ( hour + 12 ) : hour; // Ternary statement. A compact alternative to an `if` statement.
LocalTime localTime = LocalTime.of ( hour , 0 );
DayOfWeek dayOfWeek = null;
while ( Objects.isNull ( dayOfWeek ) )
{
System.out.println ( "And what day of the week is that? Please enter weekday with only first two letters. (ex. Fr)" );
try
{
String input = scanner.next ().toLowerCase ();
if ( input.isEmpty () )
{
System.out.println ( "You did not type any characters. " );
continue; // Break-out to continue on to the next loop.
}
// Parsing logic.
switch ( input )
{
case "mo":
dayOfWeek = DayOfWeek.MONDAY;
break;
case "tu":
dayOfWeek = DayOfWeek.TUESDAY;
break;
case "we":
dayOfWeek = DayOfWeek.WEDNESDAY;
break;
case "th":
dayOfWeek = DayOfWeek.THURSDAY;
break;
case "fr":
dayOfWeek = DayOfWeek.FRIDAY;
break;
case "sa":
dayOfWeek = DayOfWeek.SATURDAY;
break;
case "su":
dayOfWeek = DayOfWeek.SUNDAY;
break;
default:
String message = "You did not type a 2-letter day-of-week code as expected. (Mo, Tu, We, Th, Fr, Sa, Su)";
throw new IllegalStateException ( message );
}
} catch ( InputMismatchException e )
{
System.out.println ( "Error: Enter a digits only, for a number from 1 to 12. " );
}
}
// Calculate result.
CallCostEstimator estimator = new CallCostEstimator ();
BigDecimal estimate = estimator.estimate ( localTime , dayOfWeek );
// Report result.
String output = NumberFormat.getInstance ( Locale.US ).getCurrencyInstance ().format ( estimate );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime ( FormatStyle.SHORT ).withLocale ( Locale.US );
String dow = dayOfWeek.getDisplayName ( TextStyle.FULL , Locale.US );
String message = "Your call at " + localTime.format ( f ) + " on " + dow + " will cost per minute: " + output;
System.out.println ( message );
}
}
}
示例运行。
To calculate the cost per minute of your long-distance call, we'll need some information.
What hour are you planning on making the call? Minutes aren't necessary. Please only enter the hour number, 1-12 for 12-hour clock. (ex. 8)
1
Is the call taking place AM or PM? (type either AM or PM, or am or pm)
am
And what day of the week is that? Please enter weekday with only first two letters. (ex. Fr)
mo
Your call at 1:00 AM on Monday will cost per minute: $4.00