public > protected > 默认(什么都不写) > private
1.关键字:extends
2.格式:子类 extends 父类
3.好处:提高代码复用性
4.成员变量访问特点:
看等号左边是哪个类,就先调用哪个类中的成员,子类没有时找父类
5.成员方法访问特点:
看new的是哪个类,就先调用哪个类中的成员,子类没有找父类
6.super和this:
1.super:代表父类,可以调用父类成员
2.this: 代表子类,可以调用本类成员
3.在构造中,this和super不能一起用,都要求在构造第一行
7.继承特点:
1.继承只能单继承,不能多继承(一个儿子只能有一个亲爹)
2.继承能多层继承
3.一个父类可以拥有多个子类
抽象的定义
1.什么是抽象:说不清,道不明
2.关键字:abstract
3.注意:
a.抽象方法所在的类一定是抽象类
b.抽象类中不一定非得有抽象方法 (为什么)
c.子类继承抽象父类之后,需要重写抽象方法
d.抽象类不能new对象
4.定义
a.抽象类: public abstract class 类名{ ... }
b.抽象方法: 修饰符 abstract 返回值类型 方法名(参数);
比如:public abstract void run();
5.抽象不用看做是一门技术,抽象更偏向于一种代码的设计理念,而且抽象类肯定是作为父类来使用。
抽象的注意事项
1. 抽象类不能直接new对象的,只能创建其非抽象子类的对象。
2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
3. 抽象类中,可以有成员变量。
4. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类
5. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过。除非该子类也是抽象类。
1.关键字:abstract
2.定义:
a.抽象类: public abstract class 类名
b.抽象方法: 修饰符 abstract 返回值类型 方法名(参数)
3.注意:
a.抽象方法所在的类一定是抽象类
b.抽象类中不一定非得有抽象方法
c.子类继承抽象父类之后,需要重写抽象方法
d.抽象类不能new对象
接口中可以定义哪些内容?
1.抽象方法:
public abstract 返回值类型 方法名称(形式参数列表...);
2.常量:
public static final 数据类型 变量名称 = 数据值;
3.默认方法【jdk8开始】:
public default 返回值类型 方法名称(形式参数列表...) {...}
4.静态方法【 jdk8开始】:
public static 返回值类型 方法名称(形式参数列表...) {...}
5.注意:
接口在设计之初,目的只是为了制定一套规则/规范/标准,所以设计之初接口中只能定义抽象方法和常量
必须要掌握接口的定义格式和接口中抽象方法的定义和使用格式【最重要】
1.接口的定义格式
public interface 接口名 {
//…
}
2.抽象方法的定义格式
public abstract 返回值类型 方法名称(形式参数列表...);
3.抽象方法注意事项:
(1)接口中抽象方法,有默认修饰符public abstract,不写也有
(2)抽象类中抽象方法必须写public abstract,不能省略
接口中抽象方法的使用
(1)不能直接创建接口的对象
(2)定义实现类 实现 接口 关键字 implements
格式:
public class 类名 implements 接口A,接口B {
//覆盖重写接口中的所有的抽象方法
}
(3)实现类中覆盖重写接口中的所有的抽象方法
去掉abstract关键字,添加{}
快捷键: ctrl + i
(4)创建实现类对象
(5)使用实现类对象调用方法
1. 默认方法的定义格式
public default 返回值类型 方法名称(形式参数列表...){…}
2. 默认方法的使用:
只能使用实现类对象调用默认方法
3.注意:
(1)接口中的默认方法,不强制要求实现类进行覆盖重写
(2)但是实现类可以根据需求,选择性的覆盖重写接口中的默认方法
(3)如果实现类覆盖重写接口中的默认方法,必须去掉default关键字
1. 静态方法的定义格式
public static 返回值类型 方法名称(形式参数列表...){…}
2. 静态方法的使用:
只能使用接口名称调用接口中的静态方法
3.注意:
(1)接口中的静态方法,属于接口本身,与实现类无关, 不存在覆盖重写
(2)类中的静态方法,属于类本身,与接口无关,与对象无关
(3)类中的静态方法:
类名直接调用 ---推荐使用
对象直接调用 ---不推荐使用
4.总结: 静态的内容要么用接口名称调用,要么用类名称调用
1. 常量的定义格式
public static final 数据类型 = 数据值 ;
2.注意:
(1) 接口中不能定义变量,只能定义常量 (值不可以改变)
(2) 默认修饰符public static final 不写也有
(3) 接口中常量默认值认为是无效的必须显式赋值
(4) 接口中的常量的使用: 接口名称.常量名称
(5) 建议: 常量名称全部使用大写字母,单词之间用_分隔
1.继承的特点
(1)在继承体系中,一个类只能继承一个父类【类的单继承: 亲爹只能有一个】。
(2) 对于接口而言,一个类可以实现多个接口,叫做接口的多实现【类实现接口的多实现: 干爹可以有多个】。
(3) 并且,一个类能继承一个父类,同时实现多个接口。
(4)接口可以多继承
2.接口可以多继承 子接口会拥有父接口中的所有抽象方法
public interface 子接口名 extends 父接口名A,父接口名B,….{
}
2.一个实现类可以同时实现一个或者多个接口->需要重写接口中所有的抽象方法
public class 实现类名 implements 接口名A,接口名B,…. {
}
3.一个实现类可以继承一个父类的同时实现一个或者多个接口->需要重写父类中和接口中所有的抽象方法
public class 类名 extends 父类名 implements接口名A,接口名B,…. {
}
1. 接口关键字:interface
2. 实现关键字:implements
3. 接口能不能直接new对象?不能
4. 抽象关键字:abstract
5. 使用:通过实现类去实现
6. 接口特点:
(1)接口能继承
(2)一个实现类可以同时实现一个或者多个接口
(3)一个实现类可以继承一个父类的同时实现一个或者多个接口
多态概述
同一个对象,在不同时刻表现出来的不同形态
举例:猫
我们可以说猫是猫:猫 cat = new 猫();
我们也可以说猫是动物:动物 animal = new 猫();
这里猫在不同的时刻表现出来了不同的形态,这就是多态
多态的前提和体现
⚫ 有继承/实现关系
⚫ 有方法重写
⚫ 有父类引用指向子类对象
多态中成员访问特点
⚫ 构造方法:同继承一样,子类会通过 super 访问父类构造方法
⚫ 成员变量:看等号左边是谁,先调用谁的成员变量,子类没有,找父类
⚫ 成员方法:看new的是谁,先调用谁的成员方法,子类没有,找父类
为什么成员变量和成员方法的访问不一样呢?
⚫ 因为成员方法有重写,而成员变量没有
多态中的转型
⚫ 向上转型
从子到父
父类引用指向子类对象
⚫ 向下转型
从父到子
父类引用转为子类对象
1.多态前提:
(1)必须有子父类继承或者接口实现关系
(2)必须有方法重写
(3)父类引用执行子类对象
2.多态中能直接调用特有方法吗?不能
3.转型:
(1)向上转型
(2)向下转型->能调用子类特有方法
4.类型判断:instanceof
5.多态好处:让代码更灵活
多态中的转型存在的风险
⚫ 概述:如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现
ClassCastException
避免强转出现的问题
⚫ 关键字 instanceof
⚫ 使用格式:
变量名 instanceof 类型
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
final关键字_概述和特点
学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们
能不能随意的继承API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的
情况,Java提供了final 关键字,用于修饰不可改变内容。
1.概述:final代表不可改变。可以用于修饰类、方法和变量。
2.特点:
(1)类:被修饰的类,不能被继承。
(2)方法:被修饰的方法,不能被重写。
(3)变量:被修饰的变量,不能被重新赋值。
被final修饰的类不能被继承
1.格式:
修饰符 final 返回值类型 方法名(参数){
方法体
return结果数据;
}
2.特点:
被final修饰的方法不能被重写
3.注意:
final和abstract不能一起修饰方法
1.格式:
修饰符 返回值类型 方法名(final 基本数据类型 参数名称1){
final 基本数据类型 变量名称2;
final 基本数据类型 变量名称3 = 数据值;
return 结果数据;
}
2.特点:
(1)方法参数上final修饰的基本类型局部变量,方法内部不能进行再次赋值/修改值
(2)方法内部final修饰的基本类型局部变量,不能进行第二次赋值
final关键字修饰引用类型局部变量
1.格式:
修饰符 返回值类型 方法名(final引用数据类型 参数名称1){
final 引用数据类型 变量名称2;
final 引用数据类型 变量名称3 = 对象;
return 结果数据;
}
2.特点:
(1)final修饰的引用变量,地址不能改变,即不能再指向其它对象
(2)但是通过引用变量是可以修改内容(属性)的
final关键字修饰成员变量
1.格式:
public class 类名{
final 基本数据类型 变量名称1;
final 基本数据类型 变量名称2 = 数据值;
final 引用数据类型 变量名称3;
final 引用数据类型 变量名称4 = 对象;
}
2.特点:
(1) 定义未赋值:
a. 所有构造方法中,必须完成对final修饰的变量的赋值
b. 所有成员方法中,不能修改final修饰的变量的值
(2) 定义并赋值:
a. 所有构造方法/成员方法中,不能修改final修饰的变量的值
1.final修饰类
不能被继承
2.final修饰方法
(1)不能被重写
(2)abstract合起来使用
3.final修饰基本类型局部变量
不能被二次赋值
4.final修饰引用类型局部变量
(1)地址值不能改变
(2)内容(属性)可以改变
5.final修饰成员变量
(1)不能被二次赋值
(2)需要手动赋值
1.多个new对象中的教室名称字符串重复,浪费内存空间
2.如果修改教室名称需要修改多次
如何解决这些问题?
1.发现教室名称被所有对象共享使用,与每个对象无关
2.只需要一份,所以需要定义成静态的,使用static修饰
static关键字_概述和特点
被static修饰的成员->属于类成员->不属于对象
被static修饰的成员会跟着类的加载而加载
由于对象必须等着类加载到内存中,才能够new,而static随着类走的,所以static的成员优先于对象存在
只要是根据static所在类创建出来的对象,都可以共享这个static修饰的成员
static关键字_概述和特点
被static修饰的成员->属于类成员->不属于对象
被static修饰的成员会跟着类的加载而加载
由于对象必须等着类加载到内存中,才能够new,而static随着类走的,所以static的成员优先于对象存在
只要是根据static所在类创建出来的对象,都可以共享这个static修饰的成员
static关键字_定义和使用格式
1.static修饰成员方法(类方法: 依赖于类,与对象无关):
public static 返回值类型 方法名称(参数列表...) {...}
2.使用格式:
类名.静态成员方法名称(...) 推荐使用
对象名.静态成员方法名称(...) 不推荐使用
static关键字_注意事项
静态的内容只能使用静态的内容,不能使用非静态的内容
1.解释:
(1)静态当中不能使用非静态
(2)静态的内容,是最先被加载到内存方法区中的静态区中,并完成初始化,
但是此时没有对象(非静态的内容存在于对象中)既然没有对象,
就不能使用非静态的内容
(3)静态(先人),非静态(后人)
2.静态的注意事项
(1)静态方法可以直接访问静态变量和静态方法。
(2)静态方法不能直接访问非静态成员变量或成员方法。
(3)反之,成员方法可以直接访问静态变量或静态方法。
(4)静态方法中,不能使用this关键字。
static关键字_静态代码
1.静态代码块格式:
使用{}括起来的叫做代码块,加上static叫做静态代码
static {...}
2.特点:
(1)假如只创建对象,静态代码块会优先于构造方法执行,唯一执行一次
(2)静态代码块,随着类的加载而加载并唯一执行一次
(3)完成静态成员变量的赋值
(4)静态代码块,仍然属于静态内容,内部不能使用非静态
(5)完成项目的初始化工作
1. 静态的能直接访问非静态吗?
不能,因为静态的属于类,非静态的属于对象,所以当静态
的成员加载到内存是,非静态成员还没有产生
2.非静态的能直接访问静态成员吗?
能,因为静态的属于类,非静态的属于对象,所以当非静态
成员加载到内存时,静态成员已经存在了
1.static的成员特点:
a. 被static修饰的成员->属于类成员->不属于对象
b. 被static修饰的成员会跟着类的加载而加载
c. 由于对象必须等着类加载到内存中,才能够new,而static随着类走的
d. 所以,static的成员优先于对象存在
e. 只要是根据static所在类创建出来的对象,都可以共享这个static修饰
的成员
2.static的成员访问方式:
类名直接调用
(1)成员内部类: 定义在外部类的成员位置(和成员变量/成员方法 地位相同)
可以使用: public/private/static进行修饰
(2)局部内部类: 定义在外部类的方法内部,该内部类出了方法就没有用了
内部类_成员内部定义和使用
1.成员内部类(和成员变量/成员方法 处于同一位置)定义格式:
public class 外部类名 {//外部类
//外部类成员变量/成员方法/构造方法
public class 内部类名 {//成员内部类
//内部类成员变量/成员方法/构造方法
}
}
2.成员内部类的使用格式:
(1)外部类要访问内部类的成员,必须要建立内部类的对象。
外部类.内部类 对象名 = 外部类对象.new 内部类();
外部类.内部类 对象名 = new 外部类().new 内部类();
简单来讲: 外.内 对象名 = new 外().new 内();
(2)内部类可以直接访问外部类的成员,包括私有成员。
3.注意:
(1)内部类也是类,编译后也有对应的class文件: 外部类名$内部类名.class
(2)内部类可以使用public修饰,也可以使用private修饰,还可以使用static修饰
(3)可以在方法内部定义内部类(局部内部类),出了方法就失效了(必须在方法内部创建内部类的对象并使用)
内部类_匿名内部类
1.概念:
是内部类的简化写法。它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类/实现类对象。
2.作用:
(1)是一种创建接口实现类对象的快捷方式
把创建实现类,覆盖重写抽象方法,创建实现类对象,实现类对象调用方法这四步合成一步完成
(2)是一种创建抽象父类的子类对象的快捷方式
把创建子类,覆盖重写抽象方法,创建子类对象,子类对象调用方法这四步合成一步完成
3.匿名内部类对象创建格式:
new 抽象父类/接口(); //错误: 不能直接new抽象父类/接口的对象
new 抽象父类/接口() {
覆盖重写所有的抽象方法;
}
4.注意:
(1)上面只是创建了一个抽象父类的子类对象或者接口的实现类对象
(2)该对象目前没有名字
(3)该对象所属的类是没有名字的(注意:其实有名字(外部类名$1.class),
只是该名字不是我们起的,是JVM帮助我们起的)
1.这里创建的是FlyAble接口的实现类对象
2.new的后面没有写具体的类名,写的是接口名称,而且在接口名称后面跟了{}
3.在{}中覆盖重写了抽象方法,JVM在看到我们的这种书写形式后,
会根据接口帮助我们创建一个实现类,只是该实现类的名字我们看不见,
而且该实现类也是有构造方法的,我们也不能直接调用该构造方法,
然后因为前面有new关键字,JVM再帮助我们创建该接口的实现类对象
(JVM来调用构造方法)
1.成员内部类访问格式:
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
2.匿名内部类定义格式:
new 抽象父类/接口(){
重写方法()
}.重写方法名()