java学习笔记(6)
第六章 面向对象编程
一、 题目
1.多态中的重载与覆盖有什么不同?
多态性是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为。,,,
所谓重载(overload),是在编译时的多态,是指在类中创建了多个方法,它们具有相同的名称,但有不同的参数和不同的实现。
覆盖(override)是在运行时的多态,指的是子类继承父类时,对父类中的变量或者方法进行重新定义,函数名和参数都要相同。
1)方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个类中方法之间的关系,是水平关系。
2)覆盖只能由一个方法,或只能由一对方法产生关系;方法的重载是多个方法之间的关系。
3)覆盖要求参数列表相同;重载要求参数列表不同。
4)覆盖关系中,调用那个方法体,是根据对象的类型(对象对应存储空间类型)来决定;重载关系,是根据调用时的实参表与形参表来选择方法体的。
dalao博客详细解释:http://blog.sina.com.cn/s/blog_88b95c430100uxxl.html
2.静态方法与非静态方法的区别?
被static修饰的方法为静态方法,其与非静态方法的区别在于,它为类中所有成员、方法共有。其中一个操作对它进行改变,会导致其它操作调用它时值已经改变。静态方法属于整个类,不用进行实例化操作,使用时方法前加类名而不是对象名。
总结如下:
1、静态方法属于类所有,类实例化前即可使用;
2、非静态方法可以访问类中的任何成员,静态方法只能访问类中的静态成员;
3、因为静态方法在类实例化前就可以使用,而类中的非静态变量必须在实例化之后才能分配内存;
4、static内部只能出现static变量和其他static方法!而且static方法中还不能使用this等关键字,因为它是属于整个类;
5、静态方法效率上要比实例化高,静态方法的缺点是不自动进行销毁,而实例化的则可以做销毁;
6、静态方法和静态变量创建后始终使用同一块内存,而使用实例的方式会创建多个内存。
主要区别:静态方法在创建对象前就可以使用了,非静态方法必须通过new出来的对象调用。
例子:
// 定义一个学生档案类,包括学生姓名、性别和所在学校
// 使用static修饰成员变量
class Student {
String name;
String sex;
static String school="**工业大学";
}
public class Test_Student {
public static void main(String args[]) {
Student stu1=new Student();
Student stu2=new Student();
stu1.name="李明 ";
stu1.sex="男 ";
stu2.name="张敏 ";
stu2.sex="女";
//对类成员变量赋值
Student.school="##大学";
System.out.println(stu1.name+" "+stu1.sex+" "+stu1.school);
System.out.println(stu2.name+" "+stu2.sex+" "+stu2.school);
}
}
输出结果如下:
经验证,一经改变,其后再次调用静态变量为改变后的静态变量,说明静态变量为全体共享。
3. final成员变量和方法有什么特点?
final修饰的变量为最终成员变量,一般是在声明时进行初始化,一旦最终成员变量被赋值,则它在整个程序执行过程中不能改变。最终方法不能被重复定义或更改方法的内容,不能被覆盖。
总结:final可以修饰类,方法,变量
特点:
1)final可以修饰类,该类不能被继承
2)final可以修饰方法,该方法不能被重写。(覆盖,复写)
3)final可以修饰变量,该变量不能被重新赋值。因为这个变量其实是常量。
4. 写一个类A,该类创建的对象可以调用方法f输出英文字母表,然后再编写一个该类的子类B,要求子类B必须继承A类的方法f(不允许重写),子类创建的对象不仅可以调用方法f输出英文字母表,而且可以调用用子类新增的方法g输出希腊字母表。
见xiti6_5.java
package xiti6;
import java.util.Scanner;
class A{
A(){}
public final void f(){
System.out.print('a');
for(char i='b';i<='z';i++)
System.out.print(" "+i);
}
}
class B extends A{
public void g() {
System.out.print('α');
for(char i='β';i<='ω';i++)
System.out.print(" "+i);
// System.out.print("αβγδεζηθικλμνξοπρστυφχψω");
}
}
public class xiti6_4 {
public static void main(String args[]) {
A a=new A();//声明建立A类的一个对象a
a.f();//a调用输出英文字母表
System.out.println();
B b=new B();//声明建立B类的一个对象b
b.f();//b调用输出英文字母表
System.out.println();
b.g();//b调用输出希腊字母表
}
}
5. *阅读:
《设计模式:可复用面向对象软件的基础》,Erich Gamma等,机械工业出版社
《大话设计模式》,程杰,清华大学出版社
《大象——Thinking in UML 》,谭云杰,中国水利水电出版社
二、论述
关键字static & final 的介绍见学习笔记(5),
1、多态机制:
多态机制是面向对象程序设计的一个重要特征。
多态的特点是采用同名的方式,根据调用方法时传送的参数的多少以及传送参数类型的不同,调用不同的方法,这样对于类的编制而言,可以采用同样的方法获得不同的行为特征。
1)编译时多态
表现为方法名相同,而参数表不同。典型:System.out.println(); 它的参数有很多种。
2)运行时多态
程序运行的时候判断到底是哪个类(父类还是子类的),进而确定实际调用的方法
3)对象状态的判断
由于子类对象可以作为父亲类对象使用,有时需要判断这个对象究竟属于哪个类。Java提供instanceof 关键字
2、抽象类
所有的对象都是通过类来描绘的,但是并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
或者从形式上直观地说,用关键字abstract修饰的类称为抽象类(abstract类),同理,用关键字abstract修饰的方法称为abstract方法(抽象方法),对于abstract方法,只允许声明,不允许实现,而且不允许使用final和abstract同时修饰一个方法。
抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是不能实例化的,是专门设计为子类继承的类,抽象类通常都包括一个或多个抽象方法(只有方法说明,没有方法体),抽象方法体中内容,根据继承抽象类的子类的实际情况,有子类完成其抽象方法的代码。即抽象类只给出方案,由继承它的子类去实现定义的抽象方法
定义抽象类的一般形式:
abstract class 类名称 {
成员变量;
方法( ){ /* do something*/ }; //定义一般方法
abstract 方法( );//定义抽象方法
}
注意:
无论抽象类和抽象方法都以关键字abstract 开头
抽象实例:
说明:
抽象类里可以有非抽象的方法。
抽象类里可以没有抽象方法。
即使没有抽象方法的抽象类也不允许实例化。
一个类里有abstract方法的话,该类必须为abstract。
抽象方法一定不能有方法体(哪怕是空方法体)。
abstract类不能用new运算符创建对象,对于abstract类,不能使用new运算符创建该类的对象。如果一个非抽象类是某个抽象类的子类时,那么它必须重写父类的抽象方法,给出方法体,这就是为什么不允许使用final和abstract同时修饰一个方法的原因。
设计程序时,我们经常用到abstract类,只关心其操作,不关心其具体的实现的细节,将abstract类声明对象作为其子类的上转型对象,同时对该上转型对象进行封装,而对其扩展开放,增强了代码的可维护性。
3、接口
Java为单继承,使得其简单,但也带来一些不方便之处,为了克服单继承的缺点,Java使用了接口,一个类可以实现多个接口。同时,由于接口的实现很类似于类,所以两者的1学习可以相互比照、印证。
3.1、接口的声明与使用
(1)Java中接口定义的一般形式如下:
[访问控制符] interface 接口名 {
抽象方法声明(public abstract)
成员变量声明
(可以有public修饰的常量)
}
从上面的语法规定可以看出,定义接口与定义类非常相似,实际上可以把接口理解成为一种特殊的抽象类。
接口定义的说明:
接口不能被实例化
和类的访问级别类似,接口的访问控制符是 public 或者默认访问。
如果接口本身定义成public,所有抽象方法和成员变量都是public的,不论是否使用了public访问修饰符
接口中的所有方法都是抽象方法,在接口中只能给出这些抽象方法的方法名、返回值类型和参数列表,没有方法体。(类似C++的“纯虚类”)
接口中可以有成员变量(但变量不能用private和protected修饰)
接口中的变量,本质上都是static,而且是final的 ,无论是否用static修饰,必须以常量值初始化
实际开发中,常在接口中定义常用的变量,作为全局变量使用
访问形式: 接口名.变量名
一个接口不能继承其它的类,但是可以继承别的接口
一个类可以实现多个接口
(2)接口的使用
一个类通过使用关键字implements声明自己实现一个或多个接口。若接口有多个,用逗号隔开接口名
一旦接口被定义,一个或多个类可以实现该接口。为了实现一个接口,在类定义中使用implements关键字。其一般形式如下:
[访问控制符] class 类名 [extends 父类名]
[implements 接口名1[,接口名2…]] {
成员变量声明(实例化为public)
成员方法声明
}
使用说明:
类重写的接口方法以及接口中的常量可以被类的对象调用,而且常量也可以用类名或者接口名直接调用。(类似于类变量)
前面加public的接口可以被所有类声明实现,若不加public则称为友好接口,只能被同一个包中的类声明实现。父类实现了对接口的声明实现后,其子类不必再显式地再一次对该接口进行声明实现。
接口也可以被继承,子接口继承父接口中所有的方法和常量。(注意:只有abstract类可以在声明实现一个接口时,不用重写接口中的所有方法)
一实例如下:
(3)接口与多态
接口回调
类似于虚拟类,使用接口进行程序设计的核心思想是使用接口回调,即接口变量存放实现该接口的类的对象的引用,从而接口变量可以回调类实现的接口方法。
利用接口也可以体现程序设计的“开-闭”原则,即对扩展开放,对修改关闭。如下图:
abstract类与接口的比较
既然abstract类与接口有诸多相似之处,这里我们进行比较一下:
(a)abstract类和接口都可以有abstract方法。
(b)接口中只可以有常量,不能有变量,而abstract类中既可以有常量也可以有变量。
(c)abstract类中可以有非abstract方法,接口不可以。
详细见下表:
(4)设计模式初体验-工厂模式
简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
感觉现在学设计模式早了点,毕竟还啥都不会,但是接触一下还是有好处的,以我的理解,工厂模式就是创建一个可以创建其他类的基类,然后根据具体情况决定用哪个就实例化哪个,就像工厂根据用户需求进行生产对应的产品一样。
设计模式六大原则
设计模式的核心原则是:“开-闭”原则 (OCP)
软件实体(类,模块,函数等)应该可以扩展,但是不可以修改
依赖倒转原则
A:高层模块不应该依赖底层模块 B:抽象不应该依赖细节,细节应该依赖抽象
里氏代换原则:子类型必须能够替换它们的父类型
单一职能原则:就一个类而言,应该仅有一个引起他变化的原因 (不该你管的事情你不要管 )
迪米特法则:系统中的类,尽量不要与其他类互相作用,减少类之间的耦合度
接口隔离法则:这个法则与迪米特法则是相通。迪米特法则是目的,而接口隔离法则是对迪米特法则的规范。
上一篇: JAVA设计模式学习3——设计模式概述
下一篇: JAVA设计模式学习10——组合模式