- 浏览: 328197 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
y_715:
document.getElementById("e ...
JSTL EC TABLE extremeTable 学习 -
wangyj0898:
学习了。。。
display table 标签用法 -
hejiajie2008:
没有图啊
图解myeclipse把maven普通java项目变成web项目的全程操作 -
zhangyu_2100:
[align=center][/align][color=br ...
request.getRealPath()的替代方法 -
senhui19:
LZ写的真不错呀,现在开发中都经常是用DetachedCrit ...
Hibernate的Criteria用法总结
类是广泛的概念,表示一个有共同性质的群体,而对象指的是具体的一个实实在在的东西。例如,“人”是一个类,它可以表示地球上所有的人;而“张三”、“李四”、“爱因斯坦”等则是一个个的对象,或者说它们是“人”这个类的一个个实例。在 Java 中,我们可以定义类,然后创建类的对象。
例如:
// 声明一个类“Human”
class Human{
private String name;
public String getName(){
return name;
}
public void setName(String value){
this.name = value;
}
//......
}
创建一个类:
Human human = new Human();
其次,很多人对对象和对象的引用认识模糊
引用是程序操作对象的句柄,相当于C和C++中的指针。
前面说了,对象是一个实实在在的东西,比如前面的代码:
Human human = new Human();
程序执行到这里之后,java虚拟机将会在内存中创建一个 Human 对象,并将这个对象的引用赋给 human 变量。这里有两步,首先是创建 Human 对象,然后把创建的对象的引用赋给 human 变量。
如果声明了一个对象的引用,但没有将对象赋值给它,则这个引用指向了空的对象,或者说引用了不存在的对象。这时如果想通过这个引用访问对象,则会抛出空指针异常,例如:
Human human;
//......
human.setName("张三");
下面重点谈一谈类、抽象类、接口和继承之间的关系
不少细心的初学者在论坛上问类似这样的问题:
1、接口不实现方法,但我却在程序中可以调用接口的方法,这是为什么?比如 java.sql 包中的 Connection、Statement、ResultSet 等都是接口,怎么可以调用 它们的方法呢?
2、抽象类不能实例化,但是jdk中却有很多抽象类的对象,这是为什么?比如 System.in 是一个 InputStream 类型对象,但 InputStream 是抽象类,怎么可以得到它的对象呢?
不管怎么样,大家应该明白一点:不管是抽象类中的抽象方法,还是接口中定义的方法,都是需要被调用的,否则这些方法定义出来就没有意义了。
可能有很多书上没有提到,或者提到了而读者没有注意到这一点:
一个子类如果继承了它的基类,则表示这个类也是其基类的一种类型,这个子类的一个对象是子类类型,并且同时也是其基类的一个对象,它也具有基其类的类型;一个类如果实现了一个接口,则表示这个类的一个对象也是这个接口的一个对象。
可能这样说不太好懂,又是子类、基类、类型、接口什么的,容易搞混。其实举个现实的例子你就会觉得其实很简单:
如果“人”是一个基类,则“男人”是“人”的一个子类。如果“张三”是一个“男人”,也就是说“张三”是“男人”的一个对象,那么显然“张三”也是“人”这个基类的一个对象。
明白了这一点,就容易理解为什么我们可以得到抽象类的对象了:原来我们得到的抽象类的对象其实是它的已经实现了抽象方法的子类或子孙类的一个对象,但我们拿它当它的抽象类的基类来用。比如“人”这个类,每个人都会“悲伤”,男人悲伤的时候抽烟、喝酒,女人悲伤的时候哭泣、流泪。由于不同的子类在“悲伤”时所进行的动作不一样,因此这个动作(方法)在基类中不好实现,但基类中又需要有这个方法,因此,“人”这个类就可以定义一个抽象方法“悲伤”,由其子类“男人”和“女人”来实现“悲伤”这个方法。但是调用者只把男人和女人的对象当作其基类“人”的一个对象,调用它的“悲伤”方法。
读者可以去体验一下 jdk 的抽象类 java.lang.Process :
Runtime runtime = Rumtime.getRuntime();
Process process = rumtime.exec("notepad.exe");
Class cls = process.getClass();
System.out.println(cls.getName());
这时会打印出 process 类的名字,如果在 Windows 下它会是一个类似于 *Win32* 的名字,它是 Process 的一个子类。因为 process 类用于管理打开的进程,而在不同的操作系统上都有不同的实现,因此它把方法定义为 Process 的抽象方法,而具体的操作只能由对应在不同操作系统下的子实现。
下面来谈接口,我们知道接口只定义了一些方法,而没有实现这些方法。而其实,接口是一个规范,它规定了实现这个接口所要做的事情,或者说规定了实现接口的类必须具备的能力(也就是方法)。
那么我们可以这样对比:
某种类型的驾驶执照,规定了拿到这个驾照的人必须能够“开小汽车”和“开公共汽车”。那么我们认为这个驾照是一个接口,它规定了实现它的类所必须有的能力。
我们可以定义一个类 Driver,继承自 Human,然后实现“驾照持有者”这个接口:
public interface DriverHolder{
public void driverCar();
public void driverBus();
}
public class Driver extends Human implements DriverHolder{
public void driverCar(){
// ......
}
public void driverBus(){
// ......
}
}
这样一来,一个“Driver”对象,它同时也是一个 DrivreHolder 对象。即一个司机(Driver)同时是一个驾照执持有者对象。在程序中我们可以这样:
DriverHolder driverholder = new Driver();
driverholder.driverCar();
这样我们就解释了为什么“接口没有实现方法,却可以得到接口类的对象”的问题。
但是这样一来,肯定有人会问:为什么要定义一个接口呢,为什么不直接把这个方法定义到 Driver 类中去,然后 Driver driver = new Driver(); 一样可以调用它的 driverCar(); 和 driverBus() 方法,这样做岂不是方便得多?
这是因为java是单继承的,它只能继承于一个类,这样它的类型就只限于其基类或者基类的基类。但是java可以实现多个接口,这样它就可以有很多个接口的类型。就象一个人,它继承自“脊椎动物”这个类,而“脊椎动物”又继承自“动物”这个类,因此“张三”是个人,他是一个“脊椎动物”,当然他也是一个“动物”。但他可以继承很多个接口,比如拿驾驶执照之后,他就是“驾照持有者”类型,他也可以拿英语六级证书,这样他就是一个六级证书持有者等等。
明白这一点之后,我们来看一看 java 的事件机制。
java.awt.Button 类有一个 addActionListener(ActionListener l);方法。这个方法传入的是一个接口类型:ActionListerner,在实际中,我们需要实现 ActionListener 接口,并且把实现这个接口的类的对象引用作为参数传入。这样,Button对象就得到了一个 ActionListener 对象,它知道这个 ActionListener 对象有一个 actionPerformed 方法,或者说它有处理 Action 事件的能力,当 Action 事件发生时,它就可以调用这个对象的 actionPerformed 方法。
比如一般我们会这样做:
public class TestButton extends Frame implements ActionListener{
private Button btn1 = new Button();
//......
public TestButton(){
btn.addActionListener(this);
this.add(btn);
}
public void actionPerformed(ActionEvent e){
}
}
现在我们假设 ActionListener 不是接口,而是一个类。那么我们只能继承 ActionListener 类,并且重写 actionPerformed 方法。但是java是单继承的,如果类继承了 ActionListener 类,那么它就不能继承其它的类(Frame 类)了,而不从 Frame 类继承的话,又怎么创建窗体,怎么把 Button 放到窗体中去呢?
其实接口不完全是为了解决 java 的单继承问题,它在某种程度上可以达到调用和实现细节的分离。
比如说,中国的民用电规范是一个接口:平均电压220V、50Hz、Sin 交流电,水力发电厂、火力发电厂、核电厂,还有小型的柴油发电机如果按这个规范发电,则表示它们实现了这个民用电源的接口;冰箱、电视、洗衣机等家用电器使用这些电源,表示它们在调用这个接口。在这里,家用电器不管电从哪里来,只要它符合民用电源的规范就好,电源也不管它发的电用于什么工作,只管提供电源。
再回过头来看看 Button 的事件机制。要知道,Button 要保证所有的 action 事件发生时,程序员都可以在他的代码中处理它,图书馆管理系统、收银系统、进销存等等等等等等。而接口就可以做到这一点:找一个类实现 ActionListener 接口,并且让 Button 得到这个类的对象的引用( 调用 addActionListener 方法),从而当Action事件发生时,button 创建一个包含了事件信息的对象(ActionEvent),然后调用这个接口对象的方法,到底怎么处理这次事件,这就是实现接口的类的事情了。在这里,Button 丝毫不了解 actionPerformed 方法中到底干了什么事情,也不应该知道。Button 与具体的业务逻辑完全分离开了,它可以应用到所有的场合。
例如:
// 声明一个类“Human”
class Human{
private String name;
public String getName(){
return name;
}
public void setName(String value){
this.name = value;
}
//......
}
创建一个类:
Human human = new Human();
其次,很多人对对象和对象的引用认识模糊
引用是程序操作对象的句柄,相当于C和C++中的指针。
前面说了,对象是一个实实在在的东西,比如前面的代码:
Human human = new Human();
程序执行到这里之后,java虚拟机将会在内存中创建一个 Human 对象,并将这个对象的引用赋给 human 变量。这里有两步,首先是创建 Human 对象,然后把创建的对象的引用赋给 human 变量。
如果声明了一个对象的引用,但没有将对象赋值给它,则这个引用指向了空的对象,或者说引用了不存在的对象。这时如果想通过这个引用访问对象,则会抛出空指针异常,例如:
Human human;
//......
human.setName("张三");
下面重点谈一谈类、抽象类、接口和继承之间的关系
不少细心的初学者在论坛上问类似这样的问题:
1、接口不实现方法,但我却在程序中可以调用接口的方法,这是为什么?比如 java.sql 包中的 Connection、Statement、ResultSet 等都是接口,怎么可以调用 它们的方法呢?
2、抽象类不能实例化,但是jdk中却有很多抽象类的对象,这是为什么?比如 System.in 是一个 InputStream 类型对象,但 InputStream 是抽象类,怎么可以得到它的对象呢?
不管怎么样,大家应该明白一点:不管是抽象类中的抽象方法,还是接口中定义的方法,都是需要被调用的,否则这些方法定义出来就没有意义了。
可能有很多书上没有提到,或者提到了而读者没有注意到这一点:
一个子类如果继承了它的基类,则表示这个类也是其基类的一种类型,这个子类的一个对象是子类类型,并且同时也是其基类的一个对象,它也具有基其类的类型;一个类如果实现了一个接口,则表示这个类的一个对象也是这个接口的一个对象。
可能这样说不太好懂,又是子类、基类、类型、接口什么的,容易搞混。其实举个现实的例子你就会觉得其实很简单:
如果“人”是一个基类,则“男人”是“人”的一个子类。如果“张三”是一个“男人”,也就是说“张三”是“男人”的一个对象,那么显然“张三”也是“人”这个基类的一个对象。
明白了这一点,就容易理解为什么我们可以得到抽象类的对象了:原来我们得到的抽象类的对象其实是它的已经实现了抽象方法的子类或子孙类的一个对象,但我们拿它当它的抽象类的基类来用。比如“人”这个类,每个人都会“悲伤”,男人悲伤的时候抽烟、喝酒,女人悲伤的时候哭泣、流泪。由于不同的子类在“悲伤”时所进行的动作不一样,因此这个动作(方法)在基类中不好实现,但基类中又需要有这个方法,因此,“人”这个类就可以定义一个抽象方法“悲伤”,由其子类“男人”和“女人”来实现“悲伤”这个方法。但是调用者只把男人和女人的对象当作其基类“人”的一个对象,调用它的“悲伤”方法。
读者可以去体验一下 jdk 的抽象类 java.lang.Process :
Runtime runtime = Rumtime.getRuntime();
Process process = rumtime.exec("notepad.exe");
Class cls = process.getClass();
System.out.println(cls.getName());
这时会打印出 process 类的名字,如果在 Windows 下它会是一个类似于 *Win32* 的名字,它是 Process 的一个子类。因为 process 类用于管理打开的进程,而在不同的操作系统上都有不同的实现,因此它把方法定义为 Process 的抽象方法,而具体的操作只能由对应在不同操作系统下的子实现。
下面来谈接口,我们知道接口只定义了一些方法,而没有实现这些方法。而其实,接口是一个规范,它规定了实现这个接口所要做的事情,或者说规定了实现接口的类必须具备的能力(也就是方法)。
那么我们可以这样对比:
某种类型的驾驶执照,规定了拿到这个驾照的人必须能够“开小汽车”和“开公共汽车”。那么我们认为这个驾照是一个接口,它规定了实现它的类所必须有的能力。
我们可以定义一个类 Driver,继承自 Human,然后实现“驾照持有者”这个接口:
public interface DriverHolder{
public void driverCar();
public void driverBus();
}
public class Driver extends Human implements DriverHolder{
public void driverCar(){
// ......
}
public void driverBus(){
// ......
}
}
这样一来,一个“Driver”对象,它同时也是一个 DrivreHolder 对象。即一个司机(Driver)同时是一个驾照执持有者对象。在程序中我们可以这样:
DriverHolder driverholder = new Driver();
driverholder.driverCar();
这样我们就解释了为什么“接口没有实现方法,却可以得到接口类的对象”的问题。
但是这样一来,肯定有人会问:为什么要定义一个接口呢,为什么不直接把这个方法定义到 Driver 类中去,然后 Driver driver = new Driver(); 一样可以调用它的 driverCar(); 和 driverBus() 方法,这样做岂不是方便得多?
这是因为java是单继承的,它只能继承于一个类,这样它的类型就只限于其基类或者基类的基类。但是java可以实现多个接口,这样它就可以有很多个接口的类型。就象一个人,它继承自“脊椎动物”这个类,而“脊椎动物”又继承自“动物”这个类,因此“张三”是个人,他是一个“脊椎动物”,当然他也是一个“动物”。但他可以继承很多个接口,比如拿驾驶执照之后,他就是“驾照持有者”类型,他也可以拿英语六级证书,这样他就是一个六级证书持有者等等。
明白这一点之后,我们来看一看 java 的事件机制。
java.awt.Button 类有一个 addActionListener(ActionListener l);方法。这个方法传入的是一个接口类型:ActionListerner,在实际中,我们需要实现 ActionListener 接口,并且把实现这个接口的类的对象引用作为参数传入。这样,Button对象就得到了一个 ActionListener 对象,它知道这个 ActionListener 对象有一个 actionPerformed 方法,或者说它有处理 Action 事件的能力,当 Action 事件发生时,它就可以调用这个对象的 actionPerformed 方法。
比如一般我们会这样做:
public class TestButton extends Frame implements ActionListener{
private Button btn1 = new Button();
//......
public TestButton(){
btn.addActionListener(this);
this.add(btn);
}
public void actionPerformed(ActionEvent e){
}
}
现在我们假设 ActionListener 不是接口,而是一个类。那么我们只能继承 ActionListener 类,并且重写 actionPerformed 方法。但是java是单继承的,如果类继承了 ActionListener 类,那么它就不能继承其它的类(Frame 类)了,而不从 Frame 类继承的话,又怎么创建窗体,怎么把 Button 放到窗体中去呢?
其实接口不完全是为了解决 java 的单继承问题,它在某种程度上可以达到调用和实现细节的分离。
比如说,中国的民用电规范是一个接口:平均电压220V、50Hz、Sin 交流电,水力发电厂、火力发电厂、核电厂,还有小型的柴油发电机如果按这个规范发电,则表示它们实现了这个民用电源的接口;冰箱、电视、洗衣机等家用电器使用这些电源,表示它们在调用这个接口。在这里,家用电器不管电从哪里来,只要它符合民用电源的规范就好,电源也不管它发的电用于什么工作,只管提供电源。
再回过头来看看 Button 的事件机制。要知道,Button 要保证所有的 action 事件发生时,程序员都可以在他的代码中处理它,图书馆管理系统、收银系统、进销存等等等等等等。而接口就可以做到这一点:找一个类实现 ActionListener 接口,并且让 Button 得到这个类的对象的引用( 调用 addActionListener 方法),从而当Action事件发生时,button 创建一个包含了事件信息的对象(ActionEvent),然后调用这个接口对象的方法,到底怎么处理这次事件,这就是实现接口的类的事情了。在这里,Button 丝毫不了解 actionPerformed 方法中到底干了什么事情,也不应该知道。Button 与具体的业务逻辑完全分离开了,它可以应用到所有的场合。
评论
1 楼
moses3017
2008-02-25
很不错的文章!
其实抽象类也可以做到这一点,但是由于java是单继承的,所有大部分情况下我们使用了接口!换句话说:接口可以实现这个功能,但出于单继承的约束,某些情况下又不得不使用接口!
引用
接口不完全是为了解决 java 的单继承问题,它在某种程度上可以达到调用和实现细节的分离
其实抽象类也可以做到这一点,但是由于java是单继承的,所有大部分情况下我们使用了接口!换句话说:接口可以实现这个功能,但出于单继承的约束,某些情况下又不得不使用接口!
发表评论
-
智力题
2010-08-27 10:56 1792A说:是B偷吃的,B说:是D偷吃的。C说;我没有偷吃。D说:B ... -
experience
2009-12-28 12:05 11651.报错信息 servlet-mapping配置的问题200 ... -
JDBC高级应用二
2009-12-28 11:33 997JDBC高级应用(二)本来想继续谈JDBC的高级连结方式,事务 ... -
在JAVA文件中获取该项目的相对路径
2009-11-12 14:36 14121.基本概念的理解 绝对路径:绝对路径就是你的主页上的文 ... -
明明白白Unsupported major.minor version 49.0的错误
2009-10-26 17:19 966一:要解决的问题 我们在尝鲜 JDK1.5 的时候,相信不少人 ... -
log4j详解
2009-09-02 13:04 845log4j.properties 使用 一.参数意义说明 输出 ... -
java 文件读取 路径问题
2009-08-25 15:23 15301.如何获得当前文件路径 常用: 字符串类型:System ... -
图解myeclipse把maven普通java项目变成web项目的全程操作
2009-08-05 20:06 3956图解myeclipse把maven普通java项目变成web项 ... -
浅谈java输入输出流(二)
2009-07-09 18:05 2394导读: stream代表的是任何有能力产出数据的数据源,或 ... -
浅谈java输入输出流(一)
2009-07-09 18:01 3099Java语言的输入输出功能是十分强大而灵活的,美中不足 ... -
常用Java开源库(新手必看)
2008-12-15 12:46 1759Jakarta common: Commons Logging ... -
浅谈Java内部类的四个应用场景
2008-12-15 12:44 930Java内部类是Java言语的一个很重要的概念,《Java编程 ... -
使用 HttpClient 和 HtmlParser 实现简易爬虫
2008-12-02 20:51 1431这篇文章介绍了 HtmlParse ... -
htmlparser使用指南
2008-11-28 13:10 2013转载:http://www.yeeach.com/2008/0 ... -
file的getPath getAbsolutePath和getCanonicalPath的不同
2008-09-16 09:12 1092file的这几个取得path的 ... -
JAVA使用winrar解压缩和解带有密码的压缩包的一个类
2008-09-05 13:38 2698通过使用winrar这个工具对文件进行操作。唯一 ... -
window.event的属性
2008-08-07 18:03 1639<script language="JavaS ... -
十个习惯让你精通新的开发技术(转)
2008-05-29 17:44 1048这篇文章,是从我的《 ... -
java汉字转换为拼音
2008-05-09 17:14 2033import java.util.Iterator;impor ... -
把JSP放到WEB-INF后以保护JSP源代码
2008-04-17 08:52 4621本人在看《J2EE核心模式》(“Core J2ee Patte ...
相关推荐
java类和对象练习题.docx
定义类、属性和方法 创建并使用对象、对象和引用 Java方法的参数传递机制 方法的重载 实现良好的封装 构造方法的作用和构造方法重载
Java类和对象入门级实例代码 Java类和对象入门级实例代码
面向对象的基本概念 类声明、对象创建 参数传递 this引用 类的管理(包和JAR文件) 字符串类 数组
旺旺老师给我们详细 的讲解的 类和对象。有实例哦!
Java类和对象源码,Java实用教程的类和对象源码
java类和对象继承多态性 是JAVA的基础学习课件,有利于提高
TP01_java类和对象介绍.ppt
很好的题,希望能给大家一点点帮助。 本文件为“JAVA类与对象及数组习题”是题哦
java 类和对象封装性,是java基础学习的ppt,有助于java自学·
Java SE编程入门教程 java类和对象方法以及包的使用(共56页).pptx Java SE编程入门教程 java类和对象方法以及包的使用(共62页).pptx Java SE编程入门教程 java判断循环(共79页).ppt Java SE编程入门教程 java...
Java SE编程入门教程 java类和对象方法以及包的使用(共56页).pptx Java SE编程入门教程 java类和对象方法以及包的使用(共62页).pptx Java SE编程入门教程 java判断循环(共79页).ppt Java SE编程入门教程 java...
ava基础 包含:Java入门 基础语法 JAVA 类和对象 JAVA 高级类 等等
java类和对象笔记
Java类和对象的概念_Java教程共3页.pdf.zip
java 类和对象的讲解视频
类和对象.pdf 类和对象.pdf 类和对象.pdf
本次实验进一步学习了Java的相关知识,深入理解了面向过程与面向对象语言的区别,了解了面向对象语言的三大特征,掌握类的声明和构造方法,掌握了对象的创建方法与创建机制,掌握了成员变量、类变量和局部变量区别,...