接口,匿名内部类,枚举,泛型

目录

1.接口

2.接口的好处(重点):

2.应用案例:班级学生信息管理模块

3.接口新增的3种方法

4.接口的多继承

5.内部类:

匿名内部类(重点)

拓展:搞清楚匿名内部类在开发中的真实使用场景

6.枚举:

拓展:抽象枚举

使用枚举类实现单例设计模式

7.泛型

泛型类

泛型接口

泛型方法

泛型的上下限

注意:泛型的擦除问题和注意事项


1.接口

使用interface关键字定义的一种结构, JDK 8之前,接口中只能定义成员变量和成员方法。

public interface  接口名 {
// 成员变量(常量)
// 成员方法(抽象方法)

}

public interface A {
    // 成员变量(常量)
    String SCHOOL_NAME = "黑马程序员";

    // 成员方法(抽象方法)
    void test();

}

public class Test {
    public static void main(String[] args) {
  // 目标:认识接口。
        System.out.println(A.SCHOOL_NAME);

        // A a = new A();
    }
}

注意1.接口不能创建对象,接口是用来被类实现(implements)的,实现接口的类称为实现类

修饰符 class 实现类 implements 接口1,接口2,接口3,...{

}

2.一个接口可以继承多个接口,实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类。

public interface B {
    void testb1();
    void testb2();
}

public interface C {
    void testc1();
    void testc2();
}

// 实现类
public class D implements B, C{
    @Override
    public void testb1() {

    }

    @Override
    public void testb2() {

    }

    @Override
    public void testc1() {

    }

    @Override
    public void testc2() {

    }
}

public class Test {
    public static void main(String[] args) {
          D d = new D();

2.接口的好处(重点):

1.弥补了类单继承的不足,一个类同时可以实现多个接口。

2.让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。

import com.itheima.d5_abstract2.Animal;
import com.itheima.d5_abstract2.Cat;

public class Test {
    public static void main(String[] args) {
        // 目标:搞清楚使用接口的好处。
        Driver s = new A();
        s.drive();

        Driver d = new A();
        d.drive();

        Animal a = new Cat();
        a.cry();
    }
}

class B implements Driver{
    @Override
    public void drive() {

    }
}

class A extends Student implements Driver, Singer{
    @Override
    public void drive() {

    }

    @Override
    public void sing() {

    }
}

class Student{

}

interface Driver{
    void drive();
}

interface Singer{
    void sing();

2.应用案例:班级学生信息管理模块

接口,匿名内部类,枚举,泛型_第1张图片

public class ClassManager {

    private ArrayList students = new ArrayList<>();

    //private StudentOperator studentOperator = new StudentOperatorImpl1();

    private StudentOperator studentOperator = new StudentOperatorImpl2();


    public ClassManager(){  //构造器     通过构造器初始化班级对象
      //创建学生对象
        students.add(new Student("迪丽热巴", '女', 99));
        students.add(new Student("古力娜扎", '女', 100));
        students.add(new Student("马尔扎哈", '男', 80));
        students.add(new Student("卡尔扎巴", '男', 60));
    }

    // 打印全班全部学生的信息
    public void printInfo(){
        studentOperator.printAllInfo(students);
    }

    // 打印全班全部学生的平均分
    public void printScore(){
studentOperator.printAverageScore(students);
}
}




public interface StudentOperator {
    void printAllInfo(ArrayList students);         //抽样方法

    void printAverageScore(ArrayList students);
}



//实现类

public class StudentOperatorImpl1 implements StudentOperator{  
//抽样方法全部重写  alt+回车

    @Override
    public void printAllInfo(ArrayList students) {
        System.out.println("----------全班全部学生信息如下--------------");
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            System.out.println("姓名:" + s.getName() + ", 性别:" + s.getSex() + ", 成绩:" + s.getScore());
        }
        System.out.println("-----------------------------------------");
    }

    @Override
    public void printAverageScore(ArrayList students) {
        double allScore = 0.0;
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            allScore += s.getScore();
        }
        System.out.println("平均分:" + (allScore) / students.size());
    }
}




//第二套方案
public class StudentOperatorImpl2 implements StudentOperator{

    @Override
    public void printAllInfo(ArrayList students) {
        System.out.println("----------全班全部学生信息如下--------------");
        int count1 = 0;      //记录男生人数
        int count2 = 0;      //记录女生人数
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            System.out.println("姓名:" + s.getName() + ", 性别:" + s.getSex() + ", 成绩:" + s.getScore());
            if(s.getSex() == '男'){
                count1++;
            }else {
                count2 ++;
            }
        }
        System.out.println("男生人数是:" + count1  + ", 女士人数是:" + count2);
        System.out.println("班级总人数是:" + students.size());
        System.out.println("-----------------------------------------");
    }

    @Override
    public void printAverageScore(ArrayList students) {
        
        double allScore = 0.0;
        double max = students.get(0).getScore();  //第一个学生成绩
        double min = students.get(0).getScore();
    
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
           
            if(s.getScore() > max) max = s.getScore();
            if(s.getScore() < min) min = s.getScore();
            allScore += s.getScore();
        }
        System.out.println("学生的最高分是:" + max);
        System.out.println("学生的最低分是:" + min);
        System.out.println("平均分:" + (allScore - max - min) / (students.size() - 2));
    }
}




public class Test {
    public static void main(String[] args) {
        // 目标:完成班级学生信息管理的案例。
        ClassManager clazz = new ClassManager();
        clazz.printInfo();
        clazz.printScore();
    }
}



public class Student {
    private String name;
    private char sex;
    private double score;

    public Student() {
    }

    public Student(String name, char sex, double score) {
        this.name = name;
        this.sex = sex;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

3.接口新增的3种方法

1.默认方法:必须使用default修饰,默认会被public修饰
    实例方法:对象的方法,必须使用实现类的对象调用

2.私有方法:必须使用private修饰(jdk9开始),只能在接口内部被调用
    实例方法:对象的方法。

3. 静态方法:必须使用static修饰,默认会被public修饰

    接口名.方法();

public interface A {
    /*1.默认方法:必须使用default修饰,默认会被public修饰
    实例方法:对象的方法,必须使用实现类的对象访问*/
    default  void test1() {
        System.out.println("======默认方法=======");
        test2();
    }
    /*
    2.私有方法:必须使用private修饰(jdk9开始)
    实例方法:对象的方法。
         */
       private void test2(){
         System.out.println("=========私有方法=======");
      }

        /*
    3. 静态方法:必须使用static修饰,默认会被public修饰
         */
    static  void test3(){
        System.out.println("==静态方法=======");
    }
}

public class B implements A{

}

public class Test {
    public static void main(String[] args) {
        //掌握接口3种方法
        B b =new B();
        b.test1();
        A.test3();
    }
}

4.接口的多继承

一个接口可以继承多个接口

作用:便于实现类去实现

5.内部类:

是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。

1.成员内部类(了解):类中一个普通成员,类似于普通成员变量,成员方法

接口,匿名内部类,枚举,泛型_第2张图片

 成员内部类中访问其他成员的特点:

1、同样可以直接访问外部类的实例成员、静态成员。

2、拿到当前外部类对象,格式是:外部类名.this

接口,匿名内部类,枚举,泛型_第3张图片

接口,匿名内部类,枚举,泛型_第4张图片

2.静态内部类(了解):有static修饰的内部类,属于内部类自己持有

   可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员

接口,匿名内部类,枚举,泛型_第5张图片

 接口,匿名内部类,枚举,泛型_第6张图片

匿名内部类(重点)

是一种特殊的局部内部类 ,所谓匿名:指的是程序员不需要为这个类声明名字。

new  类或接口(参数值...){

类体(一般是方法重写);

};

特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。

作用:用于更方便的创建一个子类对象

           通常作为一个参数传输给方法。

public class Test {
    public static void main(String[] args) {
        // 目标:认识匿名内部类,并掌握其作用。

        // 1、把这个匿名内部类编译成一个子类,然后会立即创建一个子类对象出来。
        Animal a = new Animal(){
            @Override
            public void cry() {
                System.out.println("猫喵喵喵的叫~~~");
            }
        };
        a.cry();
    }
}
abstract class Animal{
    public abstract void cry();
}

使用场景:

Test2类
public class Test2 {
    public static void main(String[] args) {
        // 目标:掌握匿名的常见使用场景。

        go(new Swimming(){
            @Override
            public void swim() {
                System.out.println("狗游泳飞快~~~~");
            }
        });

    }

    // 设计一个方法,可以接收swimming接口的一切实现类对象进来参加游泳比赛。
    public static void go(Swimming s){
        System.out.println("开始-----------------------");
        s.swim();
    }
}
//猫和狗都参加游泳比赛  实现
interface Swimming{
void swim();
}

拓展:搞清楚匿名内部类在开发中的真实使用场景

public class Test {
    public static void main(String[] args) {
        //GUI编程
        //1.创建窗口
        JFrame win = new JFrame("登录界面");
        JPanel panel = new JPanel();//桌布
        win.add(panel);//把桌布加入到窗口当中去

        JButton btn = new JButton("窗口");
        panel.add(btn);

        //给按钮绑定单击事件(单击事件监听器)
//        btn.addActionListener(new ActionListener() {
//            @Override
//            public void actionPerformed(ActionEvent e) {
//                JOptionPane.showMessageDialog(win,"登录一下");
//            }
//        });
        //简化代码
        btn.addActionListener(e -> JOptionPane.showMessageDialog(win,"登录一下"));

        win.setSize(408,408);
        win.setLocationRelativeTo(null);//居中
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭窗口,退出程序
        win.setVisible(true);//显示出来
    }
}

6.枚举:

是一种特殊类。

修饰符  enum  枚举类名{

名称1,名称2..

其他成员...

}

注意:1.枚举类的第一行必须罗列的是枚举对象的名字,都是常量 ,并且每个常量记住的都是枚举类的一个对象。

2.构造器都是私有的,枚举类不能创建对象,是最终类,不能被继承

public enum A {
    //注意:枚举类的第一行必须罗列的是枚举对象的名字,都是常量
    X, Y, Z;
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

public class Test {
    public static void main(String[] args) {
        //目标 认识枚举
        A a1 =A.X;
        System.out.println(a1);  //X


        //枚举类提供一个一些额外的API
        A[] as = A.values();//拿到全部对象
        A a3 = A.valueOf("Z");
        System.out.println(a3.name());  //Z
        System.out.println(a3.ordinal());  //索引
    }
}

拓展:抽象枚举

public enum B {
    X() {
        @Override
        public void go() {

        }
    },Y("站三"){
        @Override
        public void go() {
            System.out.println(getName()+ "再跑--");
        }
    };

    private String name;

    B() {
    }

    B(String name) {
        this.name = name;
    }

    public abstract void go();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}



public class Test{
main
B y = B.Y;
y.go();
}

使用枚举类实现单例设计模式

public enum C {

       X;  //单例

}

常见应用场景:用来表示一组信息,然后作为参数进行传输

public enum Constant2 {
    BOY,GIRL;
}



public class Test {
    public static void main(String[] args) {
//目标:掌握枚举的应用场景:做信息标志和分类
         check(Constant.BOY);

    }
    public  static void check(Constant2 sex){
        switch (sex){
            case BOY:
                System.out.println("展示一些美女");
                break;
            case GIRL:
                System.out.println("展示一些帅哥");
                break;
        }
    }
}

7.泛型

定义类,接口,方法时,同时声明了一个或者多个类型变量(,称为泛型类,泛型接口,泛型方法 

public class ArrayList{    

. . .

}

作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。

泛型的本质:把具体的数据类型作为参数传给类型变量

 ArrayList list = new ArrayList<>();
    list.add("java1");
     list.add("java2");
    list.add("java3");
  //list.add("new Cat");
        for (int i = 0; i < list.size(); i++) {
            String e = list.get(i);
            System.out.println(e);
        }
}

泛型类

修饰类 class 类名<类型变量,类型变量,..>{

// 泛型类
public class MyArrayList {
    private Object[] arr = new Object[10];
    private int size; // 记录当前位置的

    public boolean add(E e){
        arr[size++] = e;
        return true;
    }

    public E get(int index){   //根据索引查数据类型
        return (E) arr[index];  //强转结果
    }
}

 
//
public class MyClass2 {
    public void put(E e, T t){

    }
}


//
public class MyClass3 {

}




public class Test {
    public static void main(String[] args) {
        // 目标:掌握泛型类的定义和使用。
        MyArrayList list = new MyArrayList<>();
        list.add("java1");
        list.add("java2");
        String ele = list.get(1);
        System.out.println(ele);

        MyClass2 c2 = new MyClass2<>();

        // MyClass3 c3 = new MyClass3<>(); // 报错
        MyClass3 c4 = new MyClass3<>();
        MyClass3 c5 = new MyClass3<>();
    }
}

泛型接口

用来给实现类实现的,可以声明数据类型上来,然后实现类重写这些方法,都将针对该类型操作

修饰符 interface 接口名<类型变量,类型变量,..>{

}

泛型变量建议用大写的英文字母。常用有:E,T, K, V

public class Test {
    public static void main(String[] args) {
        //掌握泛型接口定义和使用
        //系统需要处理学生和老师的数据,需要提供2个功能,保存对象数据,根据名称查询数据

    }
}

import java.util.ArrayList;

//泛型接口
public interface Data {  
//public interface Data {  //也可以继承
    void add(T t);
    ArrayList getByName(String name);
}

//老师类
public class Teacher {
}

//实现类
public class TeacherData implements Data{
    @Override
    public void add(Teacher teacher) {

    }

    @Override
    public ArrayList getByName(String name) {
        return null;
    }
}

//学生类
public class Student {
}

//实现类
public class StudentData  implements  Data{  //alt+回车
    @Override
    public void add(Student student) {
    }
    @Override
    public ArrayList getByName(String name) {
        return null;
    }
}

泛型方法

修饰符<类型变量,类型变量,...> 返回值类型  方法名(形参列表){

}

public static void test(T t){

}

public class Test {
    public static void main(String[] args) {
        // 目标:掌握泛型方法的定义和使用。
        String rs = test("java");
        System.out.println(rs);

        Dog d = test(new Dog());
        System.out.println(d);

        // 需求:所有的汽车可以一起参加比赛。
        ArrayList cars = new ArrayList<>();
        cars.add(new BMW());
        cars.add(new BENZ());
        go(cars);

        ArrayList bmws = new ArrayList<>();
        bmws.add(new BMW());
        bmws.add(new BMW());
        go(bmws);

        ArrayList benzs = new ArrayList<>();
        benzs.add(new BENZ());
        benzs.add(new BENZ());
        go(benzs);

//        ArrayList dogs = new ArrayList<>();
//        dogs.add(new Dog());
//        dogs.add(new Dog());
//        go(dogs);
    }

    // ? 通配符,在使用泛型的时候可以代表一切类型   ? extends Car(上限)   ? super Car(下限)
    public static void go(ArrayList cars){

    }

//    public static  void go(ArrayList cars){
//
//    }

    // 泛型方法
    public static  T test(T t){
        return t;
    }
}
通配符,在使用泛型的时候可以代表一切类型 ?extends Car(上限)   ? super Car(下限)

?,可以在“使用泛型”的时候代表一切类型;E T K V 是定义泛型的时候使用

泛型的上下限

泛型上限:   ? extends Car:   ? 能接收的必须是Car或者其子类 。  

泛型下限:  ?  super Car : ?  能接收的必须是Car或 者其父类。

注意:泛型的擦除问题和注意事项

1.泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除。

ArrayList list = new ArrayList<>();
        list.add("java1");
        list.add("java2");
        list.add("java3");
        String rs = list.get(2);
        System.out.println(rs);  

2.泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。 

//        ArrayList list1 = new ArrayList<>();
//        ArrayList list2 = new ArrayList<>();
        ArrayList list1 = new ArrayList<>();
        list1.add(12);

        ArrayList list2 = new ArrayList<>();
        list2.add(23.3);

        double a = 0.1;
        double b = 0.2;
        double c = a + b;
        System.out.println(a);
        BigDecimal a1 = new BigDecimal(0.1);

你可能感兴趣的:(java,开发语言)