◼ Java类可定义一些不含方法体的方法,它的实现交给子类根据自己的情况去 实现,这样的方法就是抽象方法,包含抽象方法的类叫抽象类
◼ 抽象关键字:abstract
◼ 抽象类只是一个类型的部分实现,所以不能被实例化(不能new对象) (那有啥用?)
◼ abstract不能用于static方法或者构造函数,也不能与private、final共同修饰 同一个方法 (想想)
抽象类示例 抽象类示例2 (带构造函数的抽象类)抽象类Animal:
◼ 公有属性:animalName(String)
◼ 2个构造函数:Animal()、Animal(String)
◼ 抽象方法:eat()
子类: Dog和Cat类
◼ 各自都有构造函数: Dog()/Dog(String)、Cat()/Cat(String)
◼ 各自实现抽象方法:eat()
◼ 分别输出: "某某狗吃骨头!", "某某猫吃老鼠!"
测试类
public class Test {
public static void main(String args[]) {
//Animal a = new Animal(); //报错
Animal a = new Dog("哈士奇");
//Animal a = new Cat("大橘");
a.eat();
}
}
抽象类特点归纳
◼ 含有抽象方法的类必须被声明为抽象类。但抽象类中不一定包含的都是抽象方法
◼ 抽象类可以有构造方法,但构造方法不能声明为抽象★
◼ 抽象类提供一个类型的部分实现,所以不能被实例化(即不能用new去产生对象), 但可声明对象(用于多态) ★
◼ 抽象类不能用final来修饰,即一个类不能既是最终类又是抽象类
◼ 抽象类的子类必须重写所有抽象方法后才能被实例化,否则子类还是个抽象类
◼ 抽象方法只需声明,而不需实现
◼ abstract不能与private、static、final并列修饰同一个方法
接口 1. 接口概念
接口是一种特殊的抽象类:
◼ 如果一个抽象类中的所有方法都是抽象的,这个类就定义为接口 (interface)
◼ 接口的所有方法通常由子类全部实现 (是implements而非extends),不同子类的 实现可以具有不同的功能
◼ 如果一个类没有全部实现某个接口的所有方法,则这个类必须声 明为抽象的
接口示例定义Shape接口,包含两个抽象方法:
◼ double getPerimeter(); //求周长
◼ double getArea(); //求面积
两个实现类:
◼ 矩形类(Rectangle)和圆(Circle)类
◼ 有自有属性,能求周长和面积
Shape接口
public interface Shape {
public abstract double getPerimeter(); //求周长
public abstract double getArea(); //求面积
}
其中public abstract可省略不写,即接口内方法默认是公有、抽象的
Rectangle类
class Rectangle implements Shape { //implements实现接口
private double height;
private double width;
public Rectangle(double height,double width) {
this.height = height;
this.width = width;
}
@Override
public double getPerimeter() { //实现接口方法
return 2 * (height + width);
}
@Override
public double getArea() {//实现接口方法
return height * width;
}
}
Circle类
class Circle implements Shape {//implements实现接口
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getPerimeter() {//实现接口方法
return 2 * Math.PI * radius;
}
@Override
public double getArea() {//实现接口方法
return Math.PI * radius * radius;
}
}
测试类
public class Test {
public static void main(String[] args) {
Shape r = new Rectangle(10,10); //多态体现
// Shape r=new Circle(10); //多态体现
System.out.println("矩形面积="+ r.getArea() );
System.out.println("矩形周长="+ r.getPerimeter() );
}
}
//Shape s = new Shape(); × 接口不能被实例化
2. 接口常量
◼ 接口中不能有变量,但可有常量
◼ 常量默认是 public static final 类型(公有全局静态常量),且必须被 显示初始化。
为什么不能定义变量:由于接口中的方法都是抽象的,如果接口可以定义变量,那么在接口中 无法通过行为(方法)来修改属性。
为什么是public static:接口提供的是一种统一的"协议",接口中的属性也属于"协议"成员,所 有实现类都可以共享这一"协议"。
为什么是final:实现接口的对象如果修改了接口中的属性,那么所有对象也都会自动拥有这一 改变后的值,这和接口提供的统一的抽象这种思想相抵触。
接口常量示例接口常量调用方法:接口名.常量
public interface A {
public static final int END=0; // OK 标准写法
private final int OK=1; // × 不能为private
int a; // × 没有初始化属于变量,接口不能有变量
int b=1; // OK 初始化的变量会自动被识别为public static final常量
public final int NO=-1; // OK 不写也默认是static
static int share=0; // OK 不写也默认是public、final
}
//建议后三行public static final都写全
接口常量用法
3. 接口default/static方法
◼ Java 8 以后,接口可添加 default 或者 static 方法 (有实现的)
static方法:实现接口的类或者子接口不会继承(不能重写),用接口.方法名()调用
default方法:实现接口的类可以继承,可以选择重写 (注:多接口实现如有同名default方法则必须重写)
接口default方法
public interface A {
public default void foo(){ //default不能省略
System.out.println("这是default方法");
}
}
class B implements A {
public void foo() { //实现类可以继承default方法或根据需要重写 (重写时不加default)
System.out.println("重写default方法");
}
}
class Test {
public static void main(String[] args) {
A a = new B();
a.foo(); // 多态,输出 重写default方法
}
}
接口static方法
public interface A {
public static void a(){ //static不能省略
System.out.println("这是A");
}
}
public class B implements A { //实现类不会继承static方法(不能重写)
}
public class test {
public static void main(String[] args) {
A a = new B();
a.a(); // × //实现类不会继承接口中的 static 方法
A.a(); // 正确调用
}
}
4. 多接口
◼ Java一个类可以实现多个接口,从而间接的实现多继承
interface A {
double fun1();
}
Interface B {
double fun2();
}
class C implements A , B {
public double fun1() {
//实现方法
}
public double fun2() {
//实现方法
}
}
多接口编程
◼ 将Shape接口用多接口实现
Rectangle类实现多接口
class Rectangle implements Shape1, Shape2 { //实现多接口
private double height;
private double width;
public Rectangle(double height,double width) {
this.height = height;
this.width = width;
}
@Override
public double getArea() { //实现shape1接口的所有方法
return height * width;
}
@Override
public double getPerimeter() { //实现shape2接口的所有方法
return 2 * (height + width);
}
}
Circle类实现多接口
class Circle implements Shape1, Shape2 {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}
5. 接口继承多接口
Java类只支持单继承,不支持多继承 但接口可以继承多个其他接口
public interface A {
void fa();
}
public interface B {
void fb();
}
public interface C extends A, B {
void fc();
}
public class E implements C {
…//必须实现接口(包括父接口)所有的方法,如fa()、fb()、fc()
}
6. 接口的特点总结
◼ 接口中的方法默认都是 public abstract 类型(可省略),没有方法体
◼ 接口不能有构造函数,不能被实例化 (注:抽象类可以有构造函数)
◼ 接口中不能有变量,常量默认是 public static final,必须被显示初始化
◼ 接口中不能包含静态抽象方法,可以有default 或者 static 方法 (Java 8以后)
示例
public interface A {
int var=1; // OK,实际是public static final常量
public A() { } // 报错,接口不能有构造函数
void method1() { } // 报错,接口抽象方法没有方法体
protected void method2(); // 报错,接口方法必须是public abstract
static void method3(); // 报错,接口不能包含静态抽象方法
static void method4() { } // OK,接口可以包含静态方法,此方法可以有方法体
default void method5() { } // OK,接口可以包含default方法
}
◼ 当一个类实现某个接口时,它必须重写这个接口的所有抽象方法(包括这个接口的父接口中的方法),否则这个类必须声明为抽象的
◼ 一个类可以实现多个接口
class C implements A , B { … }
◼ 一个接口可继承多个其它的接口 ★
interface C extends A, B { … }
◼ 一个接口不能实现(implements)另一个接口:
interface a implements b{ … } //错,接口不能实现接口
◼ 一个类在继承一个父类的同时,可实现一个或多个接口,但extends关键字必 须位于implements关键字之前:
public class A extends B implements C, D {...}
◼ 不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变 量引用实现了这个接口的类的实例(多态)
抽象类和接口对比匿名类
◼ 匿名类:是指没有类名的内部类,必须在创建时使用 new 语句来声 明类(编译成功后还是会安排一个特殊名字)
◼ 语法形式如下:
new 类或接口() { //可以是普通类、抽象类或接口
// 类的主体 通常是重写父类方法或实现接口方法
};
匿名类特点
◼ 匿名类总是一个内部类,并且不能是static的
◼ 匿名类不能是抽象的,必须要实现继承的类或者实现的接口的所有抽象方法
◼ 匿名类总是隐式的final
◼ 匿名内部类中是不能定义构造函数的
◼ 匿名内部类中不能存在静态成员变量和静态方法(静态常量可以有 static final)
◼ 匿名类的class文件命名是:主类+$+1,2,3....
◼ 普通内部类的class文件命名是:主类+$+内部类名
Lambda表达式
◼ Lambda 表达式是一个匿名函数(也称为箭头函数)
◼ Lambda语法格式:
(类型 参数) ‐> { 代码语句; }
(int a, int b) -> {
int c = a + b;
return c;
}
//进一步省略
(a, b) -> a + b
() -> 5 // 无参数,返回值为 5 return都被省略
(int x, int y) -> x + y // 2个int参数,返回和
(x, y) -> x – y // 2个参数(数字),返回差值
x -> 2 * x // 接收一个参数(数字),返回其2倍 x仅仅是一个形参名
(String s) -> System.out.print(s) // String参数,只输出,无返回值
函数式接口
◼ 函数式接口:有且只有一个抽象方法的接口
◼ @FunctionalInterface注解:当接口中声明的抽象方法多于或少于一 个时就会报错
@FunctionalInterface
interface Person{
void speak;
void eat;
}//报错 多于一个
函数式接口的匿名类实现
@FunctionalInterface
interface Person {
void speak();
}
public class Test {
public static void main(String[] args) {
Person p = new Person() {
@Override
public void speak() {
System.out.println("boy");
}
};
p.speak();
}
}
函数式接口的Lambda表达式实现
public class Test {
public static void main(String[] args) {
Person p = ()->System.out.println("boy") ;
p.speak();
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)