内容概要:
1.抽象类
2.final关键字
3.接口
4.Cloneable接口
5.Enumeration接口
1.抽象类
请注意下面noAction()方法。此方法无方法体,并且前面出现abstract关键字。
public abstract void noAction(); //body({....})
noAction()方法无方法体,因而也没有具体的动作。我们将此方法称为抽象方法,在此类方法前面有abstract关键字。
包含抽象方法的类被称为抽象类(abstract class)。在定义抽象类时,要在class前面插上abstract关键字
abstract class Myclass {...............................//Myclass类是abstract类 int myInt; public abstract void noAction();......................//x1,抽象方法 public int getMyint(){.....................................//非抽象方法 return myInt; } }
包含抽象方法的类,即抽象类无法创建对象,因为抽象方法未定义任何具体的动作。
抽象类无需定义方法体,在某些场合下,让子类继承并覆盖它,子类就能完成需要的功能,但要注意的是:继承了抽象类的子类一定要覆盖所继承的抽象方法,否则子类也将称为抽象类。
abstract class Shape{.................................//抽象类 double area; public abstract void draw();.................................//抽象方法 public double area(){ return area; } } class Rectangle extends Shape{.................................//继承 double d,h; public Rectangle(int a,int b){.................................//构造函数 d=a;h=b;area=d*h/2; } public void draw(){.................................//覆盖继承的抽象方法 System.out.println("画三角形"); } } class Rectangle2 extends Shape{.................................//继承 double l,w; public Rectangle2(int a,int b){.................................//构造函数 l=a;w=b;area=l*w; } public void draw(){.................................//覆盖抽象方法 System.out.println("绘制矩形"); } } public class Abstract1{ public static void main(String[] args) { Shape tr=new Rectangle(10,20); Shape re=new Rectangle2(10,20); System.out.println(tr.area()); tr.draw(); System.out.println(re.area()); re.draw();.................................//tr与re都是用画()方法绘制 } }
//结果:100.0 画三角形 200.0 绘制矩形
注意:抽象方法不能为private或static所修饰,abstract方法是子类应覆盖的方法,所以在抽象类中声明时不要使用private关键字。static方法在不创建对象时也可以被调用,所以其方法体(body)应该被定义。若无方法体,也就不能以“类.方法名()”的形式对其调用,所以abstract方法(无方法体)不能用static关键字修饰。
2.final关键字
final为:最后,最终,终端之意。final关键字可以用来修饰变量、方法和类。
public final int a = 10;//表示a为常量(constant)。即首次给a赋值后,以后不能再给它赋其他的值。
常量一般为所有对象所共有,所以把常量声明为static的情形也很多。public static final double PI=3.141592654358979323846;
PI值保持不变,并为所有对象共有。
static变量:static成员变量在不创建对象时也可以使用,并为所有对象共有。普通成员变量(non-static)只有在创建了对象后,才能使用。
最终方法:final关键字也可以出现在方法前面,如下所示:public final void f(){...} ,我们将此方法称为最终方法,继承含括最终方法的子类不能覆盖该最终方法。若子类可以改变最终方法,从而改变其功能,将会导致致命的错误出现。最终方法用以保护方法的功能,禁止对方法功能作出修改。
final关键字也可以出现在类前,意味着其他类无法继承该类,System类与String类就不能被继承改变其功能,所以可以定义成final类。
final class Final_1{ public static final double PI=3.14; public final void fmethod(){ System.out.println("不能覆盖此方法"); } } public class Final extends Final_1{................//final类不能被继承 public void fmethod(){............................//final方法不能被覆盖 System.out.println("错误"); } public static void main(String[] args) { PI=3.15;............................................//不能改变常数值 } }
3.接口
interface字面含义为界面,它是两个对象相互作用的接口。
在Java接口中,所有方法都是抽象的,所有变量也都是static常量,接口本身就是一种约束。
public interface MyInter{ public static final int MAX=100;.............//x1 public int MIN=1;............................//x2 public abstract void method();.............//x3 public void method2(int a);................//x4 }
接口中所有变量都是静态的(static)和最终的(final)。然而,x2行的变量MIN之前并没有static与final关键字,这并不会对变量MIN的静态性与最终性产生任何影响。
接口中所有的方法都是抽象的,x3与x4行的方法都是抽象的,关键字abstract可以省去。
由于接口所有方法都是抽象的,所有实现此接口只有全部覆盖了接口的全部方法,才能创建对象。注意,我们把继承接口称为实现接口。使用关键字implements,而不是extends。
与抽象类相比,接口更具有抽象性,实现接口的类必须实现接口中所有抽象方法。与继承类似,实现也意味着实现接口的类会继承接口的所有成员。
interface MyInter{.........................................//接口 public static final int MAX=100; public static final int MIN=1; public void method1(); public void method2(int a); } public class Interface1 implements MyInter{....................//实现MyInter接口 public void method1(){.........................................//x1,覆盖method1()方法 System.out.println("method1 override"); } public void method2(int a){.........................................//x2,覆盖method2()方法 System.out.println(a+"method2 override"); } public static void main(String[] args) { Interface1 ob=new Interface1(); ob.method1();.........................................//调用覆盖后的方法method1() ob.method2(123);......................................//调用覆盖后的方法method2() System.out.println(Interface1.MAX);...................//Interface1继承了MAX常量 System.out.println(MyInter.MIN);......................//可以在不创建对象的条件下,使用static变量 }} 在实现接口时,必须覆盖所有抽象方法。 在类的继承中,只能单重继承,而实现接口时,一次可以实现多个接口,这些接口之间用逗号分开。 interface MyInter1{........................................//接口1 public void method1(); } interface MyInter2{........................................//接口2 public void method2(); } public class Interface2 implements MyInter1,MyInter2{//同时实现接口1,接口2。(Interface2必须实现两个接口中的所有抽象方法) public void method1(){........................................//x1,覆盖Myinter1的方法 System.out.println("method1 voerride");} public void method2(){........................................//x2,覆盖MyInter2的方法 System.out.println("method2 voerride");} public static void main(String[] args){ Interface2 ob=new Interface2(); ob.method1(); ob.method2(); } }
也可以一次实现3个或3个以上的接口:
class Interface2 implements MyInter1,MyInter2,MyInter3.....{....}
我们还可在继承类的同时实现接口
public class Interface3 extends Myclass implements Myinter1,Myinter2{...}
接口也可以继承接口。
interface MyInter1{ public void method1();} interface Myinter2 extends Myinter1{ ...........//接口继承接口,用extends public void method2(); public class Interface4 implements Myinter2{....//类实现接口,用implements public void method1(){System.out.println("method1 voerride");}..//覆盖接口的抽象方法 public void method2(){System.out.println("method2 voerride");}..//覆盖接口的抽象方法 public static void main(String[] args){ Interface4 ob=new Interface4(); ob.method1(); ob.method2(); }}
Myinter2接口继承了Myinter1接口,所有拥有了两个抽象方法method1()和method2(),再Interface4实现Myinter2接口后,必须覆盖Myinter2中的两个抽象方法。
接口中的方法不能使用private与protected关键字修饰。不能用private是因为接口中的方法必须要被覆盖,protected关键字修饰的方法只允许子类进行访问,但是接口不能通过继承进行实现,所以我们用public来修饰接口方法。
4.Cloneable接口
我们学过引用传递调用知识,若方法的形式参数为一引用,那么它就可以引用由参数传递过来的对象。而有时我们要复制对象,并将对象的副本传递给方法。我们把复制对象的过程叫克隆。
void f(SomeObject ob){.....}//某方法
SomeObject ob=new SomeObject();//某对象
f(ob的副本); //将ob的副本传递给参数
在Java中产生副本时,遵守下列约定。
若想产生自身的副本:
1.创建该对象的类时必须实现Cloneable接口。
2.创建该对象的类必须覆盖Object类的clone()方法。
public class Cloneable1 implements Cloneable{ String s; int a; public Cloneable1(String s,int a){ this.s=s; this.a=a; } public Object clone(){.................................//返回自身副本,覆盖 try{ return super.clone();.................................//调用Object类的clone()方法 }catch(CloneNotSupportedException cse){} return null; } public static void main(String[] args) { Cloneable1 ob1=new Cloneable1("abce",10); Cloneable1 ob2= (Cloneable1) ob1.clone();.................................//生成ob1的副本 System.out.println("原本:"+ob1.hashCode()); System.out.println("副本:"+ob2.hashCode()); System.out.println("原本:"+ob1.s+ob1.a); System.out.println("副本:"+ob2.s+ob2.a); }}
结果:
原本:29855319
副本:5383406
原本:abce10
副本:abce10
5.Enumeration接口
实现了Enumeration接口的对象内部持有给定的元素(element),需要时,可将它们顺利的取出来。
Enumeration接口位于java.util包中,内有两个方法。如下:
boolean hasMoreElements();检查内部是否存在元素,若存在,返回true,否则返回false。
Object nextElement();返回下一个元素。
问题思考
(1)在面向对象程序设计中,使用常量(final)的原因何在?若不使用常量,会出现一些什么问题呢?
(2)抽象类与接口在作用上有何差异?请思考。
(3)图像类(shape)应该定义成接口还是抽象类呢?说明令人信服的理由。
转载请注明: ITTXX.CN--分享互联网 » Java语言学习—第九章 抽象类与接口[Java基础]
最后更新:2018-09-28 10:52:37