文章内容输出来源:拉勾教育大数据开发高薪训练营
一、抽象类
1. 抽象方法:
不能具体实现的方法并且使用abstract关键字修饰,没有方法体。
2. 语法:访问权限 abstract 返回值类型 方法名(形参列表);
3. 抽象类:
不能具体实例化的类并且使用abstract关键字修饰,也就是不能创建对象;
4. 抽象类与抽象方法:
a. 抽象类中可以有成员变量、构造方法、成员方法;
b. 抽象类中可以没有抽象方法,也可以有抽象方法;
c. 拥有抽象方法的类必须是抽象类,因此真正意义上的抽象类应该是具有抽象方法并且使用abstract关键字修饰的类。
注: 当子类继承抽象类,必须重写抽象类中的抽象方法,否则,子类必须声明为抽象类;
public abstract class AbstractTest { private int cnt; public AbstractTest() { } public AbstractTest(int cnt) { setCnt(cnt); } public int getCnt() { return cnt; } public void setCnt(int cnt) { this.cnt = cnt; } // 自定义抽象方法 public abstract void show(); }
二、接口
1. 概念:
所有方法都是抽象方法,关键字interface;类与接口间可以支持多实现,接口与接口间可以支持多继承;
2. 抽象类与接口的区别(注重理解记忆):
• 定义抽象类的关键字是abstract class,而定义接口的关键字是interface。
• 继承抽象类的关键字是extends,而实现接口的关键字是implements。
• 继承抽象类支持单继承,而实现接口支持多实现。
• 抽象类中可以有构造方法,而接口中不可以有构造方法。
• 抽象类中可以有成员变量,而接口中只可以有常量。
• 抽象类中可以有成员方法,而接口中只可以有抽象方法。
• 抽象类中增加方法时子类可以不用重写,而接口中增加方法时实现类需要重写(Java8以前的版本)。
• 从Java8开始增加新特性,接口中允许出现非抽象方法和静态方法,但非抽象方法需要使用default关键字修饰。
• 从Java9开始增加新特性,接口中允许出现私有方法。
public interface InterfaceTest { // 接口中只能有常量,因此public static final可省略 public static final int CNT = 1; // 里面只能有常量 //private void show(){} // 从Java9开始允许接口中出现私有方法 public abstract void show(); // 里面只能有抽象方法(新特性除外) }
三、内部类
-
内部类:出现在另一个类的类体中的类;
-
一个类的类体中可以出现:成员变量、成员方法、构造方法、静态成员、构造块和静态代码块、以及内部类;
-
四种内部类:
四、枚举类
1.枚举的基本概念:
在日常生活中一些些事物的取值只有明确的几个固定值,比如一年四季:春夏秋冬;性别:男女;键盘上的方向键:上下左右;此时描述这些事物的所有值都可以一一列举出来,而这个列举出来的类型就叫做枚举类型。
2.自定义实现枚举:
定义一个方向类:
/** * 编程实现所有方向的枚举,所有的方向:向上、向下、向左、向右 */ public class Direction { private final String desc; // 用于描述方向字符串的成员变量 // 2.声明本类类型的引用指向本类类型的对象 public static final Direction UP = new Direction("向上"); public static final Direction DOWN = new Direction("向下"); public static final Direction LEFT = new Direction("向左"); public static final Direction RIGHT = new Direction("向右"); // 通过构造方法实现成员变量的初始化,更加灵活 // 1.私有化构造方法,此时该构造方法只能在本类的内部使用 private Direction(String desc) { this.desc = desc; } // 通过公有的get方法可以在本类的外部访问该类成员变量的数值 public String getDesc() { return desc; } }
测试:
public class DirectionTest { public static void main(String[] args) { /* // 1.声明Direction类型的引用指向该类型的对象并打印特征 Direction d1 = new Direction("向上"); System.out.println("获取到的字符串是:" + d1.getDesc()); // 向上 Direction d2 = new Direction("向下"); System.out.println("获取到的字符串是:" + d2.getDesc()); // 向下 Direction d3 = new Direction("向左"); System.out.println("获取到的字符串是:" + d3.getDesc()); // 向左 Direction d4 = new Direction("向右"); System.out.println("获取到的字符串是:" + d4.getDesc()); // 向右 System.out.println("-------------------------------------"); Direction d5 = new Direction("向前"); // 向前 与需求不符合 原因是能new出来的对象太多 System.out.println("获取到的字符串是:" + d5.getDesc()); */ // 此时的解决方式是私有化构造方法,但是构造方法私有化后,以上程序报错,并且私有化构造方法 // 后new出来的对象太少,因此将Direction类改造如上2. /* 错误使用 */ //Direction.UP = 2; Error:类型不匹配 //Direction d2 = null; //Direction.UP = d2; Error: final关键字修饰 Direction d1 = Direction.UP; System.out.println("获取到的方向是:" + d1.getDesc()); // 向上 }
3.Java5新增的引用数据类型:enum(枚举)
使用enum实现枚举:
/** * 枚举类型要求所有枚举值必须放在枚举类型的最前面 */ public enum DirectionEnum { // 2.声明本类类型的引用指向本类类型的对象 UP("向上"), DOWN("向下"), LEFT("向左"), RIGHT("向右"); private final String desc; // 用于描述方向字符串的成员变量 // 通过构造方法实现成员变量的初始化,更加灵活 // 1.私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String desc) { this.desc = desc; } // 通过公有的get方法可以在本类的外部访问该类成员变量的数值 public String getDesc() { return desc; } }
测试:
public class DirectionTest { public static void main(String[] args) { // 使用一下Java5开始的枚举类型 DirectionEnum de = DirectionEnum.DOWN; System.out.println("获取到的方向是:" + de.getDesc()); // 向下 } }
4.总结:枚举的定义:
- Java5新增的引用数据类型:enum(枚举) ,使用时要求所有枚举值必须放在枚举类型的最前面;
- 枚举值就是当前类的类型,也就是指向本类的对象,默认使用public static final关键字共同修饰,因此采用枚举类型.的方式调用。
- 枚举类可以自定义构造方法,但是构造方法的修饰符必须是private,默认也是私有的;
5.自定义枚举与enum在switch中的使用:
public class DirectionUseTest { // 自定义枚举实现 public static void test1(String str) { switch (str) { case "向上": System.out.println("抬头望明月!"); break; case "向下": System.out.println("低头思故乡!"); break; case "向左": System.out.println("左牵黄"); break; case "向右": System.out.println("右擎苍"); break; default: System.out.println("没有这样的方向哦!"); } } // enum实现 public static void test2(DirectionEnum de) { switch (de) { case UP: System.out.println("抬头望明月!"); break; case DOWN: System.out.println("低头思故乡!"); break; case LEFT: System.out.println("左牵黄"); break; case RIGHT: System.out.println("右擎苍"); break; default: System.out.println("没有这样的方法哦!"); } } public static void main(String[] args) { DirectionUseTest.test1(Direction.UP.getDesc()); DirectionUseTest.test1("今天是个好日子!"); // 打印没有这样的方向哦! System.out.println("--------------------------------------------"); DirectionUseTest.test2(DirectionEnum.DOWN); //DirectionUseTest.test2("今天是个好日子!"); Error:类型不匹配,减少了出错的可能性 } }
6.Enum类:
7.枚举类实现接口的方式:
定义接口:
public interface DirectionInterface { // 自定义抽象方法 public abstract void show(); }
实现接口:
public enum DirectionEnum implements DirectionInterface { // 2.声明本类类型的引用指向本类类型的对象 // 匿名内部类的语法格式:接口/父类类型 引用变量名 = new 接口/父类类型() { 方法的重写 }; // public static final Direction UP = new Direction("向上") { 方法的重写 }; UP("向上") { @Override public void show() { System.out.println("贪吃蛇向上移动了一下!"); } }, DOWN("向下") { @Override public void show() { System.out.println("贪吃蛇向下移动了一下!"); } }, LEFT("向左") { @Override public void show() { System.out.println("左移了一下!"); } }, RIGHT("向右") { @Override public void show() { System.out.println("右移了一下!"); } }; private final String desc; // 用于描述方向字符串的成员变量 // 通过构造方法实现成员变量的初始化,更加灵活 // 1.私有化构造方法,此时该构造方法只能在本类的内部使用 private DirectionEnum(String desc) { this.desc = desc; } // 通过公有的get方法可以在本类的外部访问该类成员变量的数值 public String getDesc() { return desc; } // 整个枚举类型只重写一次,所有对象调用同一个 /*@Override public void show() { System.out.println("现在可以实现接口中抽象方法的重写了!"); }*/ }