Java NullPointerException写入一个长字段-(对某些人来说这似乎有点数学负担)?

Java NullPointerException写入一个长字段-(对某些人来说这似乎有点数学负担)?,java,android,nullpointerexception,Java,Android,Nullpointerexception,写long返回的NPE意味着计算阶乘 输入参数后,按下按钮,TextView将返回结果 真的很简单…(我在做梦) long是名为ComputationRange的静态类中的私有字段 ComputationRange在exercies4(一个片段)类中,该类具有计算阶乘的所有业务逻辑,并连接到UI 日志清楚地表明,第237行返回了NULLPOINTEREXCEPTION,之后会出现进一步的错误 如需进一步信息,请直接询问 我会把这个班包括在这里 在initThreadComputationRa

写long返回的NPE意味着计算阶乘

输入参数后,按下按钮,TextView将返回结果

真的很简单…(我在做梦)

long是名为ComputationRange的静态类中的私有字段

ComputationRange在exercies4(一个片段)类中,该类具有计算阶乘的所有业务逻辑,并连接到UI

日志清楚地表明,第237行返回了NULLPOINTEREXCEPTION,之后会出现进一步的错误

如需进一步信息,请直接询问

我会把这个班包括在这里




initThreadComputationRanges()
中,您没有在
mThreadsComputationRanges[0]
中实例化对象,而是尝试写入其
开始
字段。for循环only inits index>0。

哪一行是第237行?并且请添加堆栈跟踪只能是这一行
mComputationTimeoutTime=System.currentTimeMillis()+timeOut但超时类型为
int
,并且
currentTimeMillis()
返回
long
。看不到NPE:-(
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)