【发布时间】:2019-11-24 18:00:20
【问题描述】:
从写入 long 返回的 NPE 旨在计算 Factorial。
输入参数,按下按钮,TextView 应该返回结果。
真的很简单....(我在做梦吗)。
long 是名为 ComputationRange 的静态类中的私有字段。
ComputationRange 位于 Exericse4(片段)类中,该类具有计算阶乘的所有业务逻辑并连接到 UI。
日志清楚地表明 NULLPOINTEREXCEPTION 在第 237 行返回,然后进一步的错误出现。
如果需要任何进一步的信息,请尽管询问。
我将在此处包含课程
public class Exercise4Fragment extends BaseFragment {
public static Fragment newInstance() {
return new Exercise4Fragment();
}
private static int MAX_TIMEOUT_MS = 1000;
private final Handler mUiHandler = new Handler(Looper.getMainLooper());
private EditText mEdtArgument;
private EditText mEdTimeOut;
private Button mBtnStart;
private TextView mtxtResult;
private int mNumberOfThreads;
private ComputationRange[] mThreadsComputationRanges;
private volatile BigInteger[] mThreadsCOmputationResults;
private final AtomicInteger mNumOfFinishedThreads = new AtomicInteger(0);
private long mComputationTimeoutTime;
private volatile boolean mAbortComputation;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_exercise_4, container, false);
mEdtArgument = view.findViewById(R.id.edt_argument);
mEdTimeOut = view.findViewById(R.id.edt_timeout);
mBtnStart = view.findViewById(R.id.btn_compute);
mtxtResult = view.findViewById(R.id.txt_result);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mEdtArgument.getText().toString().isEmpty()) {
return;
}
mtxtResult.setText("");
mBtnStart.setEnabled(false);
InputMethodManager imm =
(InputMethodManager) requireContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mBtnStart.getWindowToken(), 0);
int argument = Integer.valueOf(mEdtArgument.getText().toString());
computeFactorial(argument, getTimeOut());
}
});
return view;
}
private void computeFactorial(final int argument,final int timeOut) {
new Thread(() -> {
initComputationParams(argument, timeOut);
startComputation();
waitForThreadsResultsOrTimeoutOrAbort();
processComputationResults();
}).start();
}
@WorkerThread
private void processComputationResults() {
String resultString;
if(mAbortComputation){
resultString = "Computation aborted";
}
else {
resultString = computeFinalResult().toString();
}
if(isTimeOut()) {
resultString = "Computation timed out";
}
final String finalResutString = resultString;
mUiHandler.post(() -> {
if(!Exercise4Fragment.this.isStateSaved()) {
mtxtResult.setText(finalResutString);
mBtnStart.setEnabled(true);
}
});
}
private BigInteger computeFinalResult() {
BigInteger result = new BigInteger("1");
for(int i = 0; i < mNumberOfThreads; i++) {
if(isTimeOut()) {
break;
}
result = result.multiply(mThreadsCOmputationResults[i]);
}
return result;
}
@WorkerThread
private void waitForThreadsResultsOrTimeoutOrAbort() {
while(true) {
if(mNumOfFinishedThreads.get() == mNumberOfThreads) {
break;
} else if(mAbortComputation) {
break;
} else if(isTimeOut()) {
break;
} else {
try {
Thread.sleep(100);
}catch (InterruptedException e) {
}
}
}
}
@WorkerThread
private void startComputation() {
for(int i = 0; i < mNumberOfThreads; i++) {
final int threadIndex = i;
new Thread(() -> {
long rangeStart = mThreadsComputationRanges[threadIndex].start;
long rangeEnd = mThreadsComputationRanges[threadIndex].end;
BigInteger product = new BigInteger("1");
for(long num = rangeStart; num <= rangeEnd; num++) {
if(isTimeOut()) {
break;
}
product = product.multiply(new BigInteger(String.valueOf(num)));
}
mThreadsCOmputationResults[threadIndex] = product;
mNumOfFinishedThreads.incrementAndGet();
}).start();
}
}
private boolean isTimeOut() {
return System.currentTimeMillis() >= mComputationTimeoutTime;
}
private void initComputationParams(int argument, int timeOut) {
mNumberOfThreads = argument < 20 ? 1 : Runtime.getRuntime().availableProcessors();
mNumOfFinishedThreads.set(0);
mAbortComputation = false;
mThreadsCOmputationResults = new BigInteger[mNumberOfThreads];
mThreadsComputationRanges = new ComputationRange[mNumberOfThreads];
initThreadComputationRanges(argument);
mComputationTimeoutTime = System.currentTimeMillis() + timeOut;
}
private void initThreadComputationRanges(int argument) {
int computationRangeSize = argument / mNumberOfThreads;
long nextComputationRangeEnd = argument;
for(int i = mNumberOfThreads -1; i > 0; i--) {
mThreadsComputationRanges[i] = new ComputationRange(
nextComputationRangeEnd - computationRangeSize + 1,
nextComputationRangeEnd
);
nextComputationRangeEnd = mThreadsComputationRanges[i].start -1;
}
mThreadsComputationRanges[0].start = 1;
}
@Override
protected String getScreenTitle() {
return "Exercise 4";
}
@Override
public void onStop() {
super.onStop();
mAbortComputation = true;
}
private int getTimeOut() {
int timeOut;
if(mEdTimeOut.getText().toString().isEmpty()) {
timeOut = MAX_TIMEOUT_MS;
} else {
timeOut = Integer.valueOf(mEdTimeOut.getText().toString());
if(timeOut > MAX_TIMEOUT_MS) {
timeOut = MAX_TIMEOUT_MS;
}
}
return timeOut;
}
private static class ComputationRange{ // This line returns Null
private long start;
private long end;
public ComputationRange(long start, long end) {
this.start = start;
this.end = end;
}
}
}
java.lang.NullPointerException: Attempt to write to field 'long com.multithread.exrecises.exercise4.Exercise4Fragment$ComputationRange.start' on a null object reference
at com.multithread.exrecises.exercise4.Exercise4Fragment$ComputationRange.access$502(Exercise4Fragment.java:237)
at com.multithread.exrecises.exercise4.Exercise4Fragment.initThreadComputationRanges(Exercise4Fragment.java:209)
【问题讨论】:
-
第 237 行是哪一行?请添加堆栈跟踪
-
只能是这一行
mComputationTimeoutTime = System.currentTimeMillis() + timeOut;但timeOut 是int类型,currentTimeMillis()返回long。看不到 NPE :-(
标签: java android nullpointerexception