abstract方法可以直接调用?

来源:互联网 发布:网络统考英语在线" 编辑:程序博客网 时间:2024/06/03 00:33

先看一段代码:

import java.io.IOException;public class RuntimeTest {public static void main(String[] args) throws IOException, InterruptedException{Process p=Runtime.getRuntime().exec("notepad.exe");p.waitFor();System.out.println("end!");}

查看文档,发现Process类的waitFor()方法是一个abstract方法。可是为什么可以直接调用啊???

恩,直觉上想,应该是下面这行代码,实际返回的是Process类的一个子类,在子类中重写了waitFor()方法。

Runtime.getRuntime().exec("notepad.exe");
那实际情况呢?我们查看下源码JDK1.5:

Runtime的源码,重载了好几个exec方法,但所有的exec方法都是调用下面这个方法来实现的。

    public Process exec(String[] cmdarray, String[] envp, File dir)        throws IOException {        return new ProcessBuilder(cmdarray)            .environment(envp)            .directory(dir)            .start();    }

那我们再来查看ProcessBuilder的start方法源码:

  public Process start() throws IOException {        // Must convert to array first -- a malicious user-supplied        // list might try to circumvent the security check.        String[] cmdarray = command.toArray(new String[command.size()]);        cmdarray = cmdarray.clone();        for (String arg : cmdarray)            if (arg == null)                throw new NullPointerException();        // Throws IndexOutOfBoundsException if command is empty        String prog = cmdarray[0];        SecurityManager security = System.getSecurityManager();        if (security != null) {            security.checkExec(prog);        }        String dir = directory == null ? null : directory.toString();        try {            return ProcessImpl.start(cmdarray,                                     environment,                                     dir,                                     redirects,                                     redirectErrorStream);        } catch (IOException | IllegalArgumentException e) {            String exceptionInfo = ": " + e.getMessage();            Throwable cause = e;            if ((e instanceof IOException) && security != null) {                // Can not disclose the fail reason for read-protected files.                try {                    security.checkRead(prog);                } catch (AccessControlException ace) {                    exceptionInfo = "";                    cause = ace;                }            }            // It's much easier for us to create a high-quality error            // message than the low-level C code which found the problem.            throw new IOException(                "Cannot run program \"" + prog + "\""                + (dir == null ? "" : " (in directory \"" + dir + "\")")                + exceptionInfo,                cause);        }    }
可以看到,返回的是:ProcessImpl.start(cmdarray,environment,dir, redirects, redirectErrorStream);,那就再查看ProcessImpl类的源码。

package java.lang;import java.io.IOException;import java.io.File;import java.io.InputStream;import java.io.OutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileDescriptor;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.lang.ProcessBuilder.Redirect;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.ArrayList;import java.util.regex.Matcher;import java.util.regex.Pattern;/* This class is for the exclusive use of ProcessBuilder.start() to * create new processes. * * @author Martin Buchholz * @since   1.5 */final class ProcessImpl extends Process {<pre name="code" class="java">/**中间部分代码省略*/
// System-dependent portion of ProcessBuilder.start()    static Process start(String cmdarray[],                         java.util.Map<String,String> environment,                         String dir,                         ProcessBuilder.Redirect[] redirects,                         boolean redirectErrorStream)        throws IOException    {        String envblock = ProcessEnvironment.toEnvironmentBlock(environment);        FileInputStream  f0 = null;        FileOutputStream f1 = null;        FileOutputStream f2 = null;        try {            long[] stdHandles;            if (redirects == null) {                stdHandles = new long[] { -1L, -1L, -1L };            } else {                stdHandles = new long[3];                if (redirects[0] == Redirect.PIPE)                    stdHandles[0] = -1L;                else if (redirects[0] == Redirect.INHERIT)                    stdHandles[0] = fdAccess.getHandle(FileDescriptor.in);                else {                    f0 = new FileInputStream(redirects[0].file());                    stdHandles[0] = fdAccess.getHandle(f0.getFD());                }                if (redirects[1] == Redirect.PIPE)                    stdHandles[1] = -1L;                else if (redirects[1] == Redirect.INHERIT)                    stdHandles[1] = fdAccess.getHandle(FileDescriptor.out);                else {                    f1 = newFileOutputStream(redirects[1].file(),                                             redirects[1].append());                    stdHandles[1] = fdAccess.getHandle(f1.getFD());                }                if (redirects[2] == Redirect.PIPE)                    stdHandles[2] = -1L;                else if (redirects[2] == Redirect.INHERIT)                    stdHandles[2] = fdAccess.getHandle(FileDescriptor.err);                else {                    f2 = newFileOutputStream(redirects[2].file(),                                             redirects[2].append());                    stdHandles[2] = fdAccess.getHandle(f2.getFD());                }            }            return new ProcessImpl(cmdarray, envblock, dir,                                   stdHandles, redirectErrorStream);        } finally {            // In theory, close() can throw IOException            // (although it is rather unlikely to happen here)            try { if (f0 != null) f0.close(); }            finally {                try { if (f1 != null) f1.close(); }                finally { if (f2 != null) f2.close(); }            }        }
/*
*中间部分代码省略
*/
     public int waitFor() throws InterruptedException {        waitForInterruptibly(handle);        if (Thread.interrupted())            throw new InterruptedException();        return exitValue();    }    private static native void waitForInterruptibly(long handle);}
可以看出,ProcessImpl类是Process类的一个子类,start方法最后返回了一个ProcessImpl对象。而且ProcessImpl重写了waitFor方法。


0 0