第一小节 抽象类
1.抽象类格式和概念
//有抽象方法的类,一定是抽象类
abstract class Demo1{
//被`abstract`修饰的都是抽象方法
public abstract void speak()
}
//抽象类不一定有抽象方法
abstract class Demo2{
//普通方法
public void speak()
}
3.代码演示
//定义形状
public abstract class Shape {
//抽象类中的普通成员变量
private double chang;
private double kuan;
//抽象类有可以有构造方法
public Shape() {}
public Shape(double chang, double kuan) {
this.chang = chang;
this.kuan = kuan;
}
//抽象类中可以有普通方法
public void method1(){
System.out.println("1");
}
//抽象方法 有抽象方法的类一定是抽象类
public abstract void method2();
}
//继承抽象类一定要实现抽象方法,如果不实现,这个类还是抽象类, 编译的时候会有提示的
abstract class Test2 extends Shape{
}
//继承
class Test extends Shape{
//继承抽象类一定要实现抽象方法
@Override
public void method2() {
}
public static void main(String[] args) {
// 抽象类不能实例化
// Shape b = new Shape();
Test test = new Test();
}
}
3.抽象类的作用
用来描述一种数据类型应该具备的基本特征(成员变量)和行为(方法),如何实现这些方法由子类通过方法重写完成。
4.抽象类的特点
- 1.抽象类和抽象方法都需要用关键字:abstract修饰
- 2.抽象类不能直接创建对象,因为调用抽象方法毫无意义,为什么没有意义呢,
因为抽象方法 没有代码块,它只是定义了方法
- 3.子类继承抽象类之后,要实现抽象类中的所有抽象方法,否则要将子类也定义为抽象类
5.抽象类常见的几个问题描述
- 5.1抽象类不能创建对象,抽象类中是有构造方法,子类可以通过super调用父类的构造方法,给父类的成员变量赋值,赋值完之后子类就可以使用父类继承的成员变量。
- 5.2抽象类一定是个父类,因为抽象类不能创建对象。
- 5.3抽象类中可以不定义抽象方法
- 5.4抽象类中可以定义普通方法(有方法体的方法)
- 5.5抽象关键字不能和private关键字共存。因为private修饰的方法不能被子类重写,而抽象方法又要求子类要重写。
第二小节 接口
1.接口的概念
- 1.1接口也是一种数据类型。它是比抽象类更加抽象的’类’
- 1.2接口是功能(方法)的集合,如何实现这些功能由实现类(子类)通过方法重写实现。
- 1.3接口中的方法都是抽象方法。
2.接口的定义和使用格式
//定义格式
interface 接口名{
// 抽象方法
}
//使用格式
class 类名 implements 接口名 {
// 重写抽象方法
}
3.示例代码
//抽象类(父类)
public abstract class Animal {
// 动物都会叫 但是每个动物叫声都不一样 所有定义一个抽象方法
public abstract void jiao();
}
//定义个子类dog继承动物类
public class Dog extends Animal{
@Override
public void jiao() {
System.out.println("汪汪汪");
}
}
//定义格式
interface 接口名{
// 抽象方法
}
//写一个接口给actdog 因为不是每个狗都会表演
public interface jiekou {
// 抽象方法
public abstract void actDog();
}
//写一个会表演的狗继承狗类 并且使用接口
public class ActDog extends Dog implements jiekou {
@Override
public void actDog() {
System.out.println("会胸口碎大石");
}
}
//写一个测试类进行测试
public class Demo2 {
public static void main(String[] args) {
ActDog dog = new ActDog();
dog.jiao();
dog.actDog();
Dog dog1 = new Dog();
dog1.jiao();
// 因为不是每一个狗都会表演 所以dog1不能调用act方法
// dog1.actDog();
}
}
4. 接口的特点和注意事项
4.1 接口特点
在JDK1.8之前,接口中所有的方法都是抽象方法,在JDK1.8后,接口中的方法可以有默认实现(有方法体)
public interface jiekou {
// 抽象方法
public abstract void actDog();
//默认方法
public static void eat() {
System.out.println("会吃东西");
};
}
接口没有构造方法
接口中定义成员变量是常量。
接口不能创建对象,原理跟抽象方法一样,因为没有代码块(也是没有具体的实现方法)
接口可以继承接口,而且可以多继承。
接口中的抽象方法有默认的修饰符:
public abstract
接口中的常量有默认的修饰符:
public static final
4.2 注意事项
Java支持类在继承一个类的同时实现1个或多个接口。
接口与父类的功能可以重复,均代表要具备某种功能,并不冲突。
当一个类实现了接口时,必须实现其所有的方法,否则这个类必须定义为一个抽象类。
4.3 接口和抽象类的应用
/**
* 适配器模式
*/
interface MyInterface{
//比如定义了n多个方法
void method();
void method2();
void method3();
void method4();
void method5();
void method6();
}
//class Demo implements MyInterface {
//这样我就要实现很多个方法了,但是我就只是实现第一个方法
//}
abstract class Adapter implements MyInterface{
@Override
public void method() {
}
@Override
public void method2() {
}
@Override
public void method3() {
}
@Override
public void method4() {
}
@Override
public void method5() {
}
@Override
public void method6() {
}
}
class Demo extends Adapter{
@Override
public void method() {
//现在就只需要实现一个方法了
}
}
5. 接口和抽象类的区别
5.1.相同点
- 都不能创建对象
- 子类或实现类都必须重写抽象方法
5.2.不同点
- 接口可以接口且可以多继承, 类只能单继承,不能多继承。
- 接口中的成员变量是常量了,抽象类可以有普通成员变量,也可以有常量。
- 抽象类中可以有构造方法(因为抽象类不能new 出来,所以抽象类的构造方法,只有在子类继承的时候才可以调用抽象类的构造方法),接口中没有构造方法
- 接口中的抽象方法有默认的修饰符:public abstract,抽象类的抽象方法没有默认的修饰符。
- 接口中的常量有默认的修饰符:public static final,抽象类的成员变量没有默认修饰符。
- 抽象类中可以有非抽象方法,接口在JDK.18(包括1.8)之后才可以有非抽象方法。
第三小节 多态
1.多态的概述
多态是java面向对象的第三大特征
,同一种事物表现出来的多种形态则称为多态。
比如:张三 ==> 学生 张三 ==> 路人甲 张三 ==> 儿子
比如:狗 ==> 动物 狗 ==> 宠物
2.多态的注意细节,例子,和分析,重点
class Animal{
int num = 10;
static int age = 20;
public void eat(){
System.out.println("动物吃饭");
}
public static void sleep(){
System.out.println("动物睡觉");
}
public void run(){
System.out.println("动物跑步");
}
}
//多态三要素之一:Cat类继承了Animal类
class Cat extends Animal{
int num = 80;
static int age =90;
String name = "tomcat";
//多态三要素之二:子类要重写父类的方法,非静态方法
public void eat(){
System.out.println("猫吃饭");
}
//多态三要素之二:子类要重写父类的方法,静态方法
public static void sleep(){
System.out.println("猫睡觉");
}
public void catchMouse(){
System.out.println("猫在抓老鼠");
}
}
class Demo{
public static void main(String[] args) {
//多态三要素之三:父类数据类型的引用指向子类对象
Animal am = new Cat(); //多态的格式,也可以只想接口
am.eat(); //猫吃饭
am.sleep(); //动物在睡觉
am.run(); //动物在奔跑
System.out.println(am.num); //10
System.out.println(am.age); //20
//总结:
//成员变量:编译看左边(父类),运行看左边(父类) --->am.num 和 am.age
//静态方法:编译看左边(父类),运行看左边(父类) --->sleep() 静态和类相关,算不上重写
//成员方法:编译看左边(父类),运行看右边(子类) --->eat()
//多态的好处缺点,不能访问子类特有的成员:成员变量和成员方法。
//am.catchMouse(); //编译报错
//System.out.println(am.name); //编译报错
//如果一定要执行am.name
Cat cat = (Cat)am;
System.out.println(cat.name); //tomcat
}
}
大家都知道花木兰替父从军的例子,花木兰替父亲花弧从军。那么这时候花木兰是子类,花弧是父类。花弧有自己的成员属性年龄,姓名,性别。花木兰也有这些属性,但是很明显二者的属性完全不一样。花弧有自己的非静态成员方法‘骑马杀敌’,同样花木兰也遗传了父亲一样的方法‘骑马杀敌’。花弧还有一个静态方法‘自我介绍’,每个人都可以问花弧姓甚名谁。同时花木兰还有一个自己特有的非静态成员方法‘涂脂抹粉’。但是,现在花木兰替父从军,女扮男装。这时候相当于父类的引用(花弧这个名字)指向了子类对象(花木兰这个人),那么在其他类(其他的人)中访问子类对象(花木兰这个人)的成员属性(姓名,年龄,性别)时,其实看到的都是花木兰她父亲的名字(花弧)、年龄(60岁)、性别(男)。当访问子类对象(花木兰这个人)的非静态成员方法(骑马打仗)时,其实都是看到花木兰自己运用十八般武艺在骑马打仗。当访问花木兰的静态方法时(自我介绍),花木兰自己都是用她父亲的名字信息在向别人作自我介绍。并且这时候花木兰不能使用自己特有的成员方法‘涂脂抹粉’。
-----多态中的向上转型
那么终于一将功成万骨枯,打仗旗开得胜了,花木兰告别了战争生活。有一天,遇到了自己心爱的男人,这时候爱情的力量将父类对象的引用(花弧这个名字)强制转换为子类对象本来的引用(花木兰这个名字),那么花木兰又从新成为了她自己,这时候她完全是她自己了。名字是花木兰,年龄是28,性别是女,打仗依然那样生猛女汉子,自我介绍则堂堂正正地告诉别人我叫花木兰。OMG!终于,终于可以使用自己特有的成员方法‘涂脂抹粉’了。从此,花木兰完全回到了替父从军前的那个花木兰了。并且和自己心爱的男人幸福的过完了一生。
-----多态中的向下转型
3.多态的使用场景
//作为形式参数,多态用于形式参数类型的时候可以接收更多类型的对象
public class Demo2 {
public static void main(String[] args) {
Animal dog = new Dog();
feedAnimal(dog);
Animal p = new pig();
feedAnimal(p);
Animal cat = new cat();
feedAnimal(cat);
}
public static void feedAnimal(Animal a) { //Animal a = new Dog();
a.eat();
}
}
//作为返回值类型,多态用于返回值类型的时候可以返回更多类型的对象。
public static void main(String[] args) {
Animal a = productAnimal(1);
a.eat();
Animal d4 = productAnimal(2);
d4.eat();
d4.jiao();
Animal d41 = productAnimal(55);
d41.eat();
d41.jiao();
}
//生成动物 type = 1 表示生产狗 type = 2 表示生产猫
public static Animal productAnimal(int type) {
if (type == 1) {
return new Dog();
} else if (type == 2) {
return new cat();
}
return new pig();
}
4.多态的转型
- 向上转型
//当把子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
使用格式 父类类型 变量名 = new 子类类型();
如:Person p = new Student();
向下转型(参考基本数据类的强制转换)
子类类型 变量名 = (子类类型) 父类类型的变量; 如:Student stu = (Student) p; //变量p 实际上指向Student对象
5. instanceof关键字
5.1.instanceof的作用
用来判断某个对象是否属于某种数据类型。如学生的对象属于学生类,学生的对象也属于人类。
5.2.使用格式
boolean b = 对象名 instanceof 类名或接口名;
5.3. 注意事项
如果instanceof右边是类名,则要求左边的对象名和类名必须存在子父类关系。