Java笔记day16
一、接口
1、接口的特点:
1)、接口使用关键字:interface表示
定义格式:interface 接口名{}
2)、类实现接口用
定义格式:class 类名 implements 接口名{}
3)、接口不能实例化
那么如何表示接口的实现呢?
使用多态的方式实现,有具体的子类进行实例化,其实这是多态的一种,接口多态
4)、接口子类的特点
如果子类是一个抽象类,那么可以不需要重写接口中的方法
如果子类是一个具体的类,必须要重写接口中所有抽象方法
5)、到目前为止,我们学过三种多态方式:
a、具体类中的多态 (最后才是这个)
b、抽象类中的多态 (其次是抽象多态)
c、接口中的多态 (是最常见的,接口开发)
6)、举例
查看代码
abstract class Animal{
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//定义一个接口,表示钻火圈
interface DrillFire{
public void zuanHuo();
}
//定义训练过具体的猫的类实现钻火圈接口
class TrainCat extends Cat implements DrillFire{
@Override
public void zuanHuo() {
System.out.println("猫跳着钻火圈");
}
}
//定义一个抽象类实现钻火圈接口
abstract class Demo implements DrillFire{
}
public class InterfaceDemo1 {
public static void main(String[] args) {
// DrillFire df = new DrillFire(); //报错,接口不能实例化
DrillFire df = new TrainCat();
}
}
2、接口成员的特点
接口成员的特点:
成员变量:
只能是常量,并且是静态的
它里面给成员变量的默认修饰符是public static final
建议:手动全部补齐
构造方法:
接口中没有构造方法
成员方法:
接口中的成员方法只能是抽象方法,没有方法体,连大括号都没有
它会自动补充修饰符:public abstract
建议:手动全部补齐
举例:
查看代码
interface Inter{
int a = 10; //它会自动补全为public static final int a = 10;
public static final int b = 20;
/*Inter(){}
Error:(20, 22) java: 接口抽象方法不能带有主体
public void fun(){
System.out.println("玩游戏"); Java:接口中的方法不能有主体
}*/
public void fun();
}
/*虽然接口中没有构造方法,但是多态初始化的时候要先初始化子类再初始化父类
这里其实继承了一个父类,java中所有的类都默认继承一个类:Object
每一个class都有Object作为超类
那么所有继承Object类的实现对象都实现了这个类中的方法
*/
class Demo1 extends Object implements Inter{
@Override
public void fun() {
System.out.println("玩游戏2");
}
}
public class InterfaceDemo2 {
public static void main(String[] args) {
Inter i = new Demo1();
//Error:(24, 10) java: 无法为最终变量a分配值
//i.a = 100;
System.out.println(i.a);
//System.out.println(Inter.a); 不报错,输出为10
}
}
3、接口、类之间的关系
类与类,类与接口,接口与接口之间的关系
类与类:
继承关系,只能进行单继承,不可以进行多继承,但是可以多层继承
类与接口:
实现关系,可以是单实现,也可也一次实现多个接口,也可以在继承一个类的同时,实现多个接口。
接口与接口之间的关系:
继承关系,可以单继承,也可以多继承。
class A{}
class B extends A{}
interface Inter3{}
interface Inter2{}
class C extends A implements Inter2, Inter3{}
interface Inter4 extends Inter2,Inter3{}
public class InterfaceDemo3 {
}
4、接口练习
/*猫狗案例,加入额外的跳高功能
分析:
猫:姓名,年龄,吃饭,睡觉
狗:姓名,年龄,吃饭,睡觉
由于猫和狗存在共性,所以我们提取出来到一个抽象类中
动物:姓名,年龄,吃饭(),睡觉()
猫:继承自动物
狗:继承自动物
由于跳高是一个额外的功能,不是动物特有的,所以我们利用接口的方式定义
接口:
跳高
部分的猫:实现接口
部分的狗:实现接口*/
查看代码
abstract class Animal3{
private String name;
private int gae;
public Animal3() {
}
public Animal3(String name, int gae) {
this.name = name;
this.gae = gae;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGae() {
return gae;
}
public void setGae(int gae) {
this.gae = gae;
}
//抽象方法
public abstract void eat();
public abstract void sleep();
}
class Cat3 extends Animal3{
public Cat3() {
}
public Cat3(String name, int gae) {
super(name, gae);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
}
class Dog3 extends Animal3{
public Dog3() {
}
public Dog3(String name, int gae) {
super(name, gae);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
//定义跳高的接口
interface Jump{
public abstract void jump();
}
//定义部分会跳高的猫
class JumpCat extends Cat3 implements Jump{
public JumpCat() {
}
public JumpCat(String name, int gae) {
super(name, gae);
}
@Override
public void jump() {
System.out.println("猫跳高");
}
}
//定义部分会跳高的狗
class JumpDog extends Dog3 implements Jump{
public JumpDog() {
}
public JumpDog(String name, int gae) {
super(name, gae);
}
@Override
public void jump() {
System.out.println("狗跳高");
}
}
public class InterfaceTest1 {
public static void main(String[] args) {
//创建不会跳高的狗
Animal3 a1 = new Dog3("小白",2);
a1.eat();
a1.sleep();
//创建一个会跳高的狗
Dog3 d1 = new JumpDog("大黄",3);
d1.eat();
d1.sleep();
((JumpDog) d1).jump();
Jump j1 = new JumpDog("小黑",4);
((JumpDog) j1).eat();
((JumpDog) j1).sleep();
j1.jump();
}
}
二、形式参数和返回值类型问题
1、形式参数:
基本数据类型:byte、short、int、long、float、double、char、boolean(略)
引用数据类型:类、抽象类、接口、(数组略)
1)、类:当类作为方法的形式参数的时候,实际上需要的该类的对象
查看代码
abstract class Animal3{
private String name;
private int gae;
public Animal3() {
}
public Animal3(String name, int gae) {
this.name = name;
this.gae = gae;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGae() {
return gae;
}
public void setGae(int gae) {
this.gae = gae;
}
//抽象方法
public abstract void eat();
public abstract void sleep();
}
class Cat3 extends Animal3{
public Cat3() {
}
public Cat3(String name, int gae) {
super(name, gae);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
}
class Dog3 extends Animal3{
public Dog3() {
}
public Dog3(String name, int gae) {
super(name, gae);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
//定义跳高的接口
interface Jump{
public abstract void jump();
}
//定义部分会跳高的猫
class JumpCat extends Cat3 implements Jump{
public JumpCat() {
}
public JumpCat(String name, int gae) {
super(name, gae);
}
@Override
public void jump() {
System.out.println("猫跳高");
}
}
//定义部分会跳高的狗
class JumpDog extends Dog3 implements Jump{
public JumpDog() {
}
public JumpDog(String name, int gae) {
super(name, gae);
}
@Override
public void jump() {
System.out.println("狗跳高");
}
}
public class InterfaceTest1 {
public static void main(String[] args) {
//创建不会跳高的狗
Animal3 a1 = new Dog3("小白",2);
a1.eat();
a1.sleep();
//创建一个会跳高的狗
Dog3 d1 = new JumpDog("大黄",3);
d1.eat();
d1.sleep();
((JumpDog) d1).jump();
Jump j1 = new JumpDog("小黑",4);
((JumpDog) j1).eat();
((JumpDog) j1).sleep();
j1.jump();
}
}
2)、抽象类:当抽象类作为方法的形式参数的时候,因为不能实例化所以使用多态的形式创建对象
abstract class Person{
public abstract void study();
}
class Student2 extends Person {
@Override
public void study() {
System.out.println("好好学习天天向上");
}
}
class PersonDemo{
//当一个抽象方法作为形式参数类型的时候,实际上需要的是子类实现对象的地址值,利用多态的性质
public void fun(Person person){ //Person person = new Student2()
person.study();
}
}
public class PersonTest {
public static void main(String[] args) {
/*
不使用匿名对象的时候
PersonDemo personDemo = new PersonDemo();
Person person = new Student2()
personDemo.fun(person);
*/
//匿名对象
PersonDemo personDemo = new PersonDemo();
personDemo.fun(new Student2());
}
}
3)、接口:当接口作为方法的形式参数的时候,使用接口多态的形式创建对象
查看代码
interface Person2{
public abstract void study();
}
class Teacher implements Person2{
@Override
public void study() {
System.out.println("好好学习天天向上");
}
}
class TeacherDemo{
//当接口作为形式参数传入的时候,实际上需要的是该接口的实现类的对象的地址值,利用接口多态的性质
public void fun(Person2 person2){ // Person2 person2 = new Teacher();
person2.study();
}
}
public class TeacherTest {
public static void main(String[] args) {
/*
不使用匿名对象的时候
TeacherDemo td = new TeacherDemo();
Person2 person2 = new Teacher();
td.fun(person2);
*/
//匿名对象
TeacherDemo td = new TeacherDemo();
td.fun(new Teacher());
}
}
2、返回值问题
基本数据类型:byte、short、int、long、float、double、char、boolean(略)
引用数据类型:类、抽象类、接口、(数组略)
1)、类:当类作为方法的返回值的时候,实际上返回的是该的对象
查看代码
class Student3{
public void study(){
System.out.println("好好学习天天向上");
}
}
class StudentDemo3{
public Student3 fun(){
//return new Student3();
//当类作为方法的返回值类型的时候,返回是实际上是该类对象的地址值
Student3 s = new Student3();
return s;
}
}
public class StudentTest2 {
public static void main(String[] args) {
StudentDemo3 sd = new StudentDemo3(); //先new一个StudentDemo3的对象调用方法,
Student3 s = sd.fun(); //把调用方法的返回值赋给s,再通过s调用fun()方法
s.study(); //这里也可以写成(new StudentDemo3()).fun().study()
}
}
2)、抽象类:当抽象类作为方法的返回值的时候,需要的是该抽象类子类的对象
查看代码
abstract class Person3{
public abstract void study();
}
class Doctor extends Person3{
@Override
public void study() {
System.out.println("医生学习医术");
}
}
class PersonDemo3{
public Person3 getPerson(){
//抽象类不能实例化
Person3 person3 = new Doctor();
return person3;
}
}
public class PersonTest2 {
public static void main(String[] args) {
PersonDemo3 pd3 = new PersonDemo3();
Person3 person3 = pd3.getPerson(); //Person3 person3 = new Doctor();
person3.study();
}
}
3)、接口:当接口作为方法的返回值的时候,需要的是实现该接口的类的对象
查看代码
interface PlayGame{
public abstract void playLoL();
}
class Teacher2 implements PlayGame{
@Override
public void playLoL() {
System.out.println("老师打英雄联盟");
}
}
class TeacherDemo2{
public PlayGame getPlayGame(){
PlayGame pg = new Teacher2();
return pg;
}
}
public class TeacherTest2 {
public static void main(String[] args) {
/*一般写法
TeacherDemo2 td2 = new TeacherDemo2();
PlayGame pg = td2.getPlayGame(); //PlayGame pg = new Teacher2();
pg.playLoL();
*/
//链式编程(后面大家会学习scala,spark,flink)
new TeacherDemo2().getPlayGame().playLoL();
}
}
三、导包以及权限修饰符
1、导包
package:到达路径为包
import:最终导的是一个类
package:放在java文件的第一行,表示将来编译运行的时候路径
import:放在package和class之间的
class:是最后出现的,表示我们要写的程序代码
2、权限修饰符
权限修饰符 | 同一类下 | 同一包子类,其他类 | 不同包子类 | 不同包其他类 |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
默认 | √ | √ | × | × |
private | √ | × | × | × |
3、类及其组成可以用的修饰符
修饰符:
访问权限修饰符:public,protected,默认,private
状态修饰符:static,final
抽象修饰符:abstract
注:下面没写的修饰符就是不能修饰
类:
访问权限修饰符:默认,public(可以修饰,但是同一个Java文件下只能有一个)
状态修饰符:final
抽象修饰符:abstract
成员变量:
访问权限修饰符:默认,public, protected, private
状态修饰符:static, final(可以修饰,需要在构造方法之前赋值)
构造方法:
访问权限修饰符:默认,public, protected, private
成员方法:
访问权限修饰符:public, 默认,protected,private
状态修饰符:static, final
抽象修饰符:abstract(可以修饰,但是不能由有方法体,且只能在抽象类中使用抽象方法)
常见的修饰符组合:
成员变量:public static final 在接口中遇见
成员方法:
1、public abstract
2、public static
3、public final
将来做开发时,除了封装必须使用private除外,如果不知道使用谁,就用public