Java学习 第十一天

第一章 Java语言的三个特点

在这里插入图片描述

第二章 抽象方法和抽象类

2.1 概述:

  当一个类应该有一个方法来实现某个功能,但是却不知道如何实现的时候,可以定义一个抽象方法,以此来表示,该类具有此功能,只是不知道该如何实现吗,而这个类叫做抽象类。而它的子类一定也会继承该抽象方法,代表它的子类也具有该功能。
生活联想: 想一下动物作为抽象类,它一定要吃东西,但是不知道吃什么,吃就是抽象方法

  此时,它的子类要么重写父类所有的抽象方法,使其具体化(写清楚,这个子类该如何实现该功能),变为普通类。要么,它的子类不重写父类所有的抽象方法,则该子类会继承抽象父类中那些没有被重写了的抽象方法,但是该类也不知道该如何实现,而抽象方法所在的类必须是抽象类所以,所以这个子类也是抽象类
生活联想: 想一下动物的子类,有脊椎动物和无脊椎动物、这两个子类也都要吃东西,但是同样无法具体到具体吃什么,所以这两个子类虽然继承了“吃”这个抽象方法,但是无法重写,使其具体,因此,这两个也是抽象类。
想一下动物的子类,猫。猫这个子类很显然,我们知道它具体吃什么,老鼠或者鱼干等等,因此我们可以把它继承来的“吃”这个抽象方法给具体化,从而使其变成一个普通类。

2.2 抽象方法的定义格式

抽象方法定义格式: 修饰符 abstract 返回值类型 方法名称(参数列表);
注意: 后面所学接口当中的抽象方法在定义时候,可以省略修饰符、abstract,但是抽象类当中定义抽象方法时候则不能省略

抽象类定义格式: 抽象方法所在的类,必须是抽象类才行,在class之前写上abstract即可

注意: 抽象方法所在的类一定是抽象类,但是抽象类不一定包括抽象方法

比如:
定义一个父类动物,动物一定要吃东西,但是具体吃什么要根据每种动物来确定,因此,动物这个类当中一定有一个方法叫“吃”,但是没法写方法体。此时,动物类的“吃”这个方法就是抽象方法。

public abstract class Animal{
	//	这是一个抽象方法
	public abstract void eat();

	//	这是一个普通方法
	public void normalMethod(){

	}
}

2.2 抽象方法和抽象类的使用

如何使用抽象类和抽象方法:
1.不能直接创建new抽象类对象。
哪里有一个对象是动物的?即使创建了动物的实例对象,这也是没有意义的。不难理解,方法都是抽象的,理应抽象类应该没有具体对象

2.必须用一个子类来继承抽象父类。(注意前面所讲,子类就是一个父类)

3.子类必须覆盖重写抽象父类当中所有的抽象方法
覆盖重写(实现): 子类去掉抽象方法的abstract关键字,然后补上方法体大括号

4.创建子类对象进行使用

//	定义抽象类Animal作为父类
public abstract class Animal{
	//	这是一个抽象方法,代表吃东西,但是具体吃什么(大括号内的内容,也就是方法体)不确定。
	public abstract void eat();

	//	这是普通的成员方法。
	public void normalMethod(){
}

//	定义子类Cat继承抽象父类Animal
public class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

//	定义测试类
public class DemoMain {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();
    }
}

2.3 抽象方法和抽象类的注意事项

  • 1.抽象类不能创建对象,如果创建,编译无法通过而报错,只能创建其非抽象子类的对象
    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义
  • 2.抽象类中,可以有构造方法,是供子类创建对象时候,初始化父类成员使用的。
    理解:抽象父类是无法通过new来实现其构造方法的,然而子类的构造方法当中有默认的super(),会访问父类的构造方法。

代码如下:


//	定义抽象父类
public abstract Fu{
   //	定义构造方法
   public Fu(){
   	System.out.println("抽象父类构造方法执行!");
   }

   //	定义抽象方法
   public abstract void eat();
}

//	定义普通子类
public class Zi{
   //	定义构造方法
   public Zi{
   	//	调用父类构造方法(构造方法一定是不能被继承的,只能被子类调用)
   	super();
   	System.out.println("子类构造方法执行!");
   }

   //	重写抽象方法
   @Override
   public void eat(){
   	System.out.println("吃饭饭");
   }
}

  • 3.抽象类当中,不一定包含抽象方法,但是抽象方法所在的类必须是抽象类
    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计

  • 4.抽象类的子类,必须要覆盖重写抽象父类当中所有的抽象方法,否则,编译无法通过而报错,除非该类也是抽象类。
    理解:假设不重写所有的抽象法方法,则类当中可能包含抽象方法,那么创建对象以后,调用抽象的方法,则没有意义。

第三章 接口

3.1 接口概述:

简单理解,接口就是一种公共的规范标准,只要符合规范标准,大家就都可以使用。

生活联想: U盘、充电器、夜读灯等各种设备只要有USB类型的接口,就一定可以在任何有USB接口的电脑上使用,这种USB接口就相当于一个接口

Java理解:接口就是多个类的公共规范。

接口是一种引用数据类型,其中最重要的内容就是其中的抽象方法

3.2 接口的定义和基本使用

3.2.1 接口定义的基本格式

格式: public interface 接口名称{ }

**备注:**换成了关键字interface之后,编译生成的字节码文件仍然是:.java—>.class

如果是Java7,那么接口当中的内容可以包含:
1.常量
2.抽象方法

如果是Java8,还可以额外包含有:
3.默认方法
4.静态方法

如果是Java9,还可以额外包含有:
5.私有方法

3.2.2 接口的抽象方法定义

在任何版本的Java当中,接口都可以定义抽象方法:

格式:
public abstract 返回值类型 方法名称(参数列表);

注意:
1.接口当中的抽象方法,修饰符必须是固定的两个关键字public abstract
2.public和abstract这两个关键字修饰符,可以省略其中任何一个单词,也可以两个单词都省略,但是编译器依然会默认是public abstract
3.方法的三要素可以随意定义

//	定义一个接口
public Interface MyInterface{
	//	这是一个抽象方法
	public abstract void methodAbs1();

	//	这也是一个抽象方法
	abstract void methodAbs2();

	//	这也是一个抽象方法
	public void methodAbs3();

	//	这也是一个抽象方法
	void methodAbs4();
}

3.2.3 接口的抽象方法使用

接口使用步骤:
1.接口不能直接使用,必须有一个 “实现类”来“实现接口”
格式:

public class 实现类名称 implements 接口名称{
	//	...
}

2.接口的实现类必须覆盖重写(实现)接口中所有的抽象方法
实现:去掉abstract关键字,再加上方法体大括号。
3.创建实现类的对象,进行使用

注意事项:
1.对比接口中的抽象方法,接口中的抽象方法格式中的public也可以省略,但是和接口中的抽象方法一样,即使省略了,这里编译器依然默认修饰符是public,而若写上也一定要写public,不能是default,protected,private等
2.如果实现类没有重写接口当中所有的抽象方法,那么实现类就好比继承了一些接口当中的抽象方法,此时这个所谓的接口实现类必须是一个抽象类。

//	定义一个接口
public Interface MyInterface{
	//	这是一个抽象方法
	public abstract void methodAbs1();

	//	这也是一个抽象方法
	abstract void methodAbs2();

	//	这也是一个抽象方法
	public void methodAbs3();

	//	这也是一个抽象方法
	void methodAbs4();
}

//	创建接口的实现类
public class MyInterfaceImpl implements MyInterface{
	@Override
	public void methodAbs1(){
		System.out.println("这是第一个方法");
	}

	@Override
	public void methodAbs2(){
		System.out.println("这是第二个方法");
	}

	@Override
	public void methodAbs3(){
		System.out.println("这是第三个方法");
	}

	@Override
	public void methodAbs4(){
		System.out.println("这是第四个方法");
	}
}

//	定义测试类
public class Demo01Interface{
	public void main(Stingr[] args){
		//	错误写法,不能直接new接口对象使用
//		MyInterface impl= new MyInterface();

		//	创建实现类的对象使用
		MyInterfaceImpl impl= new MyInterfaceImpl();
		impl.methodAbs1();				
		impl.methodAbs2();
	}
}

3.2.4 接口的默认方法定义

从Java8开始,接口里允许定义默认方法
格式:

public default 返回值类型 (参数列表){
	//	方法体
}

接口中默认方法的意义:解决接口升级的问题。
备注: 接口当中的默认方法会被实现类所继承

举例说明默认方法的意义如下:

//	定义接口
public interface MyInterface{
	//	抽象方法
	public abstract void methodAbs();

	//	新添加了一个抽象方法
	public abstract void methodAbs2();
}

//	定义实现类MyInterfaceDefaultA 
public class MyInterfaceDefaultA implements MyInterface{
	@Override
	public void methodAbs(){
		System.out.println("实现了抽象方法AA");
	}
}

//	定义实现类MyInterfaceDefaultB
public class MyInterfaceDefaultB implements MyInterface{
	@Override
	public void methodAbs{
		System.out.println("实现了抽象方法BBB");
	}
}

在上面代码块中,编译器一定会报错,因为接口当中添加了新的抽象方法methodAbs2,但是已经投入使用的两个实现类MyInterfaceDefaultA 和MyInterfaceDefaultB当中都没有对这个新的抽象方法methodAbs2进行重写,而此时这两个实现类又不是抽象类,故会报错。而如果再在MyInterfaceDefaultA 和MyInterfaceDefaultB两个类当中重写methodAbs2,既浪费时间,也有可能会使代码产生bug。默认方法的出现,就是为了解决如上情况下的接口升级问题

3.2.5 接口的默认方法使用

用默认方法对3.2.3中所示问题代码块进行修复

//	定义接口
public interface MyInterface{
	//	抽象方法
	public abstract void methodAbs();

	//	新添加了一个抽象方法
//	public abstract void methodAbs2();

	//	新添加的方法,改成默认方法
	public default void methodDefault(){
		System.out.println("这是新添加的默认方法");
	}
}

//	定义实现类MyInterfaceDefaultA 
public class MyInterfaceDefaultA implements MyInterface{
	@Override
	public void methodAbs(){
		System.out.println("实现了抽象方法AA");
	}
}

//	定义实现类MyInterfaceDefaultB
public class MyInterfaceDefaultB implements MyInterface{
	@Override
	public void methodAbs{
		System.out.println("实现了抽象方法BBB");
	}
}

//	定义测试类
public class Demo02Interface{
	public static void main(String[] args){
		//	创建了实例对象
		MyInterfaceDefaultA a = new MyInterfaceDefaultA() ;
		a.methodAbs();	//	调用抽象方法,实际运行的是右侧的实现类
		
		//	调用默认方法,如果实现类当中没有,会向上查找接口的
		a.methodDefault();	
		System.out.println("=================");

		MyInterfaceDefaultB b = new MyInterfaceDefaultB() ;
		b.methodAbs();
		b.methodDefault();
		
	}
}

注意:
1.接口的默认方法,可以通过接口的实现类对象,直接调用。
2.接口的默认方法,也可以被接口的实现类进行覆盖重写
如:

//	定义接口
public interface MyInterface{
	//	抽象方法
	public abstract void methodAbs();

	//	新添加了一个抽象方法
//	public abstract void methodAbs2();

	//	新添加的方法,改成默认方法
	public default void methodDefault(){
		System.out.println("这是新添加的默认方法");
	}
}

//	定义实现类MyInterfaceDefaultA 
public class MyInterfaceDefaultA implements MyInterface{
	@Override
	public void methodAbs(){
		System.out.println("实现了抽象方法AA");
	}
}

//	定义实现类MyInterfaceDefaultB
public class MyInterfaceDefaultB implements MyInterface{
	@Override
	public void methodAbs{
		System.out.println("实现了抽象方法BBB");
	}

	
	//	重写接口当中的默认方法
	public void methodDefault(){
		System.out.println("实现类B覆盖重写了接口当中的默认方法")
	}
}

//	定义测试类
public class Demo02Interface{
	public static void main(String[] args){
		//	创建了实例对象
		MyInterfaceDefaultA a = new MyInterfaceDefaultA() ;
		a.methodAbs();	//	调用抽象方法,实际运行的是右侧的实现类
		
		//	调用默认方法,如果实现类当中没有,会向上查找接口的
		a.methodDefault();	
		System.out.println("=================");

		MyInterfaceDefaultB b = new MyInterfaceDefaultB() ;
		b.methodAbs();
		b.methodDefault();	//	实现类B覆盖重写了接口的默认方法
		
	}

3.2.6 接口的静态方法定义

从Java 8开始,接口当中允许定义静态方法。
格式:
public static 返回值类型 方法名称(参数列表){
方法体
}
提示:就是将abstract或者default换成static即可,带上方法体

3.2.7 接口的静态方法使用

//	定义一个接口
public interface MyInterfaceStatic{
	public static void methodStatic(){
		System.out.println("这是接口的静态方法!");
	}
}

//	定义一个实现类
public class MyInterfaceImpl implements MyInterfaceStatic{
	
}
public class Demo03Interface{
	public static void main(Srtring[] args){
		//	创建一个实现类对象
		MyInterfaceImpl impl = new MyInterfaceImpl();
		//	错误写法
//		impl.methodSraruc

		//	直接通过接口名称调用静态方法
		MyInterfaceStatic.methodStatic();
	}
}

注意事项:
1.不能通过接口实现类对象来调用接口当中的静态方法
2.正确用法是:通过接口名称.静态方法名(参数)

3.2.8 接口的私有方法(用来解决默认方法、静态方法之间代码重复的问题)

问题描述:
我们需要抽取一个公共方法,用来解决两个默认方法之间重复代码的问题,但是这个公共方法不应该让实现类使用,应该是私有化的。

解决方案:
从Java 9开始,接口中允许定义私有方法
1.普通私有方法,解决多个默认方法之间重复代码问题
格式:

private 返回值类型 方法名称(参数列表){
	//	方法体
}

2.静态私有方法,解决多个静态方法之间重复代码问题
格式:

private static 返回值类型 方法名称(参数列表){
	//	方法体
}

如:
普通私有方法

public interface MyInterfacePrivateA{
	public deafult void methodDefault1(){
		System.out.println("默认方法1");
		methodCommon();
	}

	public deafult void methodDefault2(){
		System.out.println("默认方法2");
		methodCommon();
	}

	private deafult void methodCommon(){
		System.out.println("AAA");
		System.out.println("BBB");
		System.out.println("CCC");
	}
}


静态私有方法

public interface MyInterfacePrivateA{
	public staticvoid methodStatic1(){
		System.out.println("静态方法1");
		methodStaticCommon();
	}

	public staticvoid methodStatic2(){
		System.out.println("静态方法2");
		methodStaticCommon();
	}

	private staticvoid methodStaticCommon(){
		System.out.println("AAA");
		System.out.println("BBB");
		System.out.println("CCC");
	}
}

3.2.9 接口的常量定义和使用

接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】

定义格式;

public static final 数据类型 常量名称 = 数据值;

使用格式:

接口名称.常量名称

注意:
1.一旦使用final关键字进行修饰,说明不可改变。
2.接口当中的常量,可以省略public static final,注意,即使不写,编译器也默认是这样的
3.接口当中的常量,必须进行赋值,不能不赋值。这不像成员变量,是不会自动赋上默认值的。
4.接口当中的常量名称,应该使用完全大写的字母,用下划线进行分割。

代码如下:

//	定义接口
public interface MyInterfaceConst{
	//	这其实就是一个常量,一旦赋值,无法进行修改
	public static final int NUM_OF_MY_CLASS= 10;
}

//	定义实现类
public class MyInterfaceConstImpl{
	
}

//	定义测试类
public class Demo05Interface{
	public static void main(Stringp[] args){
		System.out.println("MyInterface.num");
	}
}

3.3 接口的内容小结

在Java 9+的版本中,接口的内容可以有:
下面笔记中其中带[]部分意思是可以省略不写,编译器默认为[]中的值

1.成员变量其实是常量,格式:
[public] [static] [final] 数据类型 常量名称 = 数据值;
注意:
	常量必须进行赋值,而且一旦赋值将无法再进行改变
	常量命名应该全用大写字母表示,单词之间用下划线进行分割

2.接口中最重要的就是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表);
注意:实现类必须覆盖重写接口当中所有的抽象方法,否则实现类必须是抽象类

3.从Java8开始,接口允许定义默认方法,格式:
[public] default 返回值类型 方法名称(参数列表){
	方法体
}
注意:默认方法也也会被实现类继承,同时也可以被实现类覆盖重写,

4.从Java 8开始,接口里允许定义静态方法,格式:
[public] static 返回值类型 方法名称(参数列表){
	方法体
}

5.从Java 9开始,接口里允许定义私有方法,格式:
普通私有方法:private 返回值类型 方法名称(参数列表){
	方法体
}
静态私有方法:private static 返回值类型 方法名称(参数列表){
	方法体
}
注意:private的方法只有接口自己才能调用,不能被实现类或者其他人调用

3.4 接口的注意事项

使用接口的时候,需要注意:

1.接口是没有静态代码块或者构造方法的,但是抽象类当中可以有构造方法,且抽象类的构造方法是为了其子类在构造方法中用super()进行调用来初始化变量用的
2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
格式:
public class NyInterfaceImpl implements MyInterfaceA,MyInterfaceB{
    //  覆盖重写所有抽象方法
}
3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
4.如果实现类没有覆盖重写所有接口当中的所有的抽象方法,那么实现类就必须是一个抽象类。
【5.】如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
【6.】一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,【优先用父类当中的方法。】

3.5 类与接口的关系

关系如下:
1.类与类之间是单继承的。一个类的直接父类只有一个。
2.类与接口之间是多实现的。一个类可以实现多个接口。
3.接口与接口之间是多继承的。

注意事项:
1.多个父类接口之间的抽象方法如果冲突,因为没有具体的方法体,所以没关系
2.多个父类接口之间的默认方法如果冲突,那么子接口必须进行默认方法的覆盖重写。【而且必须带着default关键字,原因在于接口当中的deafult关键字是不能省略的】

//	定义接口MyInterfaceA
public interface MyInterfaceA{
	public abstract void methodA();
	public abstract void methodCommon();
	public deafult void methodDefault(){
		System.out.println("AAA");
	}
}

//	定义接口MyInterfaceB
public interface MyInterfaceB{
	public abstract void methodB();
	public abstract void methodCommon();
	public deafult void methodDefault(){
		System.out.println("BBB");
	}	
}

//	定义子接口MyInterface,这个子接口当中共有4个抽相方法
//	methodA来源于接口A
//	methodB来源于接口B
//	methodCommon来源于接口A和接口B
//	method来源于我自己
public Interface MyInterface extends MyInterfaceA,MyInterfaceB{
	public abstract void method();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值