JAVA接口和抽象类
- 格式:wps
- 大小:45.00 KB
- 文档页数:12
提升代码扩展性的JAVA使用技巧随着软件开发的不断发展,代码的扩展性成为了一个非常重要的问题。
扩展性好的代码可以方便地进行功能的扩展和修改,而扩展性差的代码则会导致修改困难、代码冗余等问题。
在JAVA开发中,有许多技巧可以帮助我们提升代码的扩展性,本文将介绍一些常用的JAVA使用技巧,希望能对读者有所帮助。
1. 使用接口和抽象类接口和抽象类是JAVA中非常重要的概念,它们能够帮助我们实现代码的解耦和扩展。
通过定义接口和抽象类,我们可以将代码的实现细节与接口分离,从而使得代码更加灵活和可扩展。
在设计类的时候,我们可以首先考虑定义接口或抽象类,然后再进行具体的实现。
2. 使用设计模式设计模式是一种被广泛应用于软件开发中的经验总结,它提供了一套解决特定问题的方案。
在JAVA开发中,有许多常用的设计模式可以帮助我们提升代码的扩展性,例如工厂模式、观察者模式、策略模式等。
通过合理地运用设计模式,我们可以将代码的耦合度降低,从而提高代码的扩展性。
3. 使用泛型泛型是JAVA中的一个重要特性,它可以使得代码更加通用和灵活。
通过使用泛型,我们可以在编译期间对代码进行类型检查,避免了在运行时出现类型转换错误的问题。
同时,泛型还可以提高代码的可读性和可维护性,使得代码更加易于扩展和修改。
4. 使用注解注解是JAVA中的一个重要特性,它可以用来为代码添加元数据信息。
通过使用注解,我们可以在编译期间对代码进行静态检查,从而提高代码的健壮性和可扩展性。
例如,我们可以使用注解来标记某个方法需要进行事务管理,然后通过AOP的方式来实现事务管理的功能。
5. 使用反射反射是JAVA中的一个强大特性,它可以在运行时动态地获取和操作类的信息。
通过使用反射,我们可以在不知道类的具体实现的情况下,通过类的名称来创建对象、调用方法等。
反射可以使得代码更加灵活和可扩展,但是由于反射的性能较低,所以在使用反射时需要慎重考虑。
6. 使用单元测试单元测试是软件开发中非常重要的一环,它可以帮助我们验证代码的正确性和可扩展性。
相同点:(1) 都可以被继承(2) 都不能被实例化(3) 都可以包含方法声明(4) 派生类必须实现未实现的方法区别:(1) 抽象基类可以定义字段、属性、方法实现。
接口只能定义属性、索引器、事件、和方法声明,不能包含字段。
(2) 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。
微软的自定义接口总是后带able字段,证明其是表述一类“我能做。
”(3) 接口可以被多重实现,抽象类只能被单一继承(4) 抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中(5) 抽象类是从一系列相关对象中抽象出来的概念,因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定,因此反映的是事物的外部特性(6) 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法(7) 接口可以用于支持回调,而继承并不具备这个特点(8) 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的(9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法使用规则:1、抽象类主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能2、如果要设计大的功能单元,则使用抽象类;如果要设计小而简练的功能块,则使用接口。
3、如果预计要创建组件的多个版本,则创建抽象类。
接口一旦创建就不能更改。
如果需要接口的新版本,必须创建一个全新的接口。
4、如果创建的功能将在大范围的全异对象间使用,则使用接口;如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。
5、分析对象,提炼内部共性形成抽象类,用以表示对象本质,即“是什么”。
为外部提供调用或功能需要扩充时优先使用接口6、好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。
如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染7、尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。
Java抽象类和接⼝的定义与实现Java 抽象类1.什么时抽象类:在⾯向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是⽤来描绘对象的,如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员⽅法和构造⽅法的访问⽅式和普通类⼀样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使⽤。
也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
⽗类包含了⼦类集合的常见的⽅法,但是由于⽗类本⾝是抽象的,所以不能使⽤这些⽅法。
在Java中抽象类表⽰的是⼀种继承关系,⼀个类只能继承⼀个抽象类,⽽⼀个类却可以实现多个接⼝。
2.抽象类和抽象⽅法的定义:在Java语⾔中使⽤abstract class来定义抽象类。
//abstract修饰的就是抽象类public abstract class Action {//abstract修饰的⽅法就是抽象⽅法,它只有⽅法的名字没有⽅法的实现public abstract void Text();public static void main(String[] args) {//new Action() 抽象不能new出来只能靠⼦类去实现它//本质上抽象类就是⼀个约束}}抽象类的规范:1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译⽆法通过。
只有抽象类的⾮抽象⼦类可以创建对象。
2. 抽象类中不⼀定包含抽象⽅法,但是有抽象⽅法的类必定是抽象类。
3. 抽象类中的抽象⽅法只是声明,不包含⽅法体,就是不给出⽅法的具体实现也就是⽅法的具体功能。
4. 构造⽅法,类⽅法(⽤ static 修饰的⽅法)不能声明为抽象⽅法。
5. 抽象类的⼦类必须给出抽象类中的抽象⽅法的具体实现,除⾮该⼦类也是抽象类。
3.接⼝的定义:接⼝(interface)是抽象⽅法和常量值的定义的集合。
抽象类与接口-笔记关键字:接口抽象类,接口与类是一个层次的概念,是java中极其重要的概念抽象类是从多个类中抽象出来的公共模板,提供子类均具有的功能。
接口是从多个类中抽象出来的规范,体现的是规范和实现分离的原则,同时也有效的解决Java单重继承的缺陷。
*******普通方法与抽象方法的不同*******普通方法需要有访问修饰符,返回类型,方法名,还要有一个方法体,抽象方法也有访问修饰符,返回类型,方法名,但是它还多了一个修饰符——abstract,同时没有方法体,也就是说抽象方法没有实现。
普通方法与抽象方法的区别:1,普通方法必须要有实现体,抽象方法不能有实现体,抽象方法要用abstract修饰符来修饰。
********普通类与抽象类的区别*********普通类:要有访问修饰符,class关键字和类名。
抽象类:在普通类的基础之上,还多了一个abstract修饰符。
在使用的时候抽象类与普通类也不一样:普通类:可以通过new关键字实例化。
抽象类:不能使用new关键字来实例化。
**********抽象类********************抽象类:是一个不能实例化的类,它可以具有抽象方法或者普通方法。
定义抽象类的语法与定义普通类类似,只是多了一个关键字abstract。
注意:抽象类中可以定义抽象方法,也可以拥有普通方法,而普通类当中只能定义普通方法。
********对比抽象类与接口***************抽象类用abstract修饰符来定义,而且抽象类中可以有抽象方法,也可以有普通方法。
**接口是使用interface关键字来定义,关键字后面是接口名。
注意::定义接口的时候不再使用class关键字。
同时,接口只能拥有抽象方法。
***从定义就可以看出抽象类与接口的区别:1,抽象类使用abstract声明,接口使用interface声明。
2,抽象类除了抽象方法,还可以有普通方法,而接口中只能有抽象方法。
面向对象程序设计中的抽象类与接口研究随着软件开发技术的不断发展,面向对象程序设计成为了当今十分流行和广泛使用的一种编程思想。
而在面向对象程序设计中,抽象类与接口则是两个非常重要的概念。
本文将对抽象类与接口进行深入研究。
一、什么是抽象类?抽象类是一种不能被实例化的类,它的主要作用是为其子类提供具有实现细节的基类。
抽象类一般用于描述某一类事物的抽象概念,而非具体的某一个事物。
在Java中,我们可以使用abstract关键字来定义一个抽象类。
抽象类中可以包含抽象方法和非抽象方法,抽象方法则是一种没有具体实现的方法,而非抽象方法则是有具体实现的方法。
abstract class Animal {String name;public void setName(String name) { = name;}public abstract void eat();}上述代码定义了一个名为Animal的抽象类和一个抽象方法eat()。
由于抽象方法没有具体实现,因此不需要在抽象类中对它进行实现。
二、什么是接口?接口是一种到处可见的类型,它定义了一组方法的规范,但并不提供对这些方法的具体实现。
接口只是指定了一组标准,由实现该接口的类来提供具体实现。
在Java中,我们可以使用interface关键字来定义一个接口。
接口中只能包含常量和抽象方法,常量必须使用public static final修饰符进行修饰,抽象方法则必须使用public abstract修饰符进行修饰。
interface Animal {public static final int NUM_LEGS = 4;public abstract void makeSound();}上述代码定义了一个名为Animal的接口和一个抽象方法makeSound()。
由于接口中的抽象方法没有具体实现,因此我们必须在实现该接口的类中对它进行实现。
三、抽象类与接口的区别虽然抽象类与接口都是用于描述某一类事物的抽象概念,但二者之间还是存在一些区别的,具体表现如下:1. 实现方式不同抽象类是一种类,是通过继承来实现的,而接口是一种接口,是通过实现来实现的。
JA V A继承、抽象类、接口编辑人:星辰·樱联系QQ:838826112一.类的继承通过继承可以实现代码的复用,被继承的类称为父类或超类(superclass),由继承而得到的类称为子类(subclass)。
一个父类可以拥有多个子类,但一个类只能有一个直接父类,这是因为JA V A语言中不支多重继承。
子类继承父类的成员变量和成员方法,同时可以修改父类的成员变量或重写父类的方法,还可以添加新的成员变量或成员方法。
JA V A语言中有一个名为ng.Object的特殊类,所有的类都是直接或间接地继承该类而得到的。
1.子类的创建类的继承是通过extends关键字来实现的,在定义类时若使用ectends关键字指出新定义类的父类,就是在两个类之间建立了继承关系。
新定义的类称为子类,它可以从父类那里继承所有非private的成员作为自己的成员。
子类的创建:* 格式:class SubClass extends SuperClass* {* .* .* .* }2.调用父类中特定的构造方法在没有明确地指定构造方法时,子类还是会先调用父类中没有参数的构造方法,以便进行初始化的操作。
在子类的构造方法中可以通过super()来调用父类特定的构造方法。
例://以Person作为父类,创建学生子类Student,并在子类中调用父类里某指定的构造方法。
class Person2{private String name;private int age;public Person2()//定义Person2类的无参构造方法{System.out.println("调用了Person2类的无参构造方法");}public Person2(String name,int age)//定义Person2类的有参构造方法{System.out.println("调用了Person2类的有参构造方法");=name;this.age=age;}public void show(){System.out.println("姓名:"+name+" 年龄:"+age);}}class Student2extends Person2//定义继承自Person2类的子类Student2{private String department;public Student2()//定义Student2类的无参构造方法{System.out.println("调用了学生类的无参构造方法Student2()");}public Student2(String name,int age,String dep)//定义Student2类的有参构造方法{super(name,age);//调用父类的胡参构造方法department=dep;System.out.println("我是"+department+"学生");System.out.println("调用了学生类的有参构造方法Student2(String name,int age,String dep)");}}public class App8_2 {public static void main(String[] args){Student2 stu1=new Student2();//创建对象,并调用无参构造方法Student2 stu2=new Student2("李小四",23,"信息系");//创建对象并调用有参构造方法stu1.show();stu2.show();}}/*在子类中访问你类的构造方法,其格式为super(参数列表)。
java中级面试题及答案Java中级面试题主要针对Java开发者的基础知识、编程能力以及项目经验进行综合考察。
下面是一些常见的Java中级面试题及其答案,供参考:1. 什么是Java中的封装(Encapsulation)?封装是面向对象编程的一项基本原则,它通过将数据和操作数据的方法组合在一起,对数据进行保护和隐藏。
在Java中,封装可以通过使用private访问修饰符将类的字段(属性)私有化,然后提供公共的getter和setter方法来访问和修改这些字段。
2. Java中的继承(Inheritance)是什么?如何实现继承?继承是面向对象编程的另一个基本原则,它允许一个类继承另一个类的特性(字段和方法)。
在Java中,继承可以通过使用extends关键字实现。
子类(派生类)可以继承父类(基类)的非私有属性和方法,并可以通过覆盖(override)父类的方法来改变其行为。
3. 什么是Java中的多态(Polymorphism)?多态是面向对象编程中的一个重要概念,它允许不同的对象对同一个消息做出不同的响应。
在Java中,多态可以通过继承和接口实现。
通过多态,可以编写更加灵活和可扩展的代码。
4. Java中的抽象类(Abstract Class)和接口(Interface)有什么区别?抽象类和接口在Java中都可以用来定义抽象(未实现)的方法,但它们在使用和设计上有一些区别。
抽象类可以包含非抽象方法和字段,而接口只允许包含抽象方法和常量。
一个类只能继承一个抽象类,但可以实现多个接口。
抽象类通常用于具有相似属性和行为的类的抽象化,而接口通常用于定义多个类之间的共享行为。
5. Java中的异常处理机制是什么?请举例说明如何使用异常处理。
Java的异常处理机制通过try-catch-finally块来捕获和处理异常。
在try块中编写可能抛出异常的代码,在catch块中捕获并处理异常,在finally块中释放资源。
java abstract类命名摘要:1.Java抽象类概述2.抽象类的特点3.抽象类与接口的区别4.抽象类的应用案例5.命名规范与建议正文:Java抽象类是一种不能实例化的类,它包含一个或多个抽象方法。
抽象方法是没有方法体的方法,需要子类提供具体实现。
抽象类的主要目的是规定子类的接口,实现代码的复用。
抽象类的特点主要有以下几点:1.抽象类不能被实例化。
2.抽象类至少包含一个抽象方法。
3.抽象类可以包含普通方法和字段。
4.抽象类不能包含构造方法。
5.抽象类不能被继承,但可以被实现。
抽象类与接口的区别主要体现在以下几个方面:1.抽象类可以包含普通方法和字段,而接口只能包含方法定义。
2.抽象类中的方法可以有不同的访问权限,而接口中的方法都是public 的。
3.抽象类可以有构造方法,而接口不能。
4.抽象类中的方法可以有默认实现,而接口中的方法没有默认实现。
5.实现类可以同时实现多个接口,但只能继承一个抽象类。
抽象类的应用案例包括:1.模板方法模式:通过定义一个抽象类,将算法的结构和共享功能定义在该抽象类中,而将具体的实现留给子类。
2.工厂方法模式:通过定义一个抽象类,声明创建对象的方法,具体创建过程由子类决定。
3.适配器模式:通过定义一个抽象类,将原本接口不兼容的类转换成可以相互通信的类型。
在命名方面,抽象类通常以"Abstract"作为前缀,以表明它是一个抽象类。
此外,建议遵循驼峰命名法,将抽象方法命名为"abstractMethod",以与其他方法区分开来。
总之,Java抽象类是一种非常有用的编程概念,它可以帮助我们更好地实现代码复用和提高代码的可维护性。
接⼝和抽象类的区别是什么?Java接⼝中声明的变量默认都是final的。
(为什么)接⼝和抽象类的区别是什么?参考答案Java提供和⽀持创建抽象类和接⼝。
它们的实现有共同点,不同点在于:接⼝中所有的⽅法隐含的都是抽象的。
⽽抽象类则可以同时包含抽象和⾮抽象的⽅法。
类可以实现很多个接⼝,但是只能继承⼀个抽象类类可以不实现抽象类和接⼝声明的所有⽅法,当然,在这种情况下,类也必须得声明成是抽象的。
抽象类可以在不提供接⼝⽅法实现的情况下实现接⼝。
?Java接⼝中声明的变量默认都是final的。
(为什么)抽象类可以包含⾮final的变量。
Java接⼝中的成员函数默认是public的。
抽象类的成员函数可以是private,protected或者是public。
接⼝是绝对抽象的,不可以被实例化。
抽象类也不可以被实例化,但是,如果它包含main⽅法的话是可以被调⽤的。
也可以参考JDK8中抽象类和接⼝的区别问题1.Java接⼝中声明的变量默认都是final的。
(为什么)interface中的变量是当作常量来设计的,它不但是final,⽽且还是public static的,也即interface中的变量⼀定是public static final的,换⾔之,这个变量实际上已经是个“常量”。
解答:java接⼝中成员变量必须是final类型的原因如下:1. 接⼝中的数据对所有实现类只有⼀份,所以是static2.要使实现类为了向上转型成功,所以必须是final的.这个举例⼦很好理解.⽐如接⼝A,A有变量value.实现类A1,A2,可以向上转型.假如代码中有⼀句:A a=null;a=....(2)实际实现类System.out.println(a.value);利⽤向上转型,可以得到接⼝a的值,在第2步中,我不关你是实现类A1,还是new A2(),通过转型,我们可以得到正确的值.要是类中可以更改,我们得不到⼀个统⼀的值,接⼝也没有了意义.假设接⼝的成员变量x不是final的,且默认有值。
java高级程序员面试题Java作为目前最为流行和广泛应用的编程语言之一,在招聘行业中需求量极大。
作为一名Java高级程序员面试者,除了需要具备扎实的编程基础知识外,还需要具备一定的工作经验和解决实际问题的能力。
下面是一些常见的Java高级程序员面试题,供大家参考。
1.请解释Java中的面向对象编程(OOP)是什么,以及它的优点。
面向对象编程是一种程序设计范式,通过使用对象、类、继承、封装和多态等概念,将真实世界中的事物抽象为软件实体,以此构建复杂的程序。
面向对象编程的优点包括代码重用性高、易于维护和扩展、提高开发速度和降低维护成本等。
2.什么是多态性?请使用Java代码示例说明。
多态性是指同一个方法可以被不同类型的对象调用,产生不同的行为。
在Java中,多态性通过继承和方法重写实现。
例如:```javaclass Animal {public void sound() {System.out.println("动物发出声音");}}class Cat extends Animal {@Overridepublic void sound() {System.out.println("猫发出喵喵的声音");}}class Dog extends Animal {@Overridepublic void sound() {System.out.println("狗发出汪汪的声音");}}public class PolymorphismDemo {public static void main(String[] args) {Animal animal1 = new Cat();Animal animal2 = new Dog();animal1.sound(); // 输出:猫发出喵喵的声音 animal2.sound(); // 输出:狗发出汪汪的声音 }}3.请解释Java中的接口(Interface)是什么,以及它与抽象类的区别。
Java中Interface的用法1. 什么是Interface在Java中,Interface(接口)是一种特殊的抽象类,它定义了一组方法签名(方法的名称、参数列表和返回类型),但没有方法的实现。
接口可以看作是一种合同,所有实现该接口的类必须按照接口定义的方式来实现其中的方法。
接口可以用来描述类应该具备的行为,通过使用接口,可以实现多态性、代码重用性和可扩展性。
2. 定义接口接口的定义使用interface关键字,定义的方法默认是抽象的,也可以包含常量和默认方法。
public interface MyInterface {// 常量public static final int MAX_COUNT = 100;// 抽象方法public void myMethod();// 默认方法public default void myDefaultMethod() {System.out.println("This is a default method in interface");}}接口方法的可见性修饰符默认是public,可以省略。
接口中的常量默认是public static final类型的,可以省略这些修饰符。
3. 实现接口要实现一个接口,使用implements关键字,类中必须实现接口中的所有方法。
一个类可以实现多个接口,以逗号分隔。
public class MyClass implements MyInterface {// 实现接口中的抽象方法public void myMethod() {System.out.println("This is my method implementation");}}4. 接口的继承接口可以继承其他接口,使用extends关键字。
一个接口可以继承多个接口,接口之间使用逗号分隔。
public interface MyExtendedInterface extends MyInterface {// 添加新的方法public void myExtendedMethod();}接口的继承可以形成接口的层次结构,子接口继承了父接口的所有方法和常量。
实验八:抽象类和接口
【实验目的】
1.熟练掌握类的继承的概念。
2.掌握抽象类abstract的概念。
3.掌握接口interface的概念。
【实验地点】科技楼206
【课时安排】2课时
【实验内容】
1.定义一个抽象类--Shape,该类有求面积getArea和周长getPerimeter两个抽象方法。
该抽象类派生三角形Triangle、矩形Rectangle、圆Circle三个子类,为各个子类实
现抽象类的方法,并为这些子类编写合适的属性和构造方法。
编写程序分别创建三
角形、矩形、圆对象,并输出各个对象的面积和周长。
2.定义一个接口Drawable,该接口如下:
public interface Drawable{
public void draw();
public boolean isVisible();
}
对第一题中的三个派生子类,分别实现Drawable接口,并对创建的对象调用其实
现的接口方法。
(对于方法的实现可以尽量简单,如draw方法可以简单的打印出:“某某类的draw方法”)
【作业】
将第1题实验内容写实验报告。
java中abstract的用法
在Java中,abstract是一个关键字,可以用来修饰类、方法或者变量。
作为一个修饰符,它具有以下几个用法:
1. 抽象类:通过在类名前面添加abstract关键字来定义抽象类。
抽象类不能被实例化,只能被继承。
抽象类可以包含抽象方法或非抽象方法,但至少要有一个抽象方法。
2. 抽象方法:通过在方法名前面添加abstract关键字来定义抽象方法。
抽象方法没有方法体,只有方法签名。
子类必须实现所有抽象方法,否则子类也必须声明为抽象类。
3. 接口:接口是一种特殊的抽象类,其中所有的方法都是抽象方法。
接口中的方法没有方法体,只有方法签名。
类可以实现多个接口,但只能继承一个类。
4. 抽象变量:在Java中不存在抽象变量的概念,因为变量不需要被继承或实现。
总的来说,abstract的主要作用是为了实现抽象化,将具体的实现延迟到子类中去实现。
抽象类和抽象方法的使用可以提高代码复用性和灵活性,使得程序更加易于扩展和维护。
- 1 -。
接⼝和抽象类有什么区别他们都不能实例化对象,都可以包含抽象⽅法,⽽且抽象⽅法必须被继承的类全部实现。
区别:1、抽象类和接⼝都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象⽅法的⼦类对象,接⼝变量必须指向实现所有接⼝⽅法的类对象。
2、抽象类要被⼦类继承,接⼝要被类实现。
3、接⼝只能做⽅法申明,抽象类中可以做⽅法申明,也可以做⽅法实现4、接⼝⾥定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类⾥的抽象⽅法必须全部被⼦类所实现,如果⼦类不能全部实现⽗类抽象⽅法,那么该⼦类只能是抽象类。
同样,⼀个实现接⼝的时候,如不能全部实现接⼝⽅法,那么该类也只能为抽象类。
6、抽象⽅法只能申明,不能实现,接⼝是设计的结果,抽象类是重构的结果7、抽象类⾥可以没有抽象⽅法8、如果⼀个类⾥有抽象⽅法,那么这个类只能是抽象类9、抽象⽅法要被实现,所以不能是静态的,也不能是私有的。
10、接⼝可继承接⼝,并可多继承接⼝,但类只能单根继承。
参数抽象类接⼝默认的⽅法实现它可以有默认的⽅法实现接⼝完全是抽象的。
它根本不存在⽅法的实现实现⼦类使⽤extends关键字来继承抽象类。
如果⼦类不是抽象类的话,它需要提供抽象类中所有声明的⽅法的实现。
⼦类使⽤关键字implements来实现接⼝。
它需要提供接⼝中所有声明的⽅法的实现构造器抽象类可以有构造器接⼝不能有构造器与正常Java类的区别除了你不能实例化抽象类之外,它和普通Java类没有任何区别接⼝是完全不同的类型访问修饰符抽象⽅法可以有public、protected和default这些修饰符接⼝⽅法默认修饰符是public。
你不可以使⽤其它修饰符。
main⽅法抽象⽅法可以有main⽅法并且我们可以运⾏它接⼝没有main⽅法,因此我们不能运⾏它。
(java8以后接⼝可以有default和static⽅法,所以可以运⾏main⽅法)多继承抽象⽅法可以继承⼀个类和实现多个接⼝接⼝只可以继承⼀个或多个其它接⼝速度它⽐接⼝速度要快接⼝是稍微有点慢的,因为它需要时间去寻找在类中实现的⽅法。
理解Java的接口与抽象类对于面向对象编程来说,抽象是它的一大特征之一。
在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类。
这两者有太多相似的地方,又有太多不同的地方。
很多人在初学的时候会以为它们可以随意互换使用,但是实际则不然。
今天我们就一起来学习一下Java中的接口和抽象类。
下面是本文的目录大纲:一.抽象类二.接口三.抽象类和接口的区别一.抽象类在了解抽象类之前,先来了解一下抽象方法。
抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。
抽象方法的声明格式为:abstract void fun();抽象方法必须用abstract关键字进行修饰。
如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。
因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
下面要注意一个问题:在《JAVA编程思想》一书中,将抽象类定义为“包含抽象方法的类”,但是后面发现如果一个类不包含抽象方法,只是用abstract修饰的话也是抽象类。
也就是说抽象类不一定必须含有抽象方法。
个人觉得这个属于钻牛角尖的问题吧,因为如果一个抽象类不包含任何抽象方法,为何还要设计为抽象类?所以暂且记住这个概念吧,不必去深究为什么。
[public] abstract class ClassName { abstract void fun();}从这里可以看出,抽象类就是为了继承而存在的,如果你定义了一个抽象类,却不去继承它,那么等于白白创建了这个抽象类,因为你不能用它来做任何事情。
对于一个父类,如果它的某个方法在父类中实现出来没有任何意义,必须根据子类的实际需求来进行不同的实现,那么就可以将这个方法声明为abstract方法,此时这个类也就成为abstract类了。
包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。
注意,抽象类和普通类的主要有三点区别:1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
前面的文章中已经写过接口和抽象都很像,它们都具有如上特征:》接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。
》接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。
虽然它们很相像,但差别也非常大,具体体现在二者设计目的上。
接口作为系统与外界交互的窗口,接口体现在是一种规范。
对于接口的实现者而言,接口规定了实现者必须向外提供服务(以方法的形式来提供)对于接口的调用者而言,接口规定了调用者可以调用哪些服务,以及如何调用这些服务(就是如何调用方法)当一个程序中使用接口时,接口是多个模块间的耦合标准;当在多个应用程序之间使用接口时,接口是多个程序之间的通信标准也就是说从某种程序上看,接口类似于整个系统的“总纲”它制定了系统各模块应该遵循的标准,因此一个系统中的接口不应该经常改变。
一旦接口改变,对整个系统甚至其他系统的影响将是辐射式的,导致系统中大部分类都需要改写。
抽象类则不一样,抽象类作为系统中多个子类的共同父类,它所体现的是一种模板式设计,抽象父灰作为多个子类的抽象父类。
接口和抽象类在用法上也存在如下差别:》接口里只能包含抽象方法,不包含已经提供实现的方法;抽象类则完全可以包含普通方法。
》接口里不能定义静态方法:抽象类里可以定义静态方法。
》接口里只能定义静态常量属性,不能定义普通属性;抽象类里则既可以定义普通属性,也可以定义静态常量属性。
》接口不包含构造器:抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
》接口里不能包含初始化块,但抽象类则完全可以包含初始化块》一个类最多只能有一个直接父类,包括抽象类;但一个类可以直接实现多个接口,通过实现多个接口可以弥补JA V A单继承的不足。
面向接口编程我们在前面已经写到过,接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极好地降低程序各模块之间的耦合,从而提高系统的可扩展性和可维护性。
基于这种原则,很多软件架构设计理论都倡导“面向接口”编程,而不是面向实现类编程,希望通过面向接口编程来降低程序的耦合。
我们将看两种常用场景来示范“面向接口”编程的优势。
简单工厂模式有一个场景,假设程序中有个Computer类需要组合一个输出设备,现在两个选择:直接让Computer该类组合一个Printer属性,或者让Computer组合一个Output属性,那么到底采用哪种方式更好呢?假设让Computer组合一个Printer属性,如果有一天系统需要重构,需要使用BetterPrinter 来代替Printer,于是我们需要打开Computer类源代码进行修改。
如果系统中只有一个Computer类组合了Printer属性还好,如果系统中有100个类组合了Printer属性,或者更多,将意味着我们要打开100或其他,进行修改。
为了避免这个问题,我们让Computer组合一个Output属性,将Computer类与Printer类完全分离。
Computer对象实际组合的是Printer对象还是BetterPrinter对象,将Computer而言完全透明。
当Printer对象切换到BetterPrinter对象时,系统完全不受影响。
我还是把前面提到的接口给写下来:public interface Output{//接口里定义的Field只能是常量int MAX_CACHE_LINE = 50;//接口里定义的只能是public的抽象实例方法void out();void getData(String msg);}看代码:public class Computer{private Output out; //定义一个Output类型的变量给outpublic Computer (Output out){this.out=out;}//定义一个模拟获得字符串输入的方法public void keyIn(String msg){out.getData(msg)}//定义一个模拟打印的方法public void print(){out.out();}}上面的Computer类已经完全与Printer类分离开,只是与Output接口耦合。
Computer不再负责创建Ooutput对象,系统提供一个Output工厂来负责生成Output对象。
这个OutputFactory 工厂类代码如下:public class OutputFactory{public Output getOutput(){return new Printer();}//主方法入口public static voi main(String[] args){OutputFactory of = new OutputFactory();Computer c = new Computer(of.getOutput());c.keyIn("世界您好!");c.keyIn("您好世界!");c.print();}}在该OutputFactory 类中包含了一个getOutput方法,该方法返回一个Output 实现类的实例,该方法负责创建Output实例,具体创建哪一个实现类的对象由该方法决定(具体由该方法中粗体部分控制,当然也可以增加更复杂的控制逻辑)如果系统需将Printer改为BetterPrinter 实现类,只需要让BetterPrinter实现Output接口,并改变OutputFactory类中的getOutput方法即可。
看代码:public class BetterPrinter implements Output{private String[] printData = new String[MAX_CACHE_LINE*2] //因为更好//用以记录当前需打印的作业数private int dataNum = 0;public void out(){//只要还有作业,继续打印while(dataNum >0){System.out.println("高速打印机正在打印:"+printData[0]);//把作业队列整体前移一位,并将剩下的作业数减1System.out.arraycopy(printData,1 printData,0,--dataNum);}}public void getData(String msg){if(dataNum >= MAX_CACHE_LINE *2){System.out.println("输出队列已满,添加失败");}else{//把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;}}}上面的BetterPrinter类也实现了Output接口,因此也可当成Output对象使用,于是我们只要把OutputFactory工厂类的getOutput方法中粗体部分改为如下代码:return new BetterPinter();再将运行前面的OutputFactory.java程序,发现系统运行时已经改为BetterPrinter对象,而不再是原来的Printer对象。
通过这种方式,我们把所有生成Output对象的逻辑集中在OutputFactory 工厂类中管理,而所有需要使用Output对象的类只需与Output接口耦合,而不是与具体的实现类耦合。
上面介绍的就是一种被称为“简单工厂”的设计模式,所谓设计模式,就是对经常出现的软件设计问题的成熟解决方案,当然了这必须拥有足够的代码量作为基础。
命令模式考虑这样一种场景:某个方法需要完成某一个行为,但这个行为的具体实现无法确定,必须等到执行该方法时才可以确定,具体一点:假设有个方法需要遍历某个数组的数组元素,但无法确定在遍历数组元素时如何处理这些元素,需要在调用该方法是指定具休的处理行为。
因为JA V A不允许代码块单独存在,因此我们使用一个Command接口来定主一个方法,用这个方法来封装“处理行为”。
看Command接口代码:public interface Command{//接口里定义的process方法用于封装“处理行为”void process(int[] target); //省略了public abstract 修饰。
抽象方法来的}上面的Command接口里定义了一个process方法,这个方法用于封装“处理行为”,但这个方法没有方法体---因为现在还无法确定这个处理行为。
下面是需要处理数组的处理类,在这个处理类中包含一个process方法,这个方法无法确定处理数组的处理行为,所以定义该方法时使用了一个Command参数,这个Command 参数负责对数组的处理行为。
public class ProcessArray{public void process(int[] target,command cmd){cmd.process(target);}}通过一个Command类,就实现了让ProcessArray类和具体“处理行为”的分离,程序使用Command接口代表了对数组的处理行为。
Command接口也没有提供真正的处理,只有等需要调用ProcessArray对象的process方法时,才真正传入一个Commad对象,才确定对数组的处理行为。
public class CommandTest{public static void main(String[] args){ProcessArray pa = new ProcessArray();int[] target ={3,-4,6,4};//第一次处理数组,具体处理行为取决于PrintCommandpa.process(target,new printCommand());System.out.println("--------------");//第二次处理数组,具体处理行为取决于AddCommandpa.process(target,new AddCommand());}}我们知道,两次不同的处理行为是通过PrintCommand类和AddCommand类提供的。
public class PrintCommand implements Command{public void process(int[] target){for(int tmp:target) //利用了简洁foreach 用法{System.out.println("迭代输出目标数组的元素:"+tmp);}}}public class AddCommand implements Command{public void process(int[] target){int sum=0;for(int tmp :target){sum +=tmp;}Systm.out.println("数组元素的总和是:"+sum);}}看下编译结果为:对于PrintCommand和AddCommand两个实现类而言,实际有意义的部分是process(int[] target) 方法,该方法的方法体就是传入ProcessArray类里process方法的“处理行为”,通过这种方式就可实现process 方法和“处理行为”的分离。