抽象类、内部类、接口、枚举

一、抽象类

1、为什么使用抽象类

类用于描述现实生活中的一类事物,类中有属性有方法,方法都有方法体。
某种情况下,父类只能知道子类应该具备一个怎样的方法,但是不能明确知道子类如何实现该方法
例如:几何图形(多态练习),所有几何图形都应该具备计算面积的功能,但是不同几何图形计算面积的方式不同

Java 为上述问题提供了相应的解决办法
Java 允许父类中只是提供一个方法的声明,不提供具体的实现,具体的实现交给子类来完成
该方法称为“抽象方法”,拥有一个或多个抽象方法的类,称为“抽象类”

2、如何使用抽象:abstract

1)使用 abstract 修饰的类称为“抽象类”
①格式:访问控制修饰符 abstract class 类名{}
②拥有一个或多个抽象方法的类必须是抽象类
③抽象类中可以有非抽象方法,抽象类中可以没有抽象方法
④**抽象类不能创建实例
⑤抽象类中可以声明构造器。
​ 目的:当子类继承父类后,继承父类中所有的属性和方法,因此子类需要知道父类如何进行初始化

  1. 使用 abstract 修饰的方法称为“抽象方法”
    ①格式:访问控制修饰符 abstract 返回值类型 方法名(参数列表);
    ②子类继承父类后,若重写了父类中“所有”的抽象方法,该类是具体类,可以创建实例
    ③子类继承父类后,若没有重写父类中“所以”的抽象方法,该类必须是抽象类,不可以创建实例
abstract class Person{
    
    private String name;
    private int age;
    
    public Person(){}
    
    public void setName(String name){
        this.name = name;
    }
    
    //人都应该具备一个说话的功能,但是不同的人说话的方式不同
    public abstract void speak();
}

class Chinese extends Person{
    
    public void speak(){
        System.out.println("中国人说汉语");
    }
}

abstract class American extends Person{
    //public abstract void speak();
}

3、abstract 关键字的注意

① abstract 和 final 不能同时使用
② abstract 和 static 不能同时使用
③ abstract 和 private 不能同时使用
④ abstract不能用来修饰:属性、构造器等结构,不能用来修饰私方法、静态方法。

二、接口

可以定义多个不相关事物的相同功能

1、如何使用接口(如下以jdk1.7为标准)

①接口与类时平级的
​ 关键字:interface

​ 如:
​ public interface Flyer{}

②可以把接口理解为特殊的抽象类,因为jdk1.7前接口中只能定义“全局静态常量”和抽象方法

//全局静态常量
int NUM = 100;//public static final 

//抽象方法
void fly();//public abstract 

③接口中不能有变量、构造器、代码块
④**接口不能创建实例
⑤接口就是用来被实现的
​ 实现接口关键字:implements
​ 如:
​ class Bird implements Flyer{}

⑥实现接口的类称为“实现类”,实现类的功能和“继承”一样的,可以继承接口中所有的成员
⑦若实现类实现了接口中所有的抽象方法,该类为具体类,可以创建实例
若实现类没有实现接口中所有的抽象方法,该类必须是抽象类,不能创建实例
⑧接口可以多实现 — 解决了 Java 中单继承的局限性
​ 如:
​ class Bird implements Flyer, Runner{}

⑨接口不能继承任何类,接口可以继承接口并且可以多继承接口
⑩一个类可以继承另一个类,同时实现多个接口
​ 如:
​ class Bird extends Animal implements Flyer, Runner{}

​ 注意:先继承,后实现

体会:

  • 1.接口使用上也满足多态性
  • 2.接口,实际上就是定义了一种规范
  • 3.开发中,体会面向接口编程!

体会面向接口编程的思想
在这里插入图片描述

面向接口编程:我们在应用程序中,调用的结构都是JDBC中定义的接口,不会出现具体某一个。

2、jdk1.8对于接口的升级

(Lambda表达式需要函数式接口(接口中只有一个抽象方法的接口)的支持)
//知识点1:接口中定义的静态方法,只能通过接口来调用。

//知识点2:通过实现类的对象,可以调用接口中的默认方法。
//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法

//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没重写此方法的情况下,默认调用的是父类中的同名同参数的方法。–>类优先原则
//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
//那么在实现类没重写此方法的情况下,报错。–>接口冲突。
//这就需要我们必须在实现类中重写此方法
//知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
public void myMethod(){
method3();//调用自己定义的重写的方法
super.method3();//调用的是父类中声明的
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}

public class DefaultMethodTest {

    public static void main(String[] args) {
        SubClass sc = new SubClass();
        //若接口中与父类中具有相同方法签名的方法时,默认为类优先原则,接口中的默认方法会被忽略
        sc.show();

        MyInterface.test();
    }

}

interface MyInterface{

    default void show(){
        System.out.println("接口中的默认方法");
    }

    public static void test(){
        System.out.println("接口中的静态方法");
    }
}

interface MyFun{

    default  void show(){
        System.out.println("MyFun 接口中的默认方法");
    }

}

class MySuperClass{

    public void show(){
        System.out.println("父类中的方法");
    }

}

class SubClass /*extends MySuperClass*/ implements MyInterface, MyFun{
    @Override
    public void show() {
        MyFun.super.show();
    }
}

面试题:

抽象类和接口的异同?
相同点:不能实例化;都可以包含抽象方法的。
不同点:
1)把抽象类和接口(java7,java8,java9)的定义、内部结构解释说明
2)类:单继承性 接口:多继承
类与接口:多实现

三、内部类

1、成员内部类

在类中声明另一个类,里面的类称为内部类,外面的类称为外部类

成员内部类的理解:
一方面,作为外部类的成员:

  •  	>调用外部类的结构
    
  •  	>可以被static修饰
    
  •  	>可以被4种不同的权限修饰
    

另一方面,作为一个类:

  •  	> 类内可以定义属性、方法、构造器等
    
  •  	> 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
    
  •  	> 可以被abstract修饰
    
class Person{
    
    private String name;
    
    public Person(){
        System.out.println(name);
        setName("李四");
        Computer com = new Computer();
    }
    
    public void setName(String name){
        this.name = name;
    }
    
    public String getName(){
        return name;
    }
    
    //成员内部类
    public class Computer{
        
        private String name;
        
        public Computer(){}
        
        public void setName(String name){
            System.out.println("局部变量 name:" + name);
            System.out.println("当前内部类Computer对象的 name: " + this.name);
            System.out.println("当前外部类Person对象的 name:" + Person.this.name);
            System.out.println("不需要区分使用同级别成员:" + getName());
            this.name = name;
        }   
    }
    
    //对类的隐藏
    private class Head{
        
    }
    
    //静态内部类
    static class Mobile{
        public void show(){
            System.out.println("静态内部类中的方法");
        }
    }
    
}

class InnerClassTest{
    
    public static void main(String[] args){
        //创建静态内部类对象
        Person.Mobile pm = new Person.Mobile();
        pm.show();
        
        //创建非静态内部类的对象
        Person p = new Person();
        Person.Computer pc = p.new Computer();
        pc.setName("IBM");
    }
    
}

2、局部内部类

//如下方式使用较少
    public void show(){

        int num = 10;
		//局部内部类
        class Inner{

            public void test(){
                System.out.println(num);
                //注意:若局部内部类中使用了同级别的局部变量,该局部变量必须使用 final 修饰
                //jdk1.7 必须手动加 final,jdk1.8默认为 final
            }
        }

        Inner in = new Inner();
    }
   //
    public Comparator getComparator(){
        //
        return new MyComparator();
    }

    public Comparator getComparator1(){

        //若该类仅对于当前方法有用,可以声明为局部内部类
        class MyComparator implements Comparator{

        @Override
        public int compare(Object o1, Object o2) {
            return 0;
        }
    }

        return new MyComparator();
    }

    public Comparator getComparator2(){
        //匿名内部类
        Comparator com = new Comparator(){

            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        };

        return com;
    }

    public Comparator getComparator3(){
        //
        return new Comparator(){

            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        };
    }

总结:
成员内部类和局部内部类,在编译以后,都会生成字节码文件。
格式:成员内部类:外部类 内 部 类 名 . c l a s s 局 部 内 部 类 : 外 部 类 内部类名.class 局部内部类:外部类 .class数字 内部类名.class

四、枚举类

是 jdk1.5 后出的特性,可以定义有限数量的可穷举数据集。

  • 1.枚举类的理解:类的对象只有有限个,确定的。我们称此类为枚举类
  • 2.当需要定义一组常量时,强烈建议使用枚举类
  • 3.如果枚举类中只一个对象,则可以作为单例模式的实现方式。

1、自定义枚举

①私有化构造器

②类的内部创建对象

package com.atguigu.java;

/*
自定义枚举类
 */
public class Season1 {

    private String seasonName;
    private String seasonDesc;

    //2. 类的内部创建对象
    public static final Season1 SPRING = new Season1("春天", "春眠不觉晓");
    public static final Season1 SUMMER = new Season1("夏天", "夏天蚊子咬");
    public static final Season1 AUTUMN = new Season1("秋天", "秋天叶子黄");
    public static final Season1 WINTER = new Season1("冬天", "冬天雪花飘");

    //1. 私有化构造器
    private Season1(String seasonName, String seasonDesc){
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    public String getSeasonName() {
        return seasonName;
    }

    public void setSeasonName(String seasonName) {
        this.seasonName = seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    public void setSeasonDesc(String seasonDesc) {
        this.seasonDesc = seasonDesc;
    }

    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

2、使用 enum 关键字

​ valueOf(String name) : 根据枚举类对象的名称,获取枚举类对象

​ values() : 获取当前枚举类中所有的枚举类对象,组成的数组

public enum Season1 {
    
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

}

3、枚举类实现接口

public enum Season1 implements MyInterface{
    
    SPRING{
        public void show(){
            System.out.println("春天");
        }
    },
    SUMMER{
        public void show(){
            System.out.println("夏天");
        }
    },
    AUTUMN{
        public void show(){
            System.out.println("秋天");
        }
    },
    WINTER{
        public void show(){
            System.out.println("冬天");
        }
    };
    
    /*public void show(){
        System.out.println("季节");
    }*/

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值