抽象类
abstract:抽象的(可以修饰类和方法)
- abstract修饰类:抽象类
- 此类不能实例化
- 抽象类中一定有构造器,便于子类实例化时调用(涉及子类对象实例化的全过程)
- 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作
- abstract修饰方法:抽象方法
- 抽象方法只有方法的声明,没有方法体
- 包含抽象方法的类一定是抽象类;反之,抽象类可以没有抽象方法
- 若子类重写了子类的所有的抽象方法,此类方可实例化;若子类没有重写子类的所有的抽象方法,则此类也是一个抽象类
注意点:
- abstract不能用来修饰属性、构造器等结构
- abstract不能用来修饰私有方法、静态方法、final的方法和final的类
抽象类的匿名子类
public class AbstractTest {
public static void main(String[] args) {
//抽象类的匿名子类
Creature c = new Creature() {
@Override
public void breath() {
System.out.println("人呼吸");
}
};
method(c);
}
public static void method(Creature c){
c.breath();
}
}
abstract class Creature{
public abstract void breath();
}
模块方法的设计模式
public class TemplateTest {
public static void main(String[] args) {
Template t = new SubTemplate();
t.spendTime();
}
}
abstract class Template{
//计算某段代码执行所花费的时机
public void spendTime(){
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
}
public abstract void code();
}
class SubTemplate extends Template{
@Override
public void code() {
for (int i = 2; i <= 1000; i++){
boolean isFlag = true;
for (int j = 2; j <= Math.sqrt(i); j++){
if (i % j == 0){
isFlag = false;
break;
}
}
if (isFlag){
System.out.println(i);
}
}
}
}
接口
interface:接口(一种规范)
- 定义接口
- JDK7及以前:只能定义全局常量和抽象方法
全局常量:public static final(书写时可以省略)
抽象方法:public abstract(书写时可以省略)
- JDK8:还可以定义静态方法、默认方法
- 接口中不能定义构造器,意味着接口不可以实例化
- Java开发中,接口通过让类去实现(implements)的方式来使用
- 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
- 如果实现类没有覆盖了接口中的所有抽象方法,则此实现类仍为一个抽象类
- Java类可以实现多个接口–>弥补了Java单继承性的局限性
格式:class AA extends BB implements CC,DD,EE
- 接口与接口之间可以多继承
- 接口的具体使用,体现多态性
接口的匿名实现类
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
Plane plane = new Plane();
plane.fly();
plane.testMin();
//接口的匿名实现类
Flyable f = new Flyable() {
@Override
public void fly() {
System.out.println("手动起飞");
}
@Override
public void stop() {
System.out.println("手动停止");
}
};
f.fly();
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 7900;
int MIN_SPEED = 1;
//抽象方法
public abstract void fly();
void stop();
}
class Plane extends FlyableClass implements Flyable,CC{
@Override
public void fly() {
System.out.println("通过引擎起飞");
}
@Override
public void stop() {
System.out.println("驾驶员减速停止");
}
@Override
public void method1() {
System.out.println("method1");
}
@Override
public void method2() {
System.out.println("method2");
}
public void testMin(){
//System.out.println(MIN_SPEED); //编译错误
System.out.println(super.MIN_SPEED); //0
System.out.println(Flyable.MIN_SPEED); //1
}
}
class FlyableClass{
int MIN_SPEED = 0;
}
interface AA{
void method1();
}
interface BB{
void method2();
}
interface CC extends AA,BB{
}
代理模式
public class NetWorkTest {
public static void main(String[] args) {
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
}
interface NetWork{
public void browse();
}
//被代理类
class Server implements NetWork{
@Override
public void browse() {
System.out.println("真实的服务器访问网络");
}
}
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work) {
this.work = work;
}
public void check(){
System.out.println("联网之前的检查工作");
}
@Override
public void browse() {
check();
work.browse();
}
}
工厂模式
public class FactoryTest {
public static void main(String[] args) {
//工厂方法模式
Car a = new AudiFactory().getCar();
Car b = new BydFactory().getCar();
a.run();
b.run();
}
}
interface Car{
void run();
}
//两个实现类
class Audi implements Car{
@Override
public void run() {
System.out.println("奥迪再跑");
}
}
class BYD implements Car{
@Override
public void run() {
System.out.println("比亚迪在跑");
}
}
//工厂接口
interface Factory{
Car getCar();
}
//两个工厂类
class AudiFactory implements Factory{
@Override
public Car getCar() {
return new Audi();
}
}
class BydFactory implements Factory{
@Override
public Car getCar() {
return new BYD();
}
}
Java8接口新特性
为什么要有默认方法?
主要是为了方便扩展已有接口:
- 如果没有默认方法,假如给JDK中的某个接口添加一个新的抽象方法,那么所有实现了该接口的类都需要修改。
- 使用默认方法,可以给已有接口添加新方法,而不用修改该接口的实现类。当然,接口中新添加的默认方法,所有实现类也会继承该方法。
ps:示例:在Java 8的Iterable接口中,新增了一个默认方法forEach,也正因为forEach是默认方法,才不用修改所有Iterable接口的实现类。
为什么要有静态方法?
接口静态方法类似于默认方法,但是我们不能在实现类中覆盖它们,可以避免默认方法在实现类中被覆盖实现。
静态方法和默认方法的使用
public interface CompareA {
// 静态方法
public static void method1(){
System.out.println("CompareA:北京");
}
// 默认方法:在接口中定义一个已实现方法,且该接口的实现类不需要实现该方法
public default void method2(){
System.out.println("CompareA:上海");
}
default void method3(){
System.out.println("CompareA:上海");
}
}
public interface CompareB {
default void method3(){
System.out.println("CompareB:上海");
}
}
public class SuperClass {
public void method3(){
System.out.println("SuperClass:北京");
}
}
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
//1、接口定义的静态方法,只能通过接口来调用
//s.method1();
CompareA.method1();
//2、通过实现类的对象,可以调用接口中的默认方法
s.method2();
//3、如果子类(或实现类)继承的父类和实现的接口声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法
//4、如果实现类实现了多个接口,而多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下报错-->接口冲突;这就需要我们必须在实现类中重写此方法
}
}
class SubClass extends SuperClass implements CompareA,CompareB{
public void method2(){
System.out.println("SubClass:上海");
}
public void method3(){
System.out.println("SubClass:深圳");
}
//5、
public void myMethod(){
method3(); //调用自己定义的重写的方法
super.method3(); //调用父类中声明的方法
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
}
注意点:
public class ClassA implements InterfaceB, InterfaceC{
@Override
public void foo() {
InterfaceB.super.foo();
// InterfaceC.super.foo(); // 报错
}
}
interface InterfaceA {
default void foo() {
System.out.println("InterfaceA foo");
}
}
interface InterfaceB extends InterfaceA{
@Override
default void foo() {
System.out.println("InterfaceB foo");
}
}
interface InterfaceC extends InterfaceA{
// @Override
// default void foo() {
// System.out.println("InterfaceC foo");
// }
}