第八天(坚持)
抽象类
1.什么是抽象类,作用特点。
抽象类是面向对象编程中一种特殊的类,它不能被实例化,主要用于作为其他类的基类(父类)。抽象类的主要作用是定义公共结构和行为规范,同时强制子类实现特定的功能,常用于将部分代码抽象到抽象类中。比较典型的就是模板方法模式。
抽象类中可以补定义抽象方法,但抽象方法一定在抽象类中。
注解(抽象类的特点)
1)由abstract修饰的方法为抽象方法,抽象方法没有方法体,需要使用分号结尾
2)若类中包含抽象方法,那么该类必须使用关键字abstract声明成抽象类,final不能修饰抽象类
3)抽象类里,可以没有抽象方法
4)抽象类里可以提供构造器,但是不能实例化,没有意义。
5)一个类继承了抽象类,那么必须重写里面的所有抽象方法,除非该子类也声明为抽象类。
接口
接口中不考虑Java8中default方法情况下,只能定义抽象类。接口主要用于制定规范,一般在实际开发中,我们会先把接口暴露给外部,然后在业务代码中实现接口。
接口特点
使用interface定义
可以提供成员变量,默认提供public static final进行修饰
可以提供成员方法,默认使用public abtract进行修饰
接口中不能存在构造器,接口不能实例化,
与继承不同,一个类可以实现多个接口。接口间使用逗号分开。
使用关键字implements进行实现,必须实现接口中的所有抽象方法
若一个类中没有全部实现接口中的抽象方法,那么该类需要使用abstract声明成抽象类
接口之间可以存在继承关系,即一个接口通过关键字extends可以继承另一个(或多个)接口。
子接口继承了父接口中的所有抽象方法
---------------------------------------------------------------------------------------------------------------------------------
接口和抽象类的区别
1.方法定义:接口和抽象类,最明显的区别就是接口只是定义了一些方法而已,在不考虑Java8中default方法情况下,接口中只有抽象方法,是没有实现的代码的。(Java8中可以有默认方法)
2.修饰符:抽象类中的修饰符可以有public、protected和private和<default>这些修饰符,而接口中默认修饰符是public。不可以使用其它修饰符。(接口中,如果定义了成员变量,还必须要初始化)
3.构造器:抽象类可以有构造器必须私有。接口不能有构造器。
4.接口可以被实现,抽象类可以被继承。一个类可以实现多个接口,一个接口可以继承多个其他接口但,一个抽象类只能继承一个抽象类。
5.职责不同:接口和抽象类的职责不一样。接口主要用于制定规范,一般在实际开发中,我们会先把接口暴露给外部,然后在业务代码中实现接口。抽象类的主要作用是定义公共结构和行为规范,同时强制子类实现特定的功能,常用于将部分代码抽象到抽象类中。比较典型的就是模板方法模式。
---------------------------------------------------------------------------------------------------------------------------------
枚举
在Java中,枚举是一种特殊的引用数据类型,是一个被命名的整型常数的集合,用于声明一组带标识符的常数,枚举在日常生活中很常见,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一个枚举。
枚举特点
使用enum关键字定义一个枚举,默认会继承java.lang.Enum类,而且是一个final类,因此不能再继承其他类
必须在枚举类的第一行声明枚举类对象。有多个枚举对象时,使用逗号隔开,最后一个用分号结尾
可以提供构造器,必须是私有的,如果构造器有形参,定义对象时必须显式调用构造器
如果使用无参构造器创建枚举对象,则定义对象时,小括号可以省略
可以提供私有的属性(建议,如不外部可以修该)
public enum Year{//1. 枚举的第一行,必须是该枚举的对象,即你要表达的离散值。多个离散值使用逗号隔开,最后一个值分号结束。JANUARY(1),FEBRUARY(2),MARCH(3),APRIL(4),MAY(5),JUNE(6),JULY(7),AUGUST(8),SEPTEMBER(9),OCTOBER(10),NOVEMBER(11),DECEMBER(12),AAAA; // 如果调用无参构造器,小括号可以省略//2. 枚举可以提供私有属性private int number;//3. 可以提供构造器,但是必须是私有的, 实际上枚举的离散值就是调用构造器产生的,// 调用构造器的格式: 离散值(有参传参)private Year(int number){this.number = number;}//4. 构造器可以重载private Year(){}// 5. 可以给私有的成员变量,提供get/set方法, 不建议提供set方法public int getNumber(){return number;} }
带有value的枚举
package com.rs.shuatiwang.model.enums; import cn.hutool.core.util.ObjectUtil; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public enum AppTypeEnum { SCORE("得分类", 0),TEST("测评类", 1); private final String text; private final int value; AppTypeEnum(String text, int value) {this.text = text;this.value = value;} /*** 根据 value 获取枚举** @param value* @return*/public static AppTypeEnum getEnumByValue(Integer value) {if (ObjectUtil.isEmpty(value)) {return null;}for (AppTypeEnum anEnum : AppTypeEnum.values()) {if (anEnum.value == value) {return anEnum;}}return null;} /*** 获取值列表** @return*/public static List<Integer> getValues() {return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());} public int getValue() {return value;} public String getText() {return text;} }
内部类
定义在一个类内部的类,就是内部类。内部类可以分为:成员内部类、静态内部类、局部内部类、匿名内部类。
成员内部类(了解)
定义在一个类的内部,与这个类的成员(属性、方法)平级,并且没有用static修饰的类。
1、访问权限可以是任意的权限,类似于一个类中的成员。
2、实例化的过程,需要先实例化外部类对象,再使用外部类对象进行内部类的实例化
3、内部类编译后,也会生成.class字节码文件。格式:外部类$内部类.class
/*** 成员内部类*/ public class Program {public static void main(String[] args) {// 1. 实例化一个外部类的对象Outer outer = new Outer();outer.name = "outer";// 2. 通过外部类的对象,实例化内部类对象Outer.Inner inner = outer.new Inner();inner.name = "inner";inner.show("hello");} } /*** 外部类*/ class Outer {public String name;public int age1;// 这个类,由于是书写在一个类的内部,因此这个类被称为--内部类// 这个类,由于是写在Outer类中,和类中的属性、方法平级,可以称为是一个类的成员。// 并且,这个类没有使用 static 修饰,这样的类,被称为 -- 成员内部类class Inner {Inner() {System.out.println("实例化了一个Inner的对象");}public String name;public int age2; public void show(int age3) {System.out.println("参数age3: " + age3);System.out.println("内部类属性age2: " + age2);System.out.println("外部类属性age1: " + age1);} public void show(String name) {System.out.println("参数name: " + name);System.out.println("内部类属性name: " + this.name);System.out.println("外部类属性name: " + Outer.this.name);}} }
静态内部类(了解)
定义在一个类的内部,与这个类的成员(属性、方法)平级,并且使用static修饰的类。
1、访问权限可以是任意的权限,类似于一个类中的成员。
2、实例化的过程中,直接使用 new实例化一个外部类 .内部类对象即可。
3、内部类编译后,也会生成.class字节码文件。格式:外部类$内部类 .class
/*** 静态内部类*/ public class Program {public static void main(String[] args) {// 1. 实例化静态内部类对象的时候,不需要借助外部类对象的。// Outer.Inner inner = new Outer.Inner();// 2. 如果已经事先导包了,还可以直接进行实例化Inner inner = new Inner(); } } class Outer {public String name;// 因为这个类,书写与Outer类内,并且是用static修饰的类// 这样的类,被称为 -- 静态内部类static class Inner {Inner() {System.out.println("实例化了一个Inner对象");} public String name; public void show(String name) {System.out.println("参数name: " + name);System.out.println("内部类属性name: " + this.name);System.out.println("外部类属性name,此时无法访问" Outer.this.name);}} }
局部内部类(了解)
定义在某一个代码段中的中。
1、没有访问权限修饰符。
2、在当前方法中,直接实例化即可
3、内部类编译后,也会生成.class字节码文件。格式:外部类$序号内部类 .class
public class Program {public static void main(String[] args) {int a;// 写在某一个局部代码段中(例如:方法中)// 这个类,只能在当前的方法中使用class Inner { }Inner inner = new Inner();test();} static void test() {class Inner { }} }
4.4 匿名内部类(重点)以及数组自定义排序Comparable接口
匿名内部类是Java中一种特殊的内部类,它没有显式的类名,通常用于简化代码和实现一次性使用的类。
public class Teacher implements Comparable<Teacher> {private int age;public Teacher(int age) {this.age = age;} public int getAge() {return age; } @Override public String toString() {return "Teacher{" +"age=" + age +'}'; } @Override public int compareTo(Teacher o) {return this.age - o.age; } }
import java.util.Arrays; import java.util.Comparator; public class TeacherTest {public static void main(String[] args) {//定义一个Teacher类型的数组,存储4个Teacher对象Teacher[] ts = new Teacher[4];for (int i = 0; i < ts.length; i++) {ts[i] = new Teacher((int)(Math.random()*10)+30);}//排序:调用数组工具类的排序方法Arrays.sort(ts);System.out.println(Arrays.toString(ts)); //想要在不改变Teacher源码的情况下,降序/** 匿名内部类:* 1. 写在方法中。* 2. 因为只在该处使用一次,因此没有必要定义出来该类的类结构。* 3. 匿名内部类一般都是向上造型这种多态写法,父类一般都是抽象类或者是接口。* 4. 语法结构:* 父类型名 变量名 = new 父类型名(){* //要重写的方法* };*/Comparator c = new Comparator<Teacher>(){public int compare(Teacher o1, Teacher o2) {return o2.getAge()-o1.getAge();}};Arrays.sort(ts, c);System.out.println(Arrays.toString(ts));} }