1. 抽象类和方法
abstract void f();
是一个抽象方法
包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,那么类本身也必须限定为抽象的
不能使用抽象类来创建对象:
创建一个继承抽象类的新类并为之创建对象,那么就必须为基类的所有抽象方法提供方法定义。如果不这么做(可以选择不做),新类仍然是一个抽象类,编译器会强制我们为新类加上 abstract 关键字。
子类提供定义:
abstract class A{
abstract void f();
}
class B extends A{
@Override
void f() {
// TODO Auto-generated method stub
}
}
子类不提供定义:
abstract class A{
abstract void f();
}
abstract class B extends A{
//此时B也是一个抽象类
}
一个抽象类中可以没有抽象方法:
abstract class A{
void f(){
System.out.println("A");
}
}
class B extends A{
}
public class Demo1 {
public static void main(String[] args){
new A();//not ok 此时A还是一个抽象类 不能创建对象
new B();//ok B继承了A 但A中没有抽象方法 B类可以选择不重写方法
}
}
private abstract 被禁止
private abstract void f();
这样定义导致子类不能去访问重写f方法
2. 接口创建
Java 8 之前的接口更加容易,因为它们只允许抽象方法:
public interface PureInterface {
int m1();
void m2();
double m3();
}
在 Java 8 之前我们可以这么说:interface 关键字产生一个完全抽象的类,没有提供任何实现
Java 8 中接口稍微有些变化,因为 Java 8 允许接口包含默认方法和静态方法
接口使用implements关键字实现:
interface Concept {
// Package access
void idea1();//不需要显示加public修饰 接口中的方法默认就是public
void idea2();
}
class Implementation implements Concept {
@Override public void idea1() {
System.out.println("idea1");
}
@Override public void idea2() {
System.out.println("idea2");
}
}
接口中的方法权限
可以选择显式地声明接口中的方法为 public,但是即使你不这么做,它们也是public 的。所以当实现一个接口时,来自接口中的方法必须被定义为 public, 但是Java8中提供了一个默认方法
默认方法:
interface InterfaceWithDefault {
void firstMethod();
void secondMethod();
default void newMethod() {
System.out.println("newMethod");
}
}
public class Implementation2 implements InterfaceWithDefault {
@Override public void firstMethod() {
System.out.println("firstMethod");
}
@Override public void secondMethod() {
System.out.println("secondMethod");
}
public static void main(String[] args) {
InterfaceWithDefault i =
new Implementation2();
i.firstMethod();
i.secondMethod();
i.newMethod();
}
}
/* Output:
firstMethod
secondMethod
newMethod
*/
尽管 Implementation2 中未定义 newMethod(),但是可以使用 newMethod()
3. “多继承”
Java之前(Java8之前)是一种严格要求单继承的语言:只能继承自一个类(或抽象类),但可以实现任意多个接口
interface A{
void f();
}
interface B {
void f();
}
public class Demo1 implements A,B {
public static void main(String[] args){
A a=new Demo1();
B b=new Demo1();
Demo1 d=new Demo1();
a.f();
b.f();
d.f();
}
@Override
public void f() {
System.out.println("A&B");
}
}
Java8现在(Java8之后)Java 通过默认方法具有了某种多继承的特性。结合带有默认方法的接口意味着结合了多个基类中的行为
比如A接口中有一个f()方法,B接口中有一个和A方法中具有相同函数签名的f方法,此时C实现A,B两个接口,如果需要使用f方法,需要重写f方法(只实现一个接口,该接口中的默认方法可以不用重写),如果需要调用接口中的f方法,可以使用super关键字
interface A{
default void f(){
System.out.println("A");
}
}
interface B {
default void f(){
System.out.println("B");
}
}
public class Demo1 implements A,B {
public static void main(String[] args){
Demo1 d=new Demo1();
d.f();
}
@Override
public void f() {
System.out.println("A&B");
A.super.f();
B.super.f();
}
}
4. 抽象类和接口的比较
–
5. 实现接口和继承类的结合
case1: 接口中的默认方法和抽象类中的非抽象方法函数签名相同且子类没有重写该方法时,优先使用父类的方法
interface A{
default void f(){
System.out.println("A");
}
}
abstract class B{
public void f(){
System.out.println("B");
}
}
public class Demo1 extends B implements A {
public static void main(String[] args){
Demo1 d=new Demo1();
d.f();//B
}
}
case2: 两个接口中的方法函数签名相同(函数返回值不作为签名的一部分),但是返回值不同,子接口继承这两个接口时编译会报错
interface A{
void f();
}
interface B{
int f();
}
interface C extends A,B{
//编译报错
}
case3: 父接口和父类中的方法函数签名相同(函数返回值不作为签名的一部分),但是返回值不同,子接口继承实现类和接口时编译会报错
interface A{
void f();//not ok
//void f(int i);ok
}
class B{
public int f(){
return 1;
}
}
class C extends B implements A{
//编译错误
}
case4: 两个父接口,一个接口中的默认方法的函数签名和另外一个接口中的抽象方法函数签名相同,会产生方法冲突
interface A{
void f();//not ok
//void f(int i);ok
}
interface B{
default void f(){
System.out.println("B");
}
}
class C implements A,B{
//方法名冲突
}
6. 接口中的字段
接口中的字段都自动是 static 和 final 的
interface A{
int a=1;
}
public class Demo1 {
public static void main(String[] args){
System.out.println(A.a);//通过接口名直接返回
A.a=100;// not ok
}
}