学习目标:面向对象进阶
学习内容:包、final、权限修饰符、代码块、抽象类、接口
学习时间:
下午 3 点-下午 6 点
学习产出:
什么的包?
包就是文件夹。用来管理各种不同功能的Java类,方便后期代码维护。
包名的规则:公司域名反写+包的作用,需要全部英文小写,见名知意。
什么是全类包?
包名+类名
使用其他类的规则
使用同一个包中的类时,不需要导包。
使用java.lang包中的类时,不需要导包。
其他情况都需要导包。
如果同时使用两个包中的同名类,需要用全类名。
final
final修饰方法:表明该方法是最终方法,不能被重写。
final修饰类:表明该类是最终类,不能被继承。
final修饰变量:叫做常量,只能被赋值一次。
此时就可发现父类中的show()方法被final修饰,子类无法重写父类中的方法。
此代码中就可发现被final修饰的变量,不能被修改。
常量:
实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性。
常量的命名规范:
单个单词:全部大写。
多个单词:全部大写,单词之间用下划线隔开。
细节:
final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,对象内部的可以改变。
public class Test {public static void main(String[] args) {//创建对象final Student S = new Student("旭哥", 23);//记录的地址值不能发生改变,内部的属性值还是可以改变的// S = new Student();S.setName("蛋姐");S.setAge(21);System.out.println(S.getName() + ", " + S.getAge());//数组final int[] ARR = {1, 2, 3, 4, 5};ARR[0] = 10;ARR[1] = 20;//遍历数组for (int i = 0; i < ARR.length; i++) {System.out.println(ARR[i]);}}
}
运行结果:
蛋姐, 21
10
20
3
4
5
final应用场景
在之前我们写过一个学生管理系统,在代码中有一段代码实现的是目录,为了让代码阅读性更强,可将switch循环中的case选项final私有化定义,可将数字命名为可读性更强的英文。
权限修饰符
权限修饰符:是用来控制一个成员能够被访问的范围的。
可以修饰成员变量,方法,构造方法,内部类。
权限修饰符的分类
有四种作用范围由小到大(private<空着不写<protected<public)
修饰符 | 同一个类中 | 同一个包中 其他类 | 不同包下的 子类 | 不同包下的 无关类 |
private | ||||
空着不写 | ||||
protected | ||||
public |
代码块
局部代码块: 局部代码块是在方法内部定义的,它的作用域仅限于该方法内。局部代码块通常用于定义方法内的控制流,例如条件语句(if-else)、循环(for、while)等。
public class Test {
public static void main(String[] args) {{int a = 10;System.out.println(a);}}
}
构造代码块:构造代码块是在类中定义的,它在类的构造函数之前执行。如果有多个构造函数,构造代码块会在每个构造函数执行之前运行。它用于初始化类的实例变量。
public class Student {private String name;private int age;{System.out.println("开始创建对象了");}public Student() {System.out.println("空参构造");}public Student(String name, int age) {System.out.println("有参构造");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 class Test {public static void main(String[] args) {//创建对象Student s=new Student();Student s2=new Student("旭哥",23);}
}
运行结果:
开始创建对象了
空参构造
开始创建对象了
有参构造
静态代码块:静态代码块是在类中定义的,它在类被加载到JVM时执行一次,且仅执行一次。它主要用于初始化类的静态变量。
public class Student {private String name;private int age;static {System.out.println("开始创建对象了");}public Student() {System.out.println("空参构造");}public Student(String name, int age) {System.out.println("有参构造");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 class Test {public static void main(String[] args) {//创建对象Student s=new Student();Student s2=new Student("旭哥",23);}
}
运行结果:
开始创建对象了
空参构造
有参构造
抽象类
抽象方法:将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样,所以,在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。
抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类。
抽象类和抽象方法的定义格式
抽象方法的定义格式:
public abstract 返回值类型 方法名(参数列表);
抽象类的定义格式:
public abstract class 类名
public abstract class Person {public abstract void work();
}
抽象类和抽象方法的注意事项
抽象类不能实例化。
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
可以有构造方法。
抽象类的子类:
要么重写抽象类中的所有抽象方法。
要么是抽象类。
练习:编写带有抽象类的标准Javabean类
青蛙frog 属性:名字,年龄 行为:吃虫子,喝水
狗Dog 属性:名字,年龄 行为:吃骨头,喝水
山羊Sheep 属性:名字,年龄 行为:吃草,喝水
public 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();public void drink(){System.out.println("动物在喝水");}
}
public class Dog extends Animal{public Dog() {}public Dog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println("狗在啃骨头");}
}
public class Frog extends Animal{public Frog() {}public Frog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println("青蛙在吃虫子");}
}
public class Sheep extends Animal{public Sheep() {}public Sheep(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println("山羊在吃草");}
}
public class Test {public static void main(String[] args) {Sheep s=new Sheep("喜羊羊",2);s.eat();s.drink();}
}
运行结果:
山羊在吃草
动物在喝水
接口
在Java中,接口(Interface)是一种引用类型,它定义了一组方法规范,这些方法规范可以由实现该接口的类来具体实现。接口是Java面向对象编程的核心概念之一,它提供了一种机制来实现抽象和多态。
接口的定义和使用
接口用关键字interface来定义
public interface 接口名{}
接口不能实例化
接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名{}
接口的子类(实现类)
要么重写接口中的所有抽象方法
要么是抽象类
注意1:接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements 接口名1,接口名2{}
注意2:实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements 接口名1,接口名2}
练习:编写带有接口和抽象类的标准Javabean类
青蛙 属性:名字,年龄 行为:吃虫子,蛙泳
狗 属性:名字,年龄 行为:吃骨头,狗刨
兔子 属性:名字,年龄 行为:吃胡萝卜
public 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();}
public interface Swim {public abstract void swim();
}
public class Dog extends Animal implements Swim{public Dog() {}public Dog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println("狗在啃骨头");}@Overridepublic void swim() {System.out.println("狗在狗刨");}
}
public class Frog extends Animal implements Swim{public Frog() {}public Frog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println("青蛙在吃虫子");}@Overridepublic void swim() {System.out.println("青蛙在蛙泳");}
}
public class Frog extends Animal implements Swim{public Frog() {}public Frog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println("青蛙在吃虫子");}@Overridepublic void swim() {System.out.println("青蛙在蛙泳");}
}
public class Test {public static void main(String[] args) {Rabbit s=new Rabbit("喜羊羊",2);System.out.println(s.getName()+","+s.getAge());s.eat();Dog d=new Dog("维鲁斯",3);System.out.println(d.getName()+","+d.getAge());d.eat();d.swim();}
}
运行结果:
喜羊羊,2
兔子在吃胡萝卜
维鲁斯,3
狗在啃骨头
狗在狗刨
接口中成员的特点
成员变量
只能是常量
默认修饰符:public static final
构造方法
没有
成员方法
只能是抽象方法
默认修饰符:public abstract
JDK7以前:接口中只能定义抽象方法。
JDK8的新特性:接口中可以定义有方法体的方法。
JDK9的新特性:接口中可以定义私有方法。
接口和类之间的关系
类和类的关系
继承关系,只能单继承,不能多继承但是可以多层继承
类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
接口和接口的关系
继承关系,可以单继承,也可以多继承
练习:编写带有接口和抽象类的标准Javabean类
我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。
为了出国交流,跟乒乓球相关的人员都需要学习英语。
请用所有知识分析,在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口?
乒乓球运动员:姓名,年龄,学打乒乓球,说英语
篮球运动员:姓名,年龄,学打篮球
乒乓球教练:姓名,年龄,教打乒乓球,说英语
篮球教练:姓名,年龄,教打篮球
public abstract class Person {private String name;private int age;public Person() {}public Person(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 interface English {public abstract void speakElish();
}
public class baskerballSporter extends Sporter{public baskerballSporter() {}public baskerballSporter(String name, int age) {super(name, age);}@Overridepublic void study() {System.out.println("篮球运动员在学习打篮球");}
}
public class basketballCoach extends Coach{public basketballCoach() {}public basketballCoach(String name, int age) {super(name, age);}@Overridepublic void teach() {System.out.println("篮球教练在教打篮球");}
}
public abstract class Coach extends Person{public Coach() {}public Coach(String name, int age) {super(name, age);}public abstract void teach();
}
public class pingpongCoach extends Coach implements English{@Overridepublic void speakElish() {System.out.println("乒乓球教练在学习英语");}@Overridepublic void teach() {System.out.println("乒乓球教练在教打乒乓球");}
}
public class pingpongSporter extends Sporter implements English{public pingpongSporter() {}public pingpongSporter(String name, int age) {super(name, age);}@Overridepublic void speakElish() {System.out.println("乒乓球运动员在说英语");}@Overridepublic void study() {System.out.println("乒乓球运动员在学习打乒乓球");}
}
import a10demo2.Animal;public abstract class Sporter extends Person{public Sporter() {}public Sporter(String name, int age) {super(name, age);}public abstract void study();
}
public class Test {public static void main(String[] args) {pingpongSporter pps=new pingpongSporter("王楚钦",23);System.out.println(pps.getName()+", "+pps.getAge());pps.study();pps.speakElish();System.out.println("----------------------------");basketballCoach bbc=new basketballCoach("科比",41);System.out.println(bbc.getName()+", "+bbc.getAge());bbc.teach();}
}
运行结果:
王楚钦, 23
乒乓球运动员在学习打乒乓球
乒乓球运动员在说英语
----------------------------
科比, 41
篮球教练在教打篮球
JDK8以后接口中新增的方法
1、 允许在接口中定义默认方法,需要使用关键字 default修饰
作用:解决接口升级的问题
接口中默认方法的定义格式:
格式:public default 返回值类型 方法名(参数列表){}
范例:public default void show(){ }
接口中默认方法的注意事项:
默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字。
public可以省略,default不能省略。
如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写。
2、允许在接口中定义定义静态方法,需要用static修饰
接口中静态方法的定义格式:
格式:public static 返回值类型 方法名(参数列表){}
范例:public static void show(){ }
接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略
JDK9新增的方法
接口中私有方法的定义格式:
格式1:private 返回值类型 方法名(参数列表){}
范例1:private void show(){ }
格式2:private static 返回值类型 方法名(参数列表){}
范例2:private static void method(){ }
适配器设计模式
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
简单理解:设计模式就是各种套路。
适配器设计模式:解决接口与接口实现类之间的矛盾问题。