目录
1.抽象类
通俗概念:父类知道子类一定要完成某个功能,但是每个子类完成的情况不一样。那么父类的该功能就可以定义为抽象方法,子类重写调用子类自己的方法。
什么是抽象方法?->每天方法体,只有方法签名,用abstract修饰
注意:
1.拥有抽象方法的类必须定义为抽象类,抽象类必须用abstract修饰。
2.抽象方法:没有方法体,只有方法签名,必须用abtract修饰。
3.抽象类不能实例化
1.1抽象类的作用
抽象类的作用就是为了被子类继承,约束子类重写方法
一个类继承了抽象类,那么这个类就必须重写完抽象类中的所有抽象方法。
例如
public class AbstractDemo {
public static void main(String[] args) {
Teacher boZai = new Teacher();
boZai.work();
Manager boNiu=new Manager();
boNiu.work();
}
}
//需求:一家公司要开发员工管理系统(讲师、班主任)
abstract class Employee{
//子类都要完成工作这个功能,但是每个子类工作内容不一样,就定义成抽象方法
public abstract void work();
}
class Teacher extends Employee{
@Override
public void work() {
System.out.println("讲师在讲课");
}
}
class Manager extends Employee{
@Override
public void work() {
System.out.println("班主任提醒学生上课");
}
}
1.2抽象类的特征
抽象类的特征: 有得有失
有得:抽象类拥有抽象方法的能力。
有失:抽象类没有创建对象的能力。
面试题:
抽象类是否有构造器,抽象类是否可以创建对象???
答:抽象类作为类一定有构造器,而且抽象类必须有构造器
提供给子类创建对象调用父类构造器使用,但是不可以创建对象,因为抽象类如果可以实例化,那么抽象方法调用就没有任何意义,,因为没有方法体。
1.3抽象类的意义
抽象类存在的意义:1.抽象类就是为了被子类继承,否则毫无意义。
2.抽象类体现的是模板思想,部分实现,部分 抽象,
如以下的抽象类设计模式。
public class AbstractDemo {
public static void main(String[] args) {
Student student = new Student();
student.write();
//优先调子类的方法,因为用的子类对象。
}
}
class Student extends Template{
@Override
public String writeMain() {
return "\t\t我父亲很好,而且...............";
}
}
//设计一个模板类。
abstract class Template{
private String title="\t\t\t\t\t\t<<我的父亲>>";
private String one ="\t\t请介绍一下你的爸爸,说说你的父亲有多好,说说多厉害。";
private String last="\t\t我的父亲很厉害,有这样的父亲很荣幸。";
//2.写作文的功能!
public void write(){
System.out.println(title);
System.out.println(one);
//写正文部分,模板不确定,交给子类来写
System.out.println(writeMain());
System.out.println(last);
}
//定义抽象方法描述正文;
public abstract String writeMain();
}
1.4抽象类的注意事项
- 抽象类不能创建对象,如果创建,编译无法通过
- 抽象类一定而且必须器,是提供给子类创建对象时候初始化父类成员使用。
- 抽象类中,不一定包括抽象方法,但是有抽象方法的类必须是抽象类。
- 抽象类的子类,必须重写抽象类的所有方法,否则子类也是抽象类
- 抽象类存在的意义是为了被子类继承,抽象类体现了个模板思想。
2.接口
什么是接口?
接口体现的是规范思想,实现接口的子类必须重写完全部抽象方法。
接口是更加彻底的抽象,在JDK1.8之前接口只能是抽象方法和常量。
接口成分:
在JDK1.8之前,接口成分只能有抽象方法和常量。
public interface InterfaceDemo {
//1.抽象方法
//接口中的抽象方法可以省略public abstract不写,默认会加上
public abstract void run();
void eat();
//2.常量:变量值只有一个,而且在程序运行过程中不可以更改!
//常量一般修饰符是public static final
//常量的变量名称建议全部大写,多个单词用_连接
//接口中常量是可以省略 public static final不写的
public static final String SCHOOL_NAME="黑马";
}
2.1接口的使用
子类和父类与接口与实现类的对应理解:
父类 子类 继承
接口 实现类 实现
类与类是继承关系
接口与类是实现关系
关键字:implements
注意:
一个类实现接口,那么这个类就是实现类,接口可以多实现,一个类实现接口,必须实现完接口的所有方法,否则要为抽象类。
一个类实现多个接口,必须重写完全部接口中的抽象方法,否则这个类要定义成抽象类,否则报错!
案例:
package cn.airycloud._09接口的多实现;
/*
*
* 目标:接口的多实现。
*
* 类与类是单继承关系。
* 类与接口是多实现关系。
*
*小结:
* 一个类实现多个接口,必须重写完全部接口中的抽象方法,否则这个类要定义成抽象类,否则报错!
* */
public class InterfaceDemo {
public static void main(String[] args) {
//创建实现类对象调用重写的方法执行!
BasketBall basketBall = new BasketBall();
basketBall.rule();
basketBall.run();
basketBall.competition();
}
}
class BasketBall implements SportMan,Law{
@Override
public void run() {
}
@Override
public void competition() {
}
@Override
public void rule() {
}
}
interface SportMan{
void run();
void competition();
}
interface Law{
void rule();
}
2.2接口与接口的多继承关系
类与类是单继承关系,一个类只能继承一个直接父类。
类与接口是多实现关系:一个类可以同时实现多个接口。
接口与接口是多继承关系:一个接口可以同时继承多个接口。
public class InterfaceDemo {
}
interface PingPongMan extends SportMan, Law, Go{
//接口与接口之间可以多继承
}
interface SportMan{
void run();
void competition();
}
interface Law{
void rule();
}
interface Go{
void abroad();
}
2.3接口扩展
JDK1.8之后接口新增了三个方法。
JDK1.8之后接口不在纯洁。
(1)默认方法:其实就是我们之前写的实例方法。
--必须用default修饰。
--默认会加public修饰。
--只能用接口的实现类的对象调用。
(2)静态方法:
-- 可以直接加static修饰
-- 默认会加public修饰
-- 接口的静态方法只能用接口名称调用
(3)私有方法(其实从JDK1.9开始才支持):
-- 其实就是私有的实例方法,必须加private修饰。
public class InterfaceDemo {
public static void main(String[] args) {
PingPongMan zjk=new PingPongMan();
// zjk.run();
SportMan.inAddr();
}
}
//实现类
class PingPongMan implements SportMan{
}
interface SportMan{
//1.默认方法:其实也就是我们之前写的实例方法
//只能用接口的实现类对象调用
default void run(){
// go();
System.out.println("跑的贼快~~~");
}
//2.只能用接口的实现类名调用
static void inAddr(){
System.out.println("我们在吉山区~~~~");
}
//3.私有方法:只能在本接口中被访问
//私有方法通常是给私有方法或者给默认方法调用!
// private void go(){
// System.out.println("");
// }
}
注意:
1.如果实现了多个接口,多个接口存在同名的静态方法并不冲突。
2.重点:当一个类,既继承了一个父类,又实现了 若干接口的时候,父类的成员方法与接口的默认方法重名,子类就近原则执行父类的成员方法。
3.当一个类实现了多个接口时,多个接口中存在同名的默认方法。实现类必须重写这个方法。
4.接口中,没有构造器,不能创建对象、
接口是更加彻底的抽象,连构造器都没有,自然不能创建。
3.代码块
代码块是类的五大成分之一。
按照有无static修饰,分为静态代码块和实例代码块:
静态代码块:
--必须用static修饰,属于类,会和类一起加载,而且自动触发一次。
--静态代码块可以用于在执行类的方法之前进行静态资源初始化操作。
实例代码块:
--必须无static修饰,属于对象,会与类的每个对象一起加载,对象有几个就执行几次。
--可以初始化实例资源。
4.final关键词讲解
final的字面含义就是最后的意思,联想记忆它的特征:
1.final修饰类,类不能被继承。
2.final修饰方法,方法不能被重写。
3.final修饰变量,变量有且仅有被赋值一次。
注意:abstract和final是世仇关系,因为abstract就是为了被重写,被继承,但是final....是吧。
5.单例设计模式
什么是单例?永远只存在一个对象,不能创建多个对象。
为什么要用单例?(单例共8种)
开发中有很多类的对象我们只需要一个。例如虚拟机对象。任务管理器对象。
对象越多,约占内存。有时候啊对象只需要一个来实现业务,单例可以节约内存。
这里我们以懒汉式和饿汉式单例模式为例:
饿汉式:也就是提前把对象在内部定义好,注意,需要先私有化构造器,这样就不可以在外部进行实例化了,然后定义一个static修饰的对象在内部,先new出一个对象,注意static修饰是为了让这个对象属于类,可以直接调用,然后定义一个getInstance()方法进行访问这个对象。
饿汉式:
public class SingleInstanceDemo01 {
public static void main(String[] args) {
SingleInstance01 singleInstance01=SingleInstance01.getInstance();
SingleInstance01 singleInstance011=SingleInstance01.getInstance();
System.out.println(singleInstance011 == singleInstance01);
}
}
//饿汉单例
class SingleInstance01{
//2.定义一个静态成员变量用于存储出一个对象,(饿汉单例在返回对象的时候,对象要提前做好,所以这里提前new一个。
public static SingleInstance01 ins =new SingleInstance01();
//私有化,对外安全了
private SingleInstance01(){
}
//提供一个方法返回单例对象
public static SingleInstance01 getInstance(){
return ins;
}
}
懒汉式:懒汉式突出一个懒字,也就是当我们需要的时候才去new对象,这样是按需分配的思想,比饿汉式更省内存,具体如下
public class SingleInstanceDemo02 {
public static void main(String[] args) {
SingleInstance02 a = SingleInstance02.getInstance();
SingleInstance02 instance = SingleInstance02.getInstance();
System.out.println(a==instance);
}
}
class SingleInstance02{
public static SingleInstance02 ins;
private SingleInstance02(){
}
//通过一个方法返回一个对象,不存在对象才创建一个返回
public static SingleInstance02 getInstance(){
if(ins==null){
ins =new SingleInstance02();
}
return ins;
}
}
6.枚举类
枚举类作用:
枚举是为了做信息标记和信息分类。可以提高代码的可读性和约束代码按照指定的方式去写,在团队开发中在一些场景中定义枚举很友好。
* 枚举类的特点:
* 1.枚举类是final修饰的,不能被继承
* 2.枚举类默认继承了枚举类型:Java.lang.Enum
* 3.枚举类的第一行罗列的是枚举类的对象。而且是常量存储
* 4.所以枚举类的第一行写的都是常量名称,默认存储了枚举对象。
* 5.枚举类相当是多例模式。
* 6.枚举类的构造器是私有的。
枚举类的标记实质从0开始,可以用ordinal()方法获取。
public class EnumDemo01 {
public static void main(String[] args) {
Sex s1 = Sex.BOY;
System.out.println(s1);
System.out.println(s1.ordinal());
}
}
enum Sex{
BOY,GIRL;
}