BigDecimal导致NumberFormatException

时间:2015-09-17 15:50:26

标签: java android currency bigdecimal numberformatexception

我正在开发一个金融应用程序,我必须使用BigDecimal来计算货币。现在我正在尝试进行一个入口活动,即在SharedPreferences中搜索以前的注册,如果它们是1,则启动另一个活动,如果不是它启动注册活动。问题是注册活动导致NumberFormatException错误,而我正在尝试构建一个新的时间利润对象(Profit类包含BigDecimal字段)。另外,我不太确定我正在使用SharedPreferences。我不太确定我的想法和我的编码是否正常,因为我是Android开发的新手,我遇到了这个问题所以我给你所有的课程。

注册活动:

public class Registration extends Activity {

private static String enteredPassword;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    final EditText password1 = (EditText) findViewById(R.id.password1);
    final EditText password2 = (EditText) findViewById(R.id.password2);
    final EditText availability = (EditText) findViewById(R.id.availability);
    EditText profitEditText = (EditText) findViewById(R.id.profit);
    Spinner spinner = (Spinner) findViewById(R.id.period_spinner);
    Button registrationButton = (Button) findViewById(R.id.registrationButton);

    DatePicker picker = (DatePicker) findViewById(R.id.thePicker);

    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
            R.array.periods_array, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);


    final String balance =  availability.getText().toString().replace(",",".");
    String profitPeriod = ((Period) spinner.getSelectedItem()).name();
    final Profit profit = new Profit("regular_profit", profitEditText.getText().toString(),
            profitPeriod ,picker);

    registrationButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (password1.getText().toString().equals(password2.getText().toString())) {
                enteredPassword = password1.getText().toString();
                Repository.setPassword(enteredPassword, mContext);
            }
            Repository.setBalance(balance, mContext);
            Repository.setProfit(profit, mContext);
        }
    });

}

}

利润活动

public class Profit {



private Date mProfitDate;
private Date mNextProfitDate;
private BigDecimal value;

public final static String TITLE = "title";
public final static String PERIOD = "period";




Profit(String title,String value, String period, DatePicker picker) {
    this.mTitle = title;
    if(value!=null){this.value = new BigDecimal(value);}else{ this.value = new BigDecimal("0.0");};
    this.mPeriod = Period.class.cast(period);
    this.mProfitDate = Repository.getDateFromPicker(picker);
}




public long getNextProfitDate(Date profitDate, Period period){
    long unixProfitDate = profitDate.getTime() / 1000L;
    long nextProfitDate=0;
    switch (period){
        case DAILY:
            nextProfitDate = DateUtils.DAY_IN_MILLIS/1000 + unixProfitDate;
            break;
        case WEEKLY:
            nextProfitDate = DateUtils.WEEK_IN_MILLIS/1000 + unixProfitDate;
            break;
        case MONTHLY:
            Date dateNow = new Date();
            dateNow.getTime();
            nextProfitDate = Repository.monthsToSeconds(Calendar.getInstance()
                    .get(Calendar.MONTH)) + unixProfitDate;
            break;
        case YEARLY:
            nextProfitDate = DateUtils.YEAR_IN_MILLIS/1000 + unixProfitDate;
            break;
    }
    return nextProfitDate;
}

}

入学活动

public class EnterActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_enter);

    CountDownTimer timer = new CountDownTimer(3000, 100) {
        public void onTick(long millisUntilFinished) {
        }
         public void onFinish() {
            if(Repository.getPassword(mContext.getApplicationContext()).equals("No Value")){
                Intent registrationIntent = new Intent(mContext, Registration.class);
                startActivity(registrationIntent);
            }
            else{
                Intent configurationIntent = new Intent(mContext, Configuration.class);
                startActivity(configurationIntent);
            }
        }
    }.start();

}

}

存储库

public class Repository {

public static SharedPreferences sharedPreferences;


private static SharedPreferences getPrefs(Context context) {
    return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
}

public static String getPassword(Context context){
    return getPrefs(context).getString(PASSWORD,"No Value");
}
public Repository() {
}


public static void setPassword(String password, Context context){
    SharedPreferences.Editor editor = getPrefs(context).edit();
    editor.putString(PASSWORD, password);
    editor.commit();
}
public static void setBalance(String balance, Context context){
    SharedPreferences.Editor editor = getPrefs(context).edit();
    editor.putString(BALANCE, balance);
    editor.commit();
}

public static void setProfit(Profit profit, Context context){
    SharedPreferences.Editor editor = getPrefs(context).edit();
    editor.putString(BALANCE, profit.getValue().toString());
    editor.commit();
}

}

输出

E/AndroidRuntime: FATAL EXCEPTION: main
        E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{/.Registration}: java.lang.NumberFormatException: Bad offset/length: offset=0 len=0 in.length=0
        E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
        E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
        E/AndroidRuntime:     at android.app.ActivityThread.access$600(ActivityThread.java:123)
        E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
        E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
        E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:137)
        E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:4424)
        E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
        E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:511)
        E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
        E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
        E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)
        E/AndroidRuntime:  Caused by: java.lang.NumberFormatException: Bad offset/length: offset=0 len=0 in.length=0
        E/AndroidRuntime:     at java.math.BigDecimal.<init>(BigDecimal.java:282)
        E/AndroidRuntime:     at java.math.BigDecimal.<init>(BigDecimal.java:438)
        E/AndroidRuntime:     at .Profit.<init>(Profit.java:41)
        E/AndroidRuntime:     at .Registration.onCreate(Registration.java:57)
        E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:4466)
        E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
        E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
        E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
        E/AndroidRuntime:     at android.app.ActivityThread.access$600(ActivityThread.java:123)
        E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
        E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
        E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:137)
        E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:4424)
        E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
        E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:511)
        E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
        E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
        E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

您没有正确地将字符串解析为大十进制。

Profit构造函数中的以下内容:

if(value!=null)
{
    this.value = new BigDecimal(value);
}
else
{ 
    this.value = new BigDecimal("0.0"); 
}

需要将字符串解析为BigDecimal。如下所示this.value的类型为BigDecimal:

this.value = (BigDecimal) decimalFormat.parse(value);

另请注意,decimalFormat.parse可以抛出ParseException。您将需要使用try / catch处理它或抛出它。

答案 1 :(得分:0)

您只在所呈现的代码中的一个位置实例化Profit

Profit profit = new Profit("regular_profit", profitEditText.getText().toString(),
        profitPeriod, picker);

如果这会导致NumberFormatException,那么它必须来自Profit构造函数中的此代码:

if(value!=null){this.value = new BigDecimal(value);}else{ this.value = new BigDecimal("0.0");};

由于value字符串来自于对象上的toString(),因此您可以依赖它null(无论如何,如果它是null然后你会在new BigDecimal("0.0")结束,你可以自己验证一切正常。这让我们以new BigDecimal(value)为罪魁祸首。 The docs for this constructor提供了参数字符串的预期格式的详细信息。如果参数不符合该格式,则会抛出NumberFormatException

在您描述的场景中,人们可能想象的更可能是格式错误的字符串是空字符串,这与Java中的null不同。鉴于文本来自UI领域,您还必须注意有趣和难以发现的错误,例如前导和尾随空格。

也许最好像这样编写构造函数的受影响部分:

if (value != null) {
    value = value.trim();
    this.value = value.length() == 0 ? BigDecimal.ZERO : new BigDecimal(value);
} else {
    this.value = BigDecimal.ZERO;
}

请注意,即使进行了此更改,此构造函数仍会在发生其他类型的错误时抛出NumberFormatException。如果您不确定数据的有效性,您应该准备好处理这样的例外。