我正在使用Android Studio中的纯Java(无NDK)编写的应用程序。该应用程序几天前开始崩溃并告诉我,我正在尝试在空对象引用上调用抽象类方法。但是,输出控制台引用的对象引用只被修改一次(当它们第一次被实例化时)。
我有一个名为RecipeEditor
的自定义类,其中包含其他两个自定义类的私有成员对象数组:IngredientSelector
和GraphBar
。当我实例化RecipeEditor
时,它会逐个实例化IngredientSelector
个对象和GraphBar
个对象。
RecipeEditor
和IngredientSelector
都包含方法updateValues()
。实例化IngredientSelector
对象时,会传递对其所属的RecipeEditor
对象的引用。此外,当IngredientSelector
对象在其自身内部调用updateValues()
时,它会更新一些变量,然后调用先前传递给它的updateValues()
对象的RecipeEditor
函数。
这是事情变得棘手的问题:updateValues()
对象中的RecipeEditor
函数在尝试调用GraphBar类中包含的setBarValue()
方法时会崩溃应用程序。更糟糕的是,调试器表示IngredientSelector
对象数组和GraphBar
对象数组都为空。为了使事情变得更奇怪,曾经包含在数组中的对象仍然存在于内存中。我知道这一点,因为对象仍在屏幕上运行。
RecipeEditor
上课:
package darnell.coldpresstycoon;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.TextView;
import darnell.coldpresstycoon.Dialogs.*;
import java.util.ArrayList;
import java.util.Locale;
/**
* Created by Darnell on 4/8/2017.
*/
public class RecipeEditor {
private View layout;
private Recipe recipe;
private TextView ouncesRemaining;
private int ouncesRemainingValue = 16;
private IngredientSelector[] ingredientSelectors = new IngredientSelector[3];
private GraphBar[] graphBars = new GraphBar[4];
public RecipeEditor(View layout, ArrayList<Ingredient> ingredients, Recipe recipe) {
this.layout = layout;
this.recipe = recipe;
ouncesRemaining = (TextView) layout.findViewById(R.id.ouncesRemaining);
ingredientSelectors[0] = new IngredientSelector(
layout.findViewById(R.id.ingredientSelector1),
this,
recipe,
0);
ingredientSelectors[1] = new IngredientSelector(
layout.findViewById(R.id.ingredientSelector2),
this,
recipe,
1);
ingredientSelectors[2] = new IngredientSelector(
layout.findViewById(R.id.ingredientSelector3),
this,
recipe,
2);
graphBars[0] = new GraphBar(layout.findViewById(R.id.sweetness),
"SWEETNESS",
recipe);
graphBars[1] = new GraphBar(layout.findViewById(R.id.sourness),
"SOURNESS",
recipe);
graphBars[2] = new GraphBar(layout.findViewById(R.id.flavor),
"FLAVOR",
recipe);
graphBars[3] = new GraphBar(layout.findViewById(R.id.novelty),
"NOVELTY",
recipe);
updateValues();
}
//Getters
public int getOuncesRemainingValue() {
return ouncesRemainingValue;
}
public void updateValues() {
//Calculate ounces remaining
ouncesRemainingValue = 16-recipe.getQuantitySum();
//Set ounces remaing string
ouncesRemaining.setText(String.format(Locale.US, "%d", ouncesRemainingValue));
//Adjust color of ouncesRemaing TextView to reflect value
if(ouncesRemainingValue == 0)
ouncesRemaining.setTextColor(ContextCompat.getColor(layout.getContext(),
R.color.colorTextBright));
else
ouncesRemaining.setTextColor(ContextCompat.getColor(layout.getContext(),
R.color.colorTextLight));
//Update sweetness
graphBars[0].setBarValue(0.3f);
}
}
IngredientSelector
updateValues()
方法:
public void updateValues(int quantityValue) {
quantity.setText(String.format(Locale.US,
"%d ounce%s",
quantityValue,
quantityValue == 1 ? "" : "s"));
totalCost.setText(String.format(Locale.US,
"$%3.2f",
quantityValue*ingredient.getPricePerOunce()));
recipe.setQuantityValue(index, quantityValue);
recipeEditor.updateValues();
}
GraphBar
setBarValue()
方法:
public void setBarValue(float value) {
//final TableRow.LayoutParams params = new TableRow.LayoutParams(0, TableRow.LayoutParams.MATCH_PARENT, );
TableRow.LayoutParams params = new TableRow.LayoutParams(0,
TableRow.LayoutParams.MATCH_PARENT,
value);
//params = (TableRow.LayoutParams) filled.getLayoutParams();
//params.weight = value;
filled.setLayoutParams(params);
//empty.setLayoutParams(new TableRow.LayoutParams(0,
//TableRow.LayoutParams.MATCH_PARENT,
//1.0f-value));
}
堆栈追踪:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void darnell.coldpresstycoon.GraphBar.setBarValue(float)' on a null object reference
at darnell.coldpresstycoon.RecipeEditor.updateValues(RecipeEditor.java:93)
at darnell.coldpresstycoon.IngredientSelector.updateValues(IngredientSelector.java:92)
at darnell.coldpresstycoon.IngredientSelector.<init>(IngredientSelector.java:60)
at darnell.coldpresstycoon.RecipeEditor.<init>(RecipeEditor.java:35)
at darnell.coldpresstycoon.Dialogs.RecipeDialog.<init>(RecipeDialog.java:40)
at darnell.coldpresstycoon.MainActivity.onCreate(MainActivity.java:96)
我是Stack Overflow的新成员,所以如果我的问题格式错误或过于冗长,我会道歉。
答案 0 :(得分:2)
查看stacktrace中的调用堆栈:
at darnell.coldpresstycoon.RecipeEditor.updateValues(RecipeEditor.java:93)
at darnell.coldpresstycoon.IngredientSelector.updateValues(IngredientSelector.java:92)
at darnell.coldpresstycoon.IngredientSelector.<init>(IngredientSelector.java:60)
at darnell.coldpresstycoon.RecipeEditor.<init>(RecipeEditor.java:35)
RecipeEditor
构造函数调用IngredientSelector
构造函数,该构造函数调用IngredientSelector.updateValues()
,在构造{{1}之前调用RecipeEditor.updateValue()
,完成了。
阵列尚未初始化。
重新思考你的逻辑。