views:

305

answers:

3

Hi!

This is my code:

final String run_tool ="cmd.exe /C pelda.exe";
final Process tool_proc = null;

Runnable doRun = new Runnable() {
    public void run() {
        try {
            tool_proc = Runtime.getRuntime().exec(run_tool);
            } 
        catch (IOException e) {
            e.printStackTrace();
        }
    }
};    

Thread th = new Thread(doRun);
th.start();

InputStream toolstr = tool_proc.getInputStream();

After the eclipse gives this warning message fot the tool_proc variable:

The final local variable tool_proc cannot be assigned, since it is defined in an enclosing type

I dont't know why my code doesn't work

please help me

A: 

Initial value of final field cannot be changed. Remove final modificator from tool_proc:

Process tool_proc = null;
Dmitry
This will not work either, because the variable is not defined within the scope of the defined class `Runnable`. You could define a private field in the parent class.
Paul Lammertsma
+2  A: 

The tool_proc variable is final - final variables can only be assigned once, and you already assigned it the value null in the declaration. Removing the null assignment won't work because the runnable can be called more than once, resulting in multiple assignment. So your best option is to remove the final keyword and it should compile, at least:

Kevin K
Just now noticed you're dealing with a local variable, so you can't just remove the `final` keyword. See Paul's solution, he explains it there.
Kevin K
+2  A: 

The final modifier forbids changing the variable once it has been set. Kevin gives an excellent explanation of why you can't use it in this context.

The construction you have chosen for requires you to introduce a field in the parent class and set it via run():

class MyClass {
    Process tool_proc = null;

    void myFunction() {
        final String run_tool ="cmd.exe /C pelda.exe";
        Runnable doRun = new Runnable() {
            public void run() {
                try {
                    tool_proc = Runtime.getRuntime().exec(run_tool);
                    } 
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread th = new Thread(doRun);
        th.start();

        // tool_proc will be null at this point!
        InputStream toolstr = tool_proc.getInputStream();
    }
}

In the above code I have demonstrated that tool_proc will always be null on the last line, as the thread has in all liklihood not finished its execution by this time!

You can expect NullPointerExceptions!


It seems what you are trying to do is very similar to this article about capturing application output asynchronously. It's a good read, and explains why conventional approaches can cause problems. I have an implementation very similar to their StreamGobbler (article page 4).

Paul Lammertsma
You can add tool_proc.waitfor() before the getInputStream() line to fix the NullPointerException.
rob
That will not work either, as the variable hasn't been instantiated yet. You can't call a function on an empty pointer.
Paul Lammertsma