【问题标题】:NullPointerException writing to a field which is a long - (To some this may seem a bit Math heavy)? [duplicate]NullPointerException 写入一个很长的字段 - (对某些人来说,这可能看起来有点数学重)? [复制]
【发布时间】: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)

https://github.com/BenMohammad/MultiThread

【问题讨论】:

  • 第 237 行是哪一行?请添加堆栈跟踪
  • 只能是这一行mComputationTimeoutTime = System.currentTimeMillis() + timeOut; 但timeOut 是int 类型,currentTimeMillis() 返回long。看不到 NPE :-(

标签: java android nullpointerexception


【解决方案1】:

initThreadComputationRanges() 中,您没有在mThreadsComputationRanges[0] 中实例化对象,而是在尝试写入其start 字段。 for 循环仅初始化索引 > 0。

【讨论】:

    猜你喜欢
    • 2013-05-13
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多