abstract方法可以直接调用?
先看一段代码:
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 emptyString 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方法。
abstract方法可以直接调用?相关推荐
- Virtual方法和Abstract方法的使用区别
一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类 ...
- java 子类的同名方法_java 父类子类有同名方法时如何调用的实现
父类引用默认调用子类重写的方法 如果父类的引用p指向了子类的实例,则通过这个引用p访问同名方法时,调用的是子类重写的方法. 父类引用p可以指向不同的子类,调用不同子类重写的不同的同名方法,进而达到类间 ...
- 温故而知新:new与override的差异以及virtual方法与abstract方法的区别
先直接看代码吧: using System;namespace ConsoleApplication1 {class Program{static void Main(string[] args){B ...
- 零基础入门 自学 JAVA SE 基础篇(九)instanceof final 开闭原则 多态 抽象(abstract)方法与抽象类 接口(interface)
JAVA SE自学 基础篇 多态 instanceof final 开闭原则 多态 抽象(abstract)方法与抽象类 接口(interface) 目标 父类型与子类型之间的转换及instanceo ...
- Java学习之路3——方法定义、调用【重拾Java】
Java学习之路3--方法定义.调用[重拾Java] 方法定义 为什么要写方法 方法完整的定义形式.调用 方法定义的格式 修饰符 返回值类型 返回值 调用格式 方法重载 方法定义 为什么要写方法 对于 ...
- virtual方法和abstract方法的使用(轉載)
在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用.一.Virtual方法(虚方法)virtual 关 ...
- java 父类子类有同名方法时如何调用
父类引用默认调用子类重写的方法 如果父类的引用p指向了子类的实例,则通过这个引用p访问同名方法时,调用的是子类重写的方法. 父类引用p可以指向不同的子类,调用不同子类重写的不同的同名方法,进而达到类间 ...
- abstract 类和 abstract 方法 (抽象类与抽象方法)
抽象一直以来都是人们所神往的艺术形式,这点从梵高,毕加索等艺术家的身上就可以看出.抽象所代表的是一种形式上的美感,颇有一种虚无缥缈只可意会不可言传的意味.但是JAVA中的抽象类与抽象方法相对而言就更加 ...
- 笔记 16 abstract类和abstract方法
abstract 类 用关键字abstract修饰的类称为abstract类(抽象类). abstract class A{ ........ } 用关键字abstract修饰的方法称为abstrac ...
最新文章
- 用python画爱心的代码-Python一行代码画个爱心案例
- 【深度好文】多线程之WaitHandle--派生EventWaitHandle事件构造-》AutoResetEvent、ManualResetEvent...
- 最接近的三数之和Python解法
- 埋点是什么意思_(一百二十二)埋点方案举例,如何做埋点方案
- mysql cluster安装配置_mysqlcluster安装与配置_MySQL
- 忍者X2简介+安装包+安装环境说明 [复制链接]
- 连接mysql的各种方式
- java 异步编程 CompletableFuture
- 机关事业单位考勤统计和活动抽奖小程序
- 容器化运行wine模拟器制作开源代码索引chm文件
- rest-assured一些使用心得
- arduino nano关于microUSB无法用的处理
- 飞塔防火墙密码忘记重置方法
- 删除按升序排列的单链表中的重复元素
- 邮件退回 对方服务器不允许,主 题:我给别人发的邮件被退回来了如何处理?...
- MATLAB处理EXCEL文件
- 小半斤拔凉 支付Java 相关参考
- 【智能制造】智能生产:智能制造的主线
- 架构设计文档提纲简描
- 后台管理系统2——文件上传功能、富文本编辑器集成